一、ViewModel介紹
ViewModel類是被設計用來以可感知生命周期的方式存儲和管理 UI 相關數據。ViewModel中數據會一直存活即使 Activity Configuration發生變化。
ViewModel可以解決以下痛點。
1. 數據持久化
由圖可知,ViewModel 生命周期是貫穿整個 activity 生命周期,包括 Activity 因旋轉造成的重創建,直到 Activity 真正意義上銷毀后才會結束。既然如此,用來存放數據再好不過了。
2. 異步回調問題
通常我們 App 需要頻繁異步請求數據,比如調接口請求服務器數據。當然這些請求的回調都是相當耗時的,之前我們在 Activity 或 Fragment里接收這些回調。所以不得不考慮潛在的內存泄漏情況,比如 Activity 被銷毀后接口請求才返回。處理這些問題,會給我們增添好多復雜的工作。但現在我們利用 ViewModel 處理數據回調,可以完美的解決此痛點。
3. 分擔 UI controller 負擔
從最早的 MVC 到目前流行的 MVP、MVVM,目的無非是 明確職責,分離 UI Controller 負擔。
UI Controller 比如 Activity 、Fragment 是設計用來渲染展示數據、響應用戶行為、處理系統的某些交互。如果再要求他去負責加載網絡或數據庫數據,會讓其顯得臃腫和難以管理。
所以為了簡潔、清爽、絲滑,我們可以分離出數據操作的職責給 ViewModel。
4. Fragments 間共享數據
比如在一個 Activity 里有多個 Fragment,這 Fragment 之間需要做某些交互。我之前的做法是接口回調,需要統一在 Activity 里管理,並且不可避免的 Fragment 之間還得互相持有對方的引用。
仔細想想就知道這是很難搞的事情,耦合度高不說,還需要大量的容錯判斷。那么用 ViewModel 是怎么樣的呢?
public class SharedViewModel extends ViewModel { private final MutableLiveData<Item> selected = new MutableLiveData<Item>(); public void select(Item item) { selected.setValue(item); } public LiveData<Item> getSelected() { return selected; } } public class MasterFragment extends Fragment { private SharedViewModel model; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); itemSelector.setOnClickListener(item -> { model.select(item); }); } } public class DetailFragment extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); model.getSelected().observe(this, { item -> // Update the UI. }); } }
2. Fragment 只需要 與ViewModel交互,不需要知道對方 Fragment 的狀態甚至是否存在,更不需要持有其引用。所有當對方 Fragment 銷毀時,不影響本身任何工作。
3. Fragment 生命周期互不影響,甚至 fragment 替換成其他的 也不影響這個系統的運作。
二、ViewModel 的使用
ViewModel一般配合 LiveData 使用,首先,獲取 ViewModel 實例,通過提供的類ViewModelProviders:
MyViewModel model = ViewModelProviders.of(activity).get(MyViewModel.class); // 或 MyViewModel model = ViewModelProviders.of(fragment).get(MyViewModel.class);
或帶有 Factory 的
MyViewModel model = ViewModelProviders.of(activity,factory).get(MyViewModel.class);
ViewModel 內部操作如下:
public class MyViewModel extends ViewModel { private MutableLiveData<List<User>> users; public LiveData<List<User>> getUsers() { if (users == null) { users = new MutableLiveData<List<User>>(); loadUsers(); } return users; } private void loadUsers() { // Do an asynchronous operation to fetch users. } }
然后,可在 Activity 觀察數據變化:
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 the first activity. MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); model.getUsers().observe(this, users -> { // update UI }); } }
