flutter項(xiàng)目?jī)?yōu)化--渲染優(yōu)化

基于當(dāng)前的flutter項(xiàng)目功能基本實(shí)現(xiàn),項(xiàng)目框架結(jié)構(gòu)不清晰,代碼耦合嚴(yán)重,重復(fù)渲染耗費(fèi)資源過(guò)大等問(wèn)題影響項(xiàng)目接下去的迭代開發(fā),所以對(duì)當(dāng)前項(xiàng)目先進(jìn)行重構(gòu)變得尤為重要。
雖然 Flutter 技術(shù)構(gòu)建的應(yīng)用程序在默認(rèn)情況下已經(jīng)非常高性能,但一開始急于完成項(xiàng)目,并沒(méi)有就渲染上的性能問(wèn)題做過(guò)多的思考。參考flutter官網(wǎng),對(duì)頁(yè)面的渲染性能問(wèn)題需要做如下幾點(diǎn)的考慮。

1. 減少build()的耗時(shí)

1) 避免在build()方法中執(zhí)行重復(fù)且耗時(shí)的工作,因?yàn)楫?dāng)父widget重建時(shí),子widget的build()方法會(huì)被重復(fù)調(diào)用
2)避免在build()方法中返回一個(gè)超大widget,將widget拆分成多個(gè)小widget,各自控制UI的渲染,避免重復(fù)渲染一個(gè)大的widget。


實(shí)踐

1) 采用Provider庫(kù),分離數(shù)據(jù)及視圖代碼,隔絕widget。
2) 將原先在build()方法中的的一些邏輯代碼提取到provider model中處理,減少build()后多次執(zhí)行。
3)將大組件拆分成多個(gè)widget小組件。與業(yè)務(wù)代碼耦合的組件采用provider進(jìn)行數(shù)據(jù)管理,進(jìn)而驅(qū)動(dòng)頁(yè)面UI渲染,獨(dú)立小組件采用statefullwidget進(jìn)行各自數(shù)據(jù)的狀態(tài)管理。
4)采用Provider庫(kù)中的shouldRebuild來(lái)減少不必要的渲染

Selector<QualificationModel,Tuple2<Uint8List, Uint8List>>(
                shouldRebuild: (previous, next) {
                  if (previous.item1 != next.item1 && next.item1 != null) {
                    ...
                  }
                  return false;
                },
                selector: ((_, data) => Tuple2(
                    data.frontIdentity,
                    data.backIdentity)),
                builder: (context, data, _) { return ...})

2. 在必要的時(shí)候才使用一些效果

類似web開發(fā)中css3實(shí)現(xiàn)一些3D效果會(huì)開啟GPU加速渲染,占用過(guò)多的資源,flutter中也有相同的問(wèn)題。
在flutter中實(shí)現(xiàn)某些效果會(huì)調(diào)用性能代價(jià)很大的saveLayer()方法。因?yàn)檎{(diào)用 saveLayer() 會(huì)開辟一片離屏緩沖區(qū)。將內(nèi)容繪制到離屏緩沖區(qū)可能會(huì)觸發(fā)渲染目標(biāo)切換,這些切換在較早期的 GPU 中特別慢。
避免使用一些會(huì)觸發(fā)saveLayer()的widget:

  • 盡量不使用Opacitywidget
  • 使用Clipping時(shí)避免使用Clip.antiAliasWithSaveLayer
  • ShaderMask
  • ColorFilter
  • 使用Chip且disabledColorAlpha != oxff 時(shí)
  • 使用Text且存在overfloShader時(shí)

避免調(diào)用 saveLayer() 的方式:

  • 要在圖像中實(shí)現(xiàn)淡入淡出,請(qǐng)考慮使用 FadeInImage widget,該 widget 使用 GPU 的片段著色器應(yīng)用漸變不透明度。
  • 要?jiǎng)?chuàng)建帶圓角的矩形,而不是應(yīng)用剪切矩形,考慮使用很多 widget 都提供的 borderRadius屬性。

3. 對(duì)列表或者網(wǎng)格列表采用懶加載

在構(gòu)建大型網(wǎng)格或列表時(shí),使用帶有回調(diào)的惰性方法。這樣,只有屏幕的可見(jiàn)部分是在開始時(shí)構(gòu)建的。

ScrollController doneScrollController = ScrollController();
doneScrollController.addListener(() {
      if (doneScrollController.position.pixels ==
              doneScrollController.position.maxScrollExtent &&
          !Provider.of<DoneTasksModel>(context, listen: false).isLastPage) {
        Provider.of<DoneTasksModel>(context, listen: false).nextPageListData();
      }
    });
ListView.separated(
  itemBuilder: (BuildContext context, int idx) {
    return ...
  },
  separatorBuilder: (BuildContext context, int index) {
    return ...
  },
  itemCount: 50,
  controller: scrollController,
)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容