中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ViewModel如何使用

發布時間:2022-01-11 17:19:00 來源:億速云 閱讀:188 作者:iii 欄目:開發技術

這篇文章主要介紹“ViewModel如何使用”,在日常操作中,相信很多人在ViewModel如何使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”ViewModel如何使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1 主要功能

  • Activity、Fragment存活期間的數據存儲;

  • bind同一Activity的多個Fragment間數據共享;

  • 獨立或與LiveData配合實現代碼解耦;

2 使用方法

1) 引入ViewModel

  1. 在build.gradle中添加編譯lifecycle.extensions module,該module同時包含ViewModel和LiveData:

compile('android.arch.lifecycle:extensions:1.0.0')

由于lifecycle.extensions內部依賴26.1.0版本的support_v7包,建議將工程中已引用的support_v7組件版本也升級到26.1.0或以上。

2) 構造數據對象

  1. 自定義ViewModel類,繼承ViewModel;

  2. 在自定義的ViewModel類中添加需要的數據對象;

public class DemoViewModel extends ViewModel { 
    final public DemoData mData = new DemoData(); 
    public DemoViewModel() {} 
}

3) 獲取數據

  1. 通過ViewModelProviders和Activity / Fragment獲取ViewModelProvider;

  2. 通過ViewModelProvider和自定義ViewModel類獲取自定義ViewModel對象;

  3. 從自定義ViewModel對象獲取數據對象,進行需要的讀寫操作。

DemoData data = ViewModelProviders.of(getActivity()) 
        .get(DemoViewModel.class)
        .mData; 
data.doSth();

3 使用場景示范

1) 單Activity多Fragment間數據維護

  • 需求點:

    • bind同一個Activity的Fragment A、B;

    • Fragment A、B間存在跳轉關系;

    • Fragment A、B共同維護一些數據,且A、B均有讀取、修改的業務需求;

  • 傳統實現方法1:Intent +onFragmentResult()
     大致流程:

    • 跳轉時需要將數據按k-v封裝入Bundle,或者將數據Parcelable傳遞給下個頁面;

    • 下個頁面修改數據并返回后,需要從onFragmentResult()的Intent解析并同步數據;

    • Intent傳遞的數據大小總量不能超過1M;

麻煩且數據大小有限制。

  • 傳統實現方法2:數據對象SingleInstance、static
     缺點:

    • 數據的生命周期要自行控制;

    • 容易內存泄漏;

同樣麻煩,且有一定風險。

ViewModel同時規避了傳統方法的缺點:

  • bind同一個Activity的Fragments均可以通過ViewModelProvider獲取共同的數據對象,無需主動進行數據傳遞;

  • 脫離Intent、Bundle、Parcelable這些用起來很麻煩的控件;

  • 數據生命周期由ViewModel內部掌控,無需手動管理銷毀;

2) 與LiveData配合實現UI、業務邏輯分層

同為官方架構組件的LiveData,功能是監聽數據變化,并回調給注冊的observer。ViewModel+LiveData可以很方便的抽象出數據層和業務層,快速解耦。
下面的Demo來自官方案例。通過Demo,以及LiveData、ViewModel同處一個module,可以看出官方非常建議兩者搭配使用。再配合以往的Data-Binding,可以快速搭建起一套簡易的MVVM業務體系。

public class MyViewModel extends ViewModel { 
    private MutableLiveData<List<User>> users; 
    public LiveData<List<User>> getUsers() { 
          if(users == null) { 
              users= new MutableLiveData<List<Users>>(); 
              loadUsers();
          }
          return users; 
     } 
    private void loadUsers() { 
            //Do an asyncronous operation to fetch users. 
    } 
} 
public class MyActivity extends AppCompatActivity { 
    public void onCreate(Bundle savedInstanceState) { 
            //Create a ViewModel the first time the system calls an activity's onCreate()method. 
            //Re-created activities receive the same MyViewModel instance created by thefirst activity. 
          MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); 
          model.getUsers().observe(this,users -> { 
                //update UI 
          });
     } 
}

4 生命周期特性

ViewModel的生命周期與Lifecycle同步,當Activity /Fragment超出Lifecycle范圍(并不是onDestroy()回調),ViewModel連同其包含的數據一起被銷毀了。具體有多大呢,按照官方說法:

in the case of an activity, when it finishes, whilein the case of a fragment, when it’s detached.

Activity退棧后(Fragment則是與Activity解除關系后),ViewModel就解除引用關系,準備被系統回收了。

5 源碼分析

帶著兩個小問題簡單的進行下源碼分析:

1)    ViewModel與Activity / Fragment的映射關系是如何建立起來的?

(以Activity為例)

第一部分:獲取ViewModelProvider

  • 調用ViewModelProviders.of(Activity);

  • 一路調用,最終走到HolderFragmentManager.holderFragmentFor(Activity);

  • HolderFragmentManager依次從FragmentManager和HolderFragmentManager持有的HashMap查找:該Activity是否有HolderFragment與之映射(HolderFragment的作用下面一個問題將談到)

HolderFragment.class 
HolderFragment holderFragmentFor(FragmentActivity activity) { 
     FragmentManagerfm = activity.getSupportFragmentManager(); 
     HolderFragment holder = findHolderFragment(fm); 
     if(holder != null) { 
            return holder; 
      }else { 
            holder = (HolderFragment)this.mNotCommittedActivityHolders.get(activity); 
            if(holder != null) { 
                  return holder; 
            }else { 
                 //創建HolderFragment
  • 有則返回該HolderFragment;沒有則創建一個HolderFragment:

    1. 新建一個HolderFragment,commit給FragmentManager,并存入HashMap以標記為not committed狀態,防止重復commit;

    2. 向Application注冊對該Activity的生命周期監聽。如果HolderFragment尚未create,Activity就已經銷毀,則從HashMap中移除該Activity,防止泄露;

    3. HolderFragment成功創建后,從HashMap中移除該Activity;

  • 使用HolderFragment持有的ViewModelStore對象完成ViewModelProvider的創建;

第一部分的職責是構建 / 查找HolderFragment,對構建過程中的異常做保護,最后返回ViewModelProvider。HolderFragment和ViewModelProvider共同持有的ViewModelStore將成為第二部分的核心;

(第二部分:獲取ViewModel)

  • 調用ViewModelProvider.get(ViewModel.class);

  • 通過ViewModel的規范名(canonical name),從HashMap中查找是否已經存在該ViewModel的實例。有則返回;沒有則通過反射構建一個,并存入HashMap;

ViewModelStore.class 
public class ViewModelStore { 
  private final HashMap<String, ViewModel> mMap = new HashMap();

第二部分職責是映射,通過類名從HashMap查找ViewModel實例。整個映射邏輯也可以簡化為:通過Activity類名找ViewModel實例;

2) ViewModel的生命周期如何管理?

ViewModel objects are scoped to the Lifecycle passed to the ViewModelProvider when getting the ViewModel.

看到官方文檔中的這句話,心想ViewModel莫非是通過同為官方架構組件的Lifecycle來管理的生命周期的?
其實并沒有那么復雜,ViewModel在第一次調用ViewModelProvider.get(ViewModel.class)創建;而銷毀就需要靠HolderFragment自己的onDestroy()回調:

HolderFragment.class 
public void onDestroy() { 
        super.onDestroy();        
        this.mViewModelStore.clear();
}
ViewModelStore.class 
public final void clear() { 
        Iteratorvar1 = this.mMap.values().iterator(); 
        while(var1.hasNext()){ 
            ViewModel vm = (ViewModel)var1.next(); 
            vm.onCleared();
        } 
        this.mMap.clear();
    }

HolderFragment銷毀后,調用ViewModelStore.clear(),清理HashMap對ViewModel對象的引用,待系統GC回收ViewModel。這也解釋了創建ViewModelProvider時為什么需要HolderFragment配合,HolderFragment掌控了ViewModel的生命周期。

6 Last but not least

簡述下官方架構中各組件的主要職責:

  • Lifecycle:將Activity /Fragment生命周期回調事件向外拋出;

  • LiveData:在Lifecycle范圍內監聽數據的變化;

  • ViewModel:在Lifecycle范圍內存儲和共享數據;

  • Room:簡化Db操作;

除了Room,可以感受到官方在盡力把大家從最初的MVC往MVVM引導,更加強大的官方組件將使UI-業務-數據的抽象過程變得更加簡單順滑。

到此,關于“ViewModel如何使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阿合奇县| 凤凰县| 洪湖市| 平乡县| 靖江市| 增城市| 孝昌县| 封开县| 洪湖市| 合阳县| 无棣县| 灵台县| 微山县| 麻江县| 陈巴尔虎旗| 湄潭县| 彰武县| 金湖县| 通海县| 九龙县| 红河县| 布尔津县| 尼勒克县| 永年县| 外汇| 嘉义县| 正宁县| 察雅县| 万载县| 长乐市| 汤原县| 库尔勒市| 永胜县| 阳春市| 库伦旗| 江达县| 邵武市| 离岛区| 土默特右旗| 永川市| 抚顺县|