Flutter之可滾動組件子項緩存?KeepAlive詳解
本文為大家分析了Flutter之可滾動組件子項緩存 KeepAlive,供大家參考,具體內容如下
首先回想一下,在介紹 ListView 時,有一個addAutomaticKeepAlives 屬性我們并沒有介紹,如果addAutomaticKeepAlives 為 true,則 ListView 會為每一個列表項添加一個 AutomaticKeepAlive 父組件。雖然 PageView 的默認構造函數(shù)和 PageView.builder 構造函數(shù)中沒有該參數(shù),但它們最終都會生成一個 SliverChildDelegate 來負責列表項的按需加載,而在 SliverChildDelegate 中每當列表項構建完成后,SliverChildDelegate 都會為其添加一個 AutomaticKeepAlive 父組件。下面我們就先介紹一下 AutomaticKeepAlive 組件。
AutomaticKeepAlive
AutomaticKeepAlive 的組件的主要作用是將列表項的根 RenderObject 的 keepAlive 按需自動標記 為 true 或 false。為了方便敘述,我們可以認為根 RenderObject 對應的組件就是列表項的根 Widget,代表整個列表項組件,同時我們將列表組件的 Viewport區(qū)域 + cacheExtent(預渲染區(qū)域)稱為加載區(qū)域 :
1.當 keepAlive 標記為 false 時,如果列表項滑出加載區(qū)域時,列表組件將會被銷毀。
2.當 keepAlive 標記為 true 時,當列表項滑出加載區(qū)域后,Viewport 會將列表組件緩存起來;當列表項進入加載區(qū)域時,Viewport 從先從緩存中查找是否已經緩存,如果有則直接復用,如果沒有則重新創(chuàng)建列表項。
那么 AutomaticKeepAlive 什么時候會將列表項的 keepAlive 標記為 true 或 false 呢?答案是開發(fā)者說了算!Flutter 中實現(xiàn)了一套類似 C/S 的機制,AutomaticKeepAlive 就類似一個 Server,它的子組件可以是 Client,這樣子組件想改變是否需要緩存的狀態(tài)時就向 AutomaticKeepAlive 發(fā)一個通知消息(KeepAliveNotification),AutomaticKeepAlive 收到消息后會去更改 keepAlive 的狀態(tài),如果有必要同時做一些資源清理的工作(比如 keepAlive 從 true 變?yōu)?false 時,要釋放緩存)。
我們基于上一節(jié) PageView 示例,實現(xiàn)頁面緩存,根據(jù)上面的描述實現(xiàn)思路就很簡單了:讓Page 頁變成一個 AutomaticKeepAlive Client 即可。為了便于開發(fā)者實現(xiàn),F(xiàn)lutter 提供了一個 AutomaticKeepAliveClientMixin ,我們只需要讓 PageState 混入這個 mixin,且同時添加一些必要操作即可:
class _PageState extends State<Page> with AutomaticKeepAliveClientMixin { ? ? @override ? Widget build(BuildContext context) { ? ? super.build(context); // 必須調用 ? ? return Center(child: Text("${widget.text}", textScaleFactor: 5)); ? } ? ? @override ? bool get wantKeepAlive => true; // 是否需要緩存 }
代碼很簡單,我們只需要提供一個 wantKeepAlive,它會表示 AutomaticKeepAlive 是否需要緩存當前列表項;另外我們必須在 build 方法中調用一下 super.build(context),該方法實現(xiàn)在 AutomaticKeepAliveClientMixin 中,功能就是根據(jù)當前 wantKeepAlive 的值給 AutomaticKeepAlive 發(fā)送消息,AutomaticKeepAlive 收到消息后就會開始工作。
現(xiàn)在我們重新運行一下示例,發(fā)現(xiàn)每個 Page 頁只會 build 一次,緩存成功了。需要注意,如果我們采用 PageView.custom 構建頁面時沒有給列表項包裝 AutomaticKeepAlive 父組件,則上述方案不能正常工作,因為此時Client 發(fā)出消息后,找不到 Server,404 了。
KeepAliveWrapper
雖然我們可以通過 AutomaticKeepAliveClientMixin 快速的實現(xiàn)頁面緩存功能,但是通過混入的方式實現(xiàn)不是很優(yōu)雅,因為必須更改 Page 的代碼,有侵入性,這就導致不是很靈活,比如一個組件能同時在列表中和列表外使用,為了在列表中緩存它,則我們必須實現(xiàn)兩份。為了解決這個問題,筆者封裝了一個 KeepAliveWrapper 組件,如果哪個列表項需要緩存,只需要使用 KeepAliveWrapper 包裹一下它即可。
@override Widget build(BuildContext context) { ? var children = <Widget>[]; ? for (int i = 0; i < 6; ++i) { ? ? //只需要用 KeepAliveWrapper 包裝一下即可 ? ? children.add(KeepAliveWrapper(child:Page( text: '$i')); ? } ? return PageView(children: children); }
下面是 KeepAliveWrapper 的實現(xiàn)源碼:
class KeepAliveWrapper extends StatefulWidget { ? const KeepAliveWrapper({ ? ? Key? key, ? ? this.keepAlive = true, ? ? required this.child, ? }) : super(key: key); ? final bool keepAlive; ? final Widget child; ? ? @override ? _KeepAliveWrapperState createState() => _KeepAliveWrapperState(); } ? class _KeepAliveWrapperState extends State<KeepAliveWrapper> ? ? with AutomaticKeepAliveClientMixin { ? @override ? Widget build(BuildContext context) { ? ? super.build(context); ? ? return widget.child; ? } ? ? @override ? void didUpdateWidget(covariant KeepAliveWrapper oldWidget) { ? ? if(oldWidget.keepAlive != widget.keepAlive) { ? ? ? // keepAlive 狀態(tài)需要更新,實現(xiàn)在 AutomaticKeepAliveClientMixin 中 ? ? ? updateKeepAlive(); ? ? } ? ? super.didUpdateWidget(oldWidget); ? } ? ? @override ? bool get wantKeepAlive => widget.keepAlive; }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
android編程實現(xiàn)為程序創(chuàng)建快捷方式的方法
這篇文章主要介紹了android編程實現(xiàn)為程序創(chuàng)建快捷方式的方法,實例分析了Android創(chuàng)建程序快捷方式的相關設置與功能實現(xiàn)技巧,需要的朋友可以參考下2015-11-11Android Studio實現(xiàn)簡易登錄界面制作
這篇文章主要為大家詳細介紹了Android Studio實現(xiàn)簡易登錄界面制作,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Android ViewPager實現(xiàn)智能無限循環(huán)滾動回繞效果
這篇文章主要為大家詳細介紹了Android ViewPager實現(xiàn)智能無限循環(huán)滾動回繞效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07Flutter 使用Navigator進行局部跳轉頁面的方法
這篇文章主要介紹了Flutter 使用Navigator進行局部跳轉頁面的方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05解決Android V7后自定義Toolbar、ActionBar左側有空白問題
這篇文章主要介紹的Android V7后自定義Toolbar、ActionBar左側有空白問題的解決方法,需要的朋友可以參考下2017-04-04淺析Android App的相對布局RelativeLayout
這篇文章主要介紹了Android App的相對布局RelativeLayout,文中舉了一個登錄界面的XML布局例子,非常直觀,需要的朋友可以參考下2016-04-04