国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄

這篇具有很好參考價(jià)值的文章主要介紹了Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

作者:彭泰強(qiáng)

1 評(píng)價(jià)指標(biāo)&優(yōu)化成果

要做性能優(yōu)化,首先得知道性能怎么度量、怎么表示。因?yàn)樾阅苁且粋€(gè)很抽象的詞,我們必須把它量化、可視化。那么,因?yàn)槭荱I組件優(yōu)化,我首先選用了GPU呈現(xiàn)模式分析這一工具。

在手機(jī)上的開(kāi)發(fā)者模式里可以開(kāi)啟GPU呈現(xiàn)(渲染)模式分析這一工具,有的系統(tǒng)也把它叫hwui什么什么的,自己找一下,開(kāi)啟后,屏幕上會(huì)展示一個(gè)直方圖,直觀來(lái)看就是有很多豎條,每一個(gè)豎條代表一個(gè)渲染幀,這些豎條的高度代表渲染的每個(gè)階段渲染前一幀所用的相對(duì)時(shí)間。屏幕底端會(huì)有根綠線,代表的就是16.6ms,而一幀的渲染時(shí)間超出這個(gè)綠線,就有可能發(fā)生所謂的掉幀。再說(shuō)簡(jiǎn)單點(diǎn),每個(gè)豎條越低越好。

這些信息大致可以告訴我們:

  • 1、當(dāng)前渲染一幀的時(shí)間是否在合理的范圍內(nèi)。
  • 2、渲染的每個(gè)階段的耗時(shí),從而了解應(yīng)該優(yōu)化哪些方面來(lái)提高應(yīng)用的渲染性能。

關(guān)于這個(gè)工具就簡(jiǎn)單介紹到這里,更詳細(xì)的內(nèi)容可以自己看 官方文檔(官方文檔同樣也給出了對(duì)應(yīng)顏色豎條的排查問(wèn)題的思路)。

那么,我們回到翻頁(yè)組件。在之前發(fā)布的v1.0.1版本中,繪制流程是先計(jì)算所有點(diǎn),構(gòu)建Path,然后老老實(shí)實(shí)的一個(gè)圖層一個(gè)圖層繪制(例如,先繪制最底層的下一頁(yè)內(nèi)容,再繪制翻起來(lái)的這一頁(yè)內(nèi)容,再繪制陰影,再繪制頁(yè)面光澤等等...),現(xiàn)在我們打開(kāi)工具,看一下,這一看簡(jiǎn)直嚇了一跳,如左圖所示。最底下的綠線是16.6ms,然而,一翻頁(yè)之后,滿屏的豎條出現(xiàn)了,這高度也太嚇人了,遠(yuǎn)超合理的范圍,每一幀都花費(fèi)了很多時(shí)間,相當(dāng)于嚴(yán)重掉幀了。這下,不得不開(kāi)始優(yōu)化了。

那么,經(jīng)過(guò)這一周的思考和優(yōu)化,最后的結(jié)果就是右圖了,雖然還有好幾個(gè)可以優(yōu)化的大點(diǎn),但是我懶得寫(xiě)了,就先優(yōu)化到這里吧,定為v1.1.0版本。

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

接下來(lái)講一下優(yōu)化的思路和過(guò)程供大家參考,如果有不足之處也歡迎討論和批評(píng)指正。

2 思考

那么現(xiàn)在知道了性能問(wèn)題很糟糕,想要優(yōu)化,首先得搞清楚能優(yōu)化哪些方面,然后是怎么去優(yōu)化,下面是一些思考的角度。

注:本節(jié)僅僅是思考的過(guò)程,具體的實(shí)現(xiàn)細(xì)節(jié)方案之類的在后面討論,甚至,可能有一些本節(jié)列出的優(yōu)化角度經(jīng)驗(yàn)證后會(huì)是不可實(shí)現(xiàn)或?qū)崿F(xiàn)成本巨大的,最后放棄了。

2.1 Compose

這個(gè)UI組件首先是一個(gè)Jetpack Compose編寫(xiě)的組件,那么Compose的部分是否存在能優(yōu)化的大項(xiàng)?

1. 是否存在過(guò)度重組

關(guān)于Compose,首先能想到的一點(diǎn)就是重組次數(shù)是否合理,即,是否存在過(guò)度重組、不必要的重組的情況。其實(shí)在之前的第一版代碼實(shí)現(xiàn)時(shí),我就考慮了這一點(diǎn),使用官方的Layout Inspector(默認(rèn)在Android Studio的右下角),可以去檢查每個(gè)@Composable重組的情況,確認(rèn)他們是否合理,所幸,并沒(méi)有發(fā)生過(guò)度重組的情況。這個(gè)優(yōu)化點(diǎn)直接跳過(guò)。

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

2. 降低重組頻率、提高重組速度

現(xiàn)在的事實(shí)是:由于手指每次哪怕移動(dòng)一丁點(diǎn),都會(huì)觸發(fā)手勢(shì)監(jiān)聽(tīng)(從log看我的小破測(cè)試機(jī)大概是10-12ms會(huì)觸發(fā)一次onDrag回調(diào)),進(jìn)而觸發(fā)重組,然后重新進(jìn)行屏幕上所有點(diǎn)的計(jì)算(而這個(gè)計(jì)算是很耗時(shí)的),計(jì)算完后,再根據(jù)計(jì)算結(jié)果調(diào)用canvas API進(jìn)行繪制。

基于上面的這個(gè)事實(shí)流程,簡(jiǎn)單思考過(guò)后,便能發(fā)現(xiàn)幾個(gè)也許可以優(yōu)化的角度:

  • 耗時(shí)計(jì)算能否放到子線程?那么耗時(shí)計(jì)算放到子線程計(jì)算完后,如何把結(jié)果給回Compose觸發(fā)UI更新?如果這個(gè)想法可以實(shí)現(xiàn),那么就可以提高重組的速度。
  • onDrag的回調(diào)觸發(fā)是否過(guò)于頻繁了?也許沒(méi)必要這么頻繁地觸發(fā)手勢(shì)監(jiān)聽(tīng),也就是說(shuō),并非每次onDrag都去觸發(fā)耗時(shí)計(jì)算,而是有一個(gè)頻率上的降低,保證UI看起來(lái)還是連貫的即可。這樣可以直接降低重組頻率。

3、去掉重組中的多余代碼

這一點(diǎn)是很trick的一個(gè)點(diǎn),例如,如果你在一個(gè)可能會(huì)頻繁重組的@Composable塊中輸出了Log,甚至多條Log,一方面確實(shí)會(huì)影響重組的性能,另一方面,如果這些Log中含有State變量,甚至可能會(huì)導(dǎo)致不必要的重組發(fā)生。

因此,如果非要想在@Composable塊中用Log調(diào)試,請(qǐng)?jiān)谕瓿删幋a后把這些Log都刪掉或者注釋掉。

關(guān)于Compose部分,能優(yōu)化的點(diǎn)我暫時(shí)就想到這些。

2.2 Bitmap

下一個(gè)方向是Bitmap方向,因?yàn)檎麄€(gè)翻頁(yè)組件,不論是算法(例如扭曲算法、曲線邊緣算法)還是Compose側(cè)實(shí)現(xiàn)都與Bitmap有關(guān),那么肯定得好好盤(pán)一盤(pán)這個(gè)Bitmap相關(guān)的部分。

2.2.1 組件中有關(guān)Bitmap的部分

這里先簡(jiǎn)單提一下組件實(shí)現(xiàn)中涉及到Bitmap的部分,以免不知道后面的優(yōu)化部分在說(shuō)什么。

首先,為什么會(huì)用到Bitmap?因?yàn)橛幸粋€(gè)需求是要實(shí)現(xiàn)類似紙張翻起來(lái)的一個(gè)文字扭曲效果,如下圖右側(cè)所示。

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

這個(gè)扭曲的實(shí)現(xiàn)思路用到了Canvas的drawBitmapMesh方法,也就是說(shuō),組件要把任意自定義的@Composable內(nèi)容進(jìn)行“截屏”操作,繪制成一張Bitmap,然后對(duì)這張Bitmap調(diào)用drawBitmapMesh進(jìn)行扭曲(既然是“截屏”操作,這也就解釋了為什么組件支持顯示任意的非動(dòng)態(tài)的內(nèi)容)。

在每次頁(yè)面內(nèi)容發(fā)生改變(例如當(dāng)前頁(yè)面內(nèi)容有變化、或者翻頁(yè)了)時(shí),就要去重繪前一頁(yè)、當(dāng)前頁(yè)、后一頁(yè)這三張Bitmap,且這三張Bitmap都是同樣大小的,與組件大小一樣大。

組件中涉及Bitmap的部分就先說(shuō)到這里,接下來(lái)回到我們的優(yōu)化思路中。

1、Bitmap的Config

那么,首先想到的是與項(xiàng)目無(wú)關(guān)的,Bitmap本身的優(yōu)化,例如一些常見(jiàn)的思路:

  • 加載圖片時(shí),對(duì)圖片進(jìn)行下采樣,減少加載的消耗,減少內(nèi)存占用,且提高加載速度(這個(gè)思路我沒(méi)有去管,因?yàn)榻M件實(shí)現(xiàn)中,Bitmap都是由截屏操作生成的,就是屏幕大小,但其實(shí)感覺(jué)可能可以針對(duì)不同尺寸的屏幕去做適配?因?yàn)槿绻聊缓芨咔?,生成的圖片也會(huì)很大,但實(shí)際上也許不需要那么大。而因?yàn)槲覜](méi)有測(cè)試設(shè)備(我的設(shè)備是一個(gè)720*1600的低端機(jī)),所以這一塊暫時(shí)沒(méi)去管。)
  • 既然是翻頁(yè)組件,那頁(yè)的紙張肯定是不透明的,既然如此,在截屏生成Bitmap時(shí),我們就不需要有透明度的Bitmap了,也就是Bitmap其實(shí)可以采用RGB565格式,而不用ARGB8888,這樣,內(nèi)存占用直接減小了一半,后續(xù)對(duì)Bitmap的操作速度也會(huì)快些。
  • 關(guān)于下采樣,類似地,在drawBitmapMesh時(shí),會(huì)需要設(shè)置mesh的格點(diǎn)數(shù),同樣,減少這個(gè)格點(diǎn)數(shù)也會(huì)導(dǎo)致性能提高。

2、Bitmap的復(fù)用

既然組件后續(xù)繪制需要涉及到的Bitmap的數(shù)量是固定的,就只有3張(前一頁(yè)、當(dāng)前頁(yè)、后一頁(yè)),而且,實(shí)際的絕大部分場(chǎng)景下,翻頁(yè)組件的大小都是固定的,不會(huì)輕易變化,那么就可以想到這3張Bitmap其實(shí)可以復(fù)用,也就是繪制新的Bitmap時(shí)把新的像素直接覆蓋在原來(lái)Bitmap分配的內(nèi)存上,這樣就不用每次翻頁(yè)或者refresh頁(yè)面時(shí)都先recycle再重新create,只要組件大小不發(fā)生變化,就可以避免多余的內(nèi)存回收和再分配。

此外,既然說(shuō)到了復(fù)用,同樣也能聯(lián)想到一些其他的可復(fù)用的大對(duì)象,例如繪制時(shí)用到的Canvas和Path等,因?yàn)樗鼈兊膭?chuàng)建回收也是在native的,這樣可以減少創(chuàng)建和回收帶來(lái)的消耗。

2.3 繪制

作為一個(gè)UI組件,另一個(gè)思考方向就是UI組件的一些常見(jiàn)優(yōu)化點(diǎn)。

1、布局是否嵌套過(guò)深

如果組件的布局嵌套太深,肯定影響性能,但所幸這個(gè)組件并沒(méi)有這個(gè)情況(PTQBookPageViewInner中也只有一個(gè)Box和Canvas),所以這個(gè)優(yōu)化點(diǎn)直接跳過(guò)。

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

2、是否存在過(guò)度繪制

過(guò)度繪制就是指,由于代碼編寫(xiě)不當(dāng),導(dǎo)致同一個(gè)像素點(diǎn)被反復(fù)更新。我們只能看見(jiàn)最上面的圖層,因此可以去考慮是否存在大量的被掩蓋的區(qū)域,既然這些區(qū)域是不可見(jiàn)的,那它們本身就不應(yīng)該被繪制。

這里同樣有一個(gè)工具,系統(tǒng)自帶的,叫 調(diào)試GPU過(guò)度繪制,在開(kāi)發(fā)者選項(xiàng)中打開(kāi)這個(gè)工具,它就會(huì)在屏幕上顯示我們過(guò)度繪制的區(qū)域。

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

現(xiàn)在讓我們看看優(yōu)化前的區(qū)域(下左圖),一片紅,那么基本上可以確定了,這也是一個(gè)可優(yōu)化的大點(diǎn)。

在實(shí)際開(kāi)發(fā)時(shí),有一些過(guò)度繪制是無(wú)法避免的,因此我們要做的就是盡可能地減少過(guò)度繪制,在思考優(yōu)化方案過(guò)后,做到了下右圖的效果,減少了一些過(guò)度繪制,提高了性能。

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄,Android,性能優(yōu)化,移動(dòng)開(kāi)發(fā),android,ui,性能優(yōu)化,移動(dòng)開(kāi)發(fā),Framework

3、耗時(shí)的繪制

一些Canvas和Path的API可能會(huì)相對(duì)來(lái)說(shuō)比較耗時(shí),我們應(yīng)該盡可能減少此類API的調(diào)用

目前我能想到的可優(yōu)化的點(diǎn)和思路就是這些,下面開(kāi)始實(shí)現(xiàn)。

3 實(shí)現(xiàn)

一些細(xì)節(jié)就不提了,例如什么Path的復(fù)用之類的,本節(jié)就講一些主要的部分。

3.1 BitmapController優(yōu)化

這個(gè)部分主要的改動(dòng)是Bitmap的復(fù)用,以及Bitmap的create流程(這個(gè)是代碼上的優(yōu)化,不涉及性能)。

在PTQBookPageBitmapController內(nèi),使用一個(gè)大小為3的數(shù)組作為Bitmap的復(fù)用池。

private val bitmapBuffer = arrayOfNulls<Bitmap?>(3)

在AbstractComposeView重寫(xiě)的dispatchDraw中調(diào)用controller的renderAndSave,而renderAndSave會(huì)提供一個(gè)Canvas,這個(gè)Canvas已經(jīng)把Bitmap準(zhǔn)備好了,如果可以繪制,則由super.dispatchDraw繪制。

override fun dispatchDraw(canvas: Canvas?) {
    controller.renderThenSave(width, height) {
        super.dispatchDraw(it)
    }
}

看看renderThenSave的實(shí)現(xiàn)。

fun renderThenSave(width: Int, height: Int, render: (drawable: Canvas) -> Unit) {
    //如果不再需要bitmap,則不再繪制了
    if (needBitmapPages.isEmpty() || width <= 0 || height <= 0) {
        return
    }

    //當(dāng)前需要繪制第幾頁(yè)的
    val first = needBitmapPages.first()

    //這里判斷是否需要重新創(chuàng)建Bitmap而不是從復(fù)用池去取
    var needNew = false
    if (bitmapBuffer[first.second] == null) {
        needNew = true
    } else {
        //新的大小發(fā)生變化(因?yàn)閏onfig不變,所以bitmap的大小可以認(rèn)為只受width, height影響,而不再去計(jì)算allocationByteCount)
        bitmapBuffer[first.second]!!.let {
            if (width != it.width || height != it.height) {
                it.recycle()
                needNew = true
            }
        }
    }

    //如果需要新創(chuàng)建,則創(chuàng)建一個(gè)RGB565格式的Bitmap
    if (needNew) {
        bitmapBuffer[first.second] = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
    }

    canvas.let {
        //Canvas設(shè)置Bitmap以在dispatchDraw時(shí)把內(nèi)容繪制到Bitmap上
        it.setBitmap(bitmapBuffer[first.second]!!)
        //一切準(zhǔn)備就緒后,才會(huì)回調(diào)render,讓dispatchDraw給Bitmap填充內(nèi)容
        render(it)
        //記得清掉引用
        it.setBitmap(null)
    }

    //如果還需要繪制下一張,則繼續(xù),否則流程終止
    needBitmapPages.removeFirst()
    if (needBitmapPages.isEmpty()) return
    exeRecompositionBlock?.let { it() }
}

Bitmap復(fù)用的邏輯就說(shuō)到這里,接下來(lái)我們來(lái)說(shuō)說(shuō)過(guò)度繪制的優(yōu)化。

3.2 繪制優(yōu)化

在2.3節(jié)的第2點(diǎn)中我們提到,過(guò)度繪制是一個(gè)可優(yōu)化大項(xiàng),同時(shí)第3點(diǎn)中提到,Path太大也會(huì)影響Path API的調(diào)用耗時(shí)。因此這一小節(jié)主要對(duì)這兩個(gè)情況進(jìn)行優(yōu)化。

對(duì)于過(guò)度繪制,我檢查了繪制的代碼,對(duì)于有重疊的繪制區(qū)域則盡可能地減少重復(fù)區(qū)域的繪制,這一部分的具體代碼就不貼了,代碼都在PTQBookPageViewInner的Canvas這個(gè)@Composable中。

關(guān)于過(guò)度繪制這部分,我本來(lái)想直接用一張Bitmap來(lái)“合成”扭曲圖和底圖的,這樣就可以減少繪制次數(shù),但經(jīng)過(guò)嘗試后失敗了。代碼中注釋掉的有關(guān)synthesizedBitmap的部分就是這個(gè)失敗的嘗試。

而對(duì)于Path太大的問(wèn)題,我們思考一下,根據(jù)我們抽象出來(lái)的頁(yè)面點(diǎn)模型,當(dāng)頁(yè)面接近垂直狀態(tài)時(shí),這時(shí)Path的端點(diǎn)會(huì)向上延伸到很遠(yuǎn)很遠(yuǎn)處,我用log看過(guò)了,甚至有的點(diǎn)的y坐標(biāo)到了20-30萬(wàn),這就很夸張了,所以Path太大的主要影響因素就是垂直的時(shí)候,因此我們需要對(duì)部分方便計(jì)算(有的地方是曲線不太好計(jì)算,得設(shè)計(jì)算法但我懶得想了)的繪制圖層進(jìn)行專門(mén)的垂直處理,以buildPath函數(shù)中的shadow3的Path的構(gòu)建為例,我針對(duì)越界的線與組件邊框范圍求了交點(diǎn),以避免過(guò)大的Path點(diǎn)出現(xiàn),代碼如下。

//shadow3
pathResult.shadowPaths[2].apply {
    moveTo(W)
    lineTo(S1)
    //若接近垂直,則直接畫(huà)成矩形,否則畫(huà)梯形
    if (((T1.y - O.y) / (C.y - O.y)).absoluteValue > shadow3VerticalThreshold) {
        lineTo(S1.copy(y = (C.y - O.y).absoluteValue - S1.y))
        lineTo(W.copy(y = (C.y - O.y).absoluteValue - W.y))
    } else {
        /**
         * @since v1.1.0 越界繪制優(yōu)化:如果Z在BC內(nèi),則直接畫(huà)線,否則求交點(diǎn)
         */
        //給一組log數(shù)據(jù)供參考
        //buildPath: C.y:0 O.y:1600 upsideDown:true W: Point(x=376.90134, y=0.0) S1: Point(x=523.4354, y=0.0) T1: Point(x=720.0, y=36051.1) Z: Point(x=720.0, y=62926.297)
        //buildPath: C:1600.0 O.y:0 upsideDown:false W: Point(x=380.06815, y=1600.0) S1: Point(x=526.1546, y=1600.0) T1: Point(x=720.0, y=-46201.938) Z: Point(x=720.0, y=-82226.625)
        val S1T1_OBx = Line.withKAndOnePoint(lST.k, S1).x(O.y) //S1T1交OB的x坐標(biāo)
        val WZ_OBx = Line.withKAndOnePoint(lST.k, W).x(O.y)
        lineTo(if (S1T1_OBx > C.x) T1 else Point(S1T1_OBx, O.y))
        lineTo(if (S1T1_OBx > C.x) Z else Point(WZ_OBx, O.y))
    }
    close()
}

3.3 未實(shí)現(xiàn)的優(yōu)化

這一部分記錄一下未實(shí)現(xiàn)或者失敗了的優(yōu)化,但是思路我覺(jué)得可能還是會(huì)有點(diǎn)用的。

1、native層進(jìn)行圖片合成

如果說(shuō)有兩張圖片想左右拼接,或者四張圖片想左右拼接,而又比較吃性能的話,可以考慮ndk開(kāi)發(fā),直接在native層操縱圖片的像素,但我這里失敗了,因?yàn)槲倚枰扔胏anvas API對(duì)圖片處理,再去操縱像素則更沒(méi)必要了。

這里提一嘴,如果要手動(dòng)把RGB565的圖片轉(zhuǎn)為ARGB8888,每個(gè)像素的轉(zhuǎn)換方法。

RGB565是一個(gè)像素16位,從高到低分別是R5位,G6位,B5位,而ARGB8888則是32位,每個(gè)字節(jié)8位,但這里有個(gè)坑,ARGB8888從高到低分別是ABGR。

代碼如下:

static uint32_t rgb565PixelToArgb8888(uint16_t pixel) {
    uint8_t r = ((pixel >> 11) & 0x1F) * 0xff / 0x1f;
    uint8_t g = ((pixel >> 5) & 0x3F) * 0xff / 0x3f;
    uint8_t b = (pixel & 0x1F) * 0xff / 0x1f;
    return 0xff << 24 | (b & 0xff) << 16 | (g & 0xff) << 8 | (r & 0xff);
}

2、Compose中開(kāi)子線程計(jì)算,同時(shí)降低手勢(shì)的回調(diào)頻率

這個(gè)就是2.1節(jié)第2點(diǎn)提到的優(yōu)化思路,我沒(méi)去做,因?yàn)樘珣辛恕?shí)現(xiàn)的思路大概是在手勢(shì)觸發(fā)后,起一個(gè)其他線程的協(xié)程去進(jìn)行復(fù)雜計(jì)算,然后有結(jié)果了就直接用flow(collectAsState)發(fā)送給@Composable中的state變量,導(dǎo)致UI更新。而限制頻率可以嘗試用flow的debounce方法。

這一部分我沒(méi)有去實(shí)現(xiàn),因此上面僅是個(gè)設(shè)想,可能實(shí)際操作還會(huì)有其他的問(wèn)題,不過(guò)也算給個(gè)思路供參考吧。

4 結(jié)語(yǔ)

目前的組件優(yōu)化到了一個(gè)能用的程度了,文中也說(shuō)了,其實(shí)還能進(jìn)一步優(yōu)化,比如耗時(shí)計(jì)算放到新線程,或者改用C++重寫(xiě),應(yīng)該還能優(yōu)化一些,但是懶得去實(shí)現(xiàn)了。

這一趟優(yōu)化下來(lái)也確實(shí)令我學(xué)到了不少東西,已經(jīng)收獲滿滿了,不過(guò)學(xué)習(xí)的腳步不能停下,還有很多細(xì)節(jié)是需要學(xué)習(xí)的,一步步來(lái)吧。

對(duì)于復(fù)雜UI的優(yōu)化,希望文中的一些思路能幫到大家,就寫(xiě)到這里好了。

Android 學(xué)習(xí)筆錄

Android 性能優(yōu)化篇:https://qr18.cn/FVlo89
Android 車(chē)載篇:https://qr18.cn/F05ZCM
Android 逆向安全學(xué)習(xí)筆記:https://qr18.cn/CQ5TcL
Android Framework底層原理篇:https://qr18.cn/AQpN4J
Android 音視頻篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(內(nèi)含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源碼解析筆記:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知識(shí)體:https://qr18.cn/CyxarU
Android 核心筆記:https://qr21.cn/CaZQLo
Android 往年面試題錦:https://qr18.cn/CKV8OZ
2023年最新Android 面試題集:https://qr18.cn/CgxrRy
Android 車(chē)載開(kāi)發(fā)崗位面試習(xí)題:https://qr18.cn/FTlyCJ
音視頻面試題錦:https://qr18.cn/AcV6Ap文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-628703.html

到了這里,關(guān)于Android復(fù)雜UI的性能優(yōu)化實(shí)踐 - PTQBookPageView 性能優(yōu)化記錄的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Android UI性能優(yōu)化實(shí)戰(zhàn) 識(shí)別繪制中的性能問(wèn)題(1)

    Android UI性能優(yōu)化實(shí)戰(zhàn) 識(shí)別繪制中的性能問(wèn)題(1)

    { public String name; public int imageId; public String date; public String msg; public Droid(String msg, String date, int imageId, String name) { this.msg = msg; this.date = date; this.imageId = imageId; this.name = name; } public static List generateDatas() { List datas = new ArrayList(); datas.add(new Droid(“Lorem ipsum dolor sit amet, orci nullam cra”

    2024年04月13日
    瀏覽(32)
  • 解決前端性能問(wèn)題:如何優(yōu)化大量數(shù)據(jù)渲染和復(fù)雜交互?

    解決前端性能問(wèn)題:如何優(yōu)化大量數(shù)據(jù)渲染和復(fù)雜交互?

    ??祝屏幕前的小伙伴們每天都有好運(yùn)相伴左右,一定要天天開(kāi)心!??? ????作者主頁(yè): 喔的嘛呀???? 目錄 引言 一、分頁(yè)加載數(shù)據(jù) 二、虛擬滾動(dòng) 三、懶加載 四、數(shù)據(jù)緩存 五、減少重繪和回流 六、優(yōu)化圖片和資源: 七、合并壓縮文件 八、使用Web Workers? 在前端開(kāi)發(fā)

    2024年03月10日
    瀏覽(23)
  • 解決前端性能瓶頸:高效處理大量數(shù)據(jù)渲染與復(fù)雜交互的策略與優(yōu)化方法

    解決前端性能瓶頸:高效處理大量數(shù)據(jù)渲染與復(fù)雜交互的策略與優(yōu)化方法

    ??祝屏幕前的小伙伴們每天都有好運(yùn)相伴左右,一定要天天開(kāi)心!??? ????作者主頁(yè): 喔的嘛呀???? 目錄 引言 一、分頁(yè)加載數(shù)據(jù) 二、虛擬滾動(dòng) 三、懶加載 四、數(shù)據(jù)緩存 五、減少重繪和回流 六、優(yōu)化圖片和資源: 七、合并壓縮文件 八、使用Web Workers? 在前端開(kāi)發(fā)

    2024年04月27日
    瀏覽(21)
  • 性能優(yōu)化實(shí)踐:一行代碼性能提升幾十倍?

    性能優(yōu)化實(shí)踐:一行代碼性能提升幾十倍?

    Part1 問(wèn)題背景 在一般的互聯(lián)網(wǎng)公司,大家都非常忙碌?;顑菏怯肋h(yuǎn)干不完的。這時(shí)候,我建議先做重要的事情。試想:一個(gè)人永遠(yuǎn)都在做「緊急不重要」的事情,他的產(chǎn)出必然是非常低的。這就是為什么「重要不緊急」在第二象限,僅僅排在「重要且緊急」后面。 所以對(duì)于

    2024年04月28日
    瀏覽(19)
  • Unity性能優(yōu)化筆記——UI優(yōu)化

    NGUI: UGUI: 元素更新方式: NGUI: UIPanel.LateUpdate 1.輪詢 2.UIPanel.UpdateWidgets UGUI: Canvas.SendWillRenderCanvas 1.隊(duì)列 2.m_LayoutRebuildQueue 3.m_GraphicRebuildQueue UGUI如果Canvas沒(méi)有變化Canvas.SendWillRenderCanvas是完全沒(méi)有開(kāi)銷(xiāo)的 處理隱藏顯示元素方式 NGUI:? ? ? ? 1.大量的SetActive(false), ? ? ? 2.適量

    2024年02月08日
    瀏覽(19)
  • 線索系統(tǒng)性能優(yōu)化實(shí)踐

    線索系統(tǒng)性能優(yōu)化實(shí)踐

    在京東家居事業(yè)部,線索CRM系統(tǒng)扮演著至關(guān)重要的角色,它作為構(gòu)建家居場(chǎng)景核心解決方案集的首要環(huán)節(jié),肩負(fù)著獲客和拓展業(yè)務(wù)的重要使命。然而,隨著業(yè)務(wù)的不斷擴(kuò)張和市場(chǎng)需求的日益增長(zhǎng),系統(tǒng)原有的架構(gòu)開(kāi)始顯露出諸多不適應(yīng)之處,如架構(gòu)設(shè)計(jì)不再清晰,代碼存在過(guò)

    2024年01月25日
    瀏覽(19)
  • Andriod開(kāi)發(fā)性能優(yōu)化實(shí)踐

    內(nèi)存優(yōu)化 在Android開(kāi)發(fā)中,有一些實(shí)踐可以幫助進(jìn)行內(nèi)存優(yōu)化,以減少應(yīng)用程序的內(nèi)存占用和提高性能。以下是一些常見(jiàn)的內(nèi)存優(yōu)化實(shí)踐: 使用合適的數(shù)據(jù)結(jié)構(gòu)和集合:選擇合適的數(shù)據(jù)結(jié)構(gòu)和集合來(lái)存儲(chǔ)和操作數(shù)據(jù),以減少內(nèi)存占用。例如,使用SparseArray代替HashMap,使用Arr

    2024年02月15日
    瀏覽(26)
  • 客戶端性能優(yōu)化實(shí)踐

    客戶端性能優(yōu)化實(shí)踐

    雙十一大促時(shí),客戶客服那邊反饋商品信息加載卡頓,在不斷有訂單咨詢時(shí),甚至出現(xiàn)了商品信息一直處于加載狀態(tài)的情況,顯然,在這種高峰期接待客戶時(shí),是沒(méi)法進(jìn)行正常的接待工作的。 起初,頁(yè)面一直處于加載狀態(tài),初步認(rèn)為是后端接口返回太慢導(dǎo)致,后經(jīng)過(guò)后端日志

    2024年02月03日
    瀏覽(25)
  • XxlJob深度性能優(yōu)化實(shí)踐

    XxlJob深度性能優(yōu)化實(shí)踐

    天畫(huà)項(xiàng)目的數(shù)據(jù)工廠目前在與xxl-job對(duì)接自動(dòng)化數(shù)據(jù)生成任務(wù),另外我司也在使用該組件做業(yè)務(wù),所以想深入了解下XxlJob。在跟進(jìn)了社區(qū)的github等倉(cāng)庫(kù)issue發(fā)現(xiàn)開(kāi)發(fā)迭代停滯了一段時(shí)間,思來(lái)想去準(zhǔn)備開(kāi)個(gè)下游分支做一些性能優(yōu)化和特性開(kāi)發(fā)等,于是fork了下源碼,將其作為天畫(huà)

    2024年02月21日
    瀏覽(19)
  • React組件性能優(yōu)化實(shí)踐

    React組件性能優(yōu)化的核心是減少渲染真實(shí)DOM節(jié)點(diǎn)的頻率,減少 Virtual DOM比對(duì)的頻率。 在組件中為 window注冊(cè)的全局事件,以及定時(shí)器,在組件卸載前要清理掉,防止組件卸載后繼續(xù)執(zhí)行影響應(yīng)用性能。 需求:開(kāi)啟定時(shí)器,然后卸載組件,查看組件中的定時(shí)器是否還在運(yùn)行。 什

    2024年02月14日
    瀏覽(28)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包