<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Flutter2.*_狀態(tài)共享

          共 3521字,需瀏覽 8分鐘

           ·

          2021-11-16 20:16

          ????提及狀態(tài)管理,以我們之前介紹的觀察者模式來理解,可以輕松一些,特別是對應(yīng)flutter的eventbus,可以實現(xiàn)跨組件狀態(tài)同步,狀態(tài)的持有方進(jìn)行更新,然后發(fā)布狀態(tài),使用者們監(jiān)聽狀態(tài)改變事件,完成一些后續(xù)操作。

          ????對于狀態(tài)共享,存在一個原則:當(dāng)狀態(tài)是組件私有的,則這個狀態(tài)應(yīng)該由該組件管理。當(dāng)狀態(tài)需要跨組件共享時,那么這個狀態(tài)應(yīng)該涉及到的跨組件范圍內(nèi)的所有組件的父類來管理,對于跨組件的狀態(tài)管理,管理方式有很多,前面我們聊到的eventbus便是其中之一。

          ????當(dāng)然使用軟件設(shè)計模式里的觀察者可以解決我們的處理問題訴求,但是這種設(shè)計模式是用來管理狀態(tài)的最完美的解么?不是的,使用觀察者模式時,需要我們每次定義相關(guān)事件,然后在widgewt進(jìn)行初始時,將事件進(jìn)行注冊,相同的在注銷時要把所有訂閱事件進(jìn)行事件解綁,這當(dāng)然不是最優(yōu)的選擇,那么誰才是呢?如果了解之前我們的更新帖子,想必大家會有一個關(guān)于使用InheritedWidget的大膽想法,沒錯,就是依據(jù)InheritedWidget的處理思路,flutter提供了provider,即flutetr的跨組件狀態(tài)管理解決方案!

          自定義Provider


          ??

          ????定義保存共享數(shù)據(jù)的InheritedWidget,由于不同業(yè)務(wù)的數(shù)據(jù)類型不能預(yù)期,所以使用范型接收:

          //?一個通用的InheritedWidget,保存需要跨組件共享的狀態(tài)class?InheritedProvider?extends?InheritedWidget?{
          ??InheritedProvider({
          ????required?this.data,
          ????required?Widget?child,
          ??})?:?super(child:?child);
          
          ??final?T?data;
          
          ??@override
          ??bool?updateShouldNotify(InheritedProvider?old)?{
          ????//在此簡單返回true,則每次更新都會調(diào)用依賴其的子孫節(jié)點的`didChangeDependencies`。
          ????return?true;
          ??}}

          ????數(shù)據(jù)保存已經(jīng)完成,接下來需要在數(shù)據(jù)變化時對InheritedProvider進(jìn)行重構(gòu),那么要處理的問題有兩個:

          ????·數(shù)據(jù)變化時如何通知;

          ????·重構(gòu)InheritedProvider的處理由誰來進(jìn)行;

          ????數(shù)據(jù)變化時的通知我們可以使用eventbus來進(jìn)行,對應(yīng)于flutter的sdk工具類ChangeNotifier,ChangeNotifier繼承自 Listenable,實現(xiàn)來發(fā)布-訂閱模式,定義結(jié)構(gòu)為:

          class?ChangeNotifier?implements?Listenable?{
          ??List?listeners=[];
          ??@override
          ??void?addListener(VoidCallback?listener)?{
          ?????//添加監(jiān)聽器
          ?????listeners.add(listener);
          ??}
          ??@override
          ??void?removeListener(VoidCallback?listener)?{
          ????//移除監(jiān)聽器
          ????listeners.remove(listener);
          ??}
          ??
          ??void?notifyListeners()?{
          ????//通知所有監(jiān)聽器,觸發(fā)監(jiān)聽器回調(diào)?
          ????listeners.forEach((item)=>item());
          ??}
          ???
          ??...?//省略無關(guān)代碼}

          ????此時通過Notifier的add*和remove*可以添加移除監(jiān)聽的訂閱者,使用notifyListeners()可以觸發(fā)所有的監(jiān)聽起回調(diào),此時數(shù)據(jù)通知的處理已經(jīng)完成,那么重構(gòu)工作呢?我們可以將要共享的狀態(tài)放入一個model類中,讓其繼承自changenotifier,當(dāng)共享的狀態(tài)發(fā)生變化時,只需調(diào)用notifyListeners方法即可通知訂閱者們重新構(gòu)建InheritedProvider,來看一下訂閱者類的實現(xiàn)代碼:

          class?ChangeNotifierProvider?extends?StatefulWidget?{
          ??ChangeNotifierProvider({
          ????Key??key,
          ????this.data,
          ????this.child,
          ??});
          
          ??final?Widget?child;
          ??final?T?data;
          
          ??//定義一個便捷方法,方便子樹中的widget獲取共享數(shù)據(jù)
          ??static?T?of(BuildContext?context)?{
          ????final?type?=?_typeOf>();
          ????final?provider?=??context.dependOnInheritedWidgetOfExactType>();
          ????return?provider.data;
          ??}
          
          ??@override
          ??_ChangeNotifierProviderState?createState()?=>?_ChangeNotifierProviderState();}
          class?_ChangeNotifierProviderState?extends?State>?{
          ??void?update()?{
          ????//如果數(shù)據(jù)發(fā)生變化(model類調(diào)用了notifyListeners),重新構(gòu)建InheritedProvider
          ????setState(()?=>?{});
          ??}
          
          ??@override
          ??void?didUpdateWidget(ChangeNotifierProvider?oldWidget)?{
          ????//當(dāng)Provider更新時,如果新舊數(shù)據(jù)不"==",則解綁舊數(shù)據(jù)監(jiān)聽,同時添加新數(shù)據(jù)監(jiān)聽
          ????if?(widget.data?!=?oldWidget.data)?{
          ??????oldWidget.data.removeListener(update);
          ??????widget.data.addListener(update);
          ????}
          ????super.didUpdateWidget(oldWidget);
          ??}
          
          ??@override
          ??void?initState()?{
          ????//?給model添加監(jiān)聽器
          ????widget.data.addListener(update);
          ????super.initState();
          ??}
          
          ??@override
          ??void?dispose()?{
          ????//?移除model的監(jiān)聽器
          ????widget.data.removeListener(update);
          ????super.dispose();
          ??}
          
          ??@override
          ??Widget?build(BuildContext?context)?{
          ????return?InheritedProvider(
          ??????data:?widget.data,
          ??????child:?widget.child,
          ????);
          ??}}

          ????上述代碼于ChangeNotifierProvider中提供靜態(tài)方法供子類獲取widget樹中InheritedProvider中保存的共享狀態(tài),_ChangeNotifierProviderState類中主要用來監(jiān)聽共享數(shù)據(jù)改變時重構(gòu)Widget樹,需要注意的是在調(diào)用setstate()方法操作的widget.child始終為同一個,因此執(zhí)行build時,InheritedProvider的child引用的始終是同一個子widget,在對當(dāng)前widget進(jìn)行重新build時,widget.child并不會進(jìn)行重構(gòu),即實現(xiàn)了對widget.child的緩存。需要注意的是如果ChangeNotifierProvider父級Widget重新build時,則其傳入的child便有可能會發(fā)生變化;

          ????上述即為flutter提供的provider的實現(xiàn)思路,下一天的更新,我們會結(jié)合較為經(jīng)典的購物車功能,來看一下provider的實際使用,今天的分享就到這里,感謝各位看官捧場,讓我們后續(xù)研討學(xué)習(xí)!

          瀏覽 52
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷色五月激情强奸 | 直接能看的黄色网址 | 亚洲欧洲视频在线观看 | JUY-579被丈夫的上司侵犯后的第7天,我 尤物网在线观看 | 操一区|