??ViewModel類旨在存儲和管理與UI相關(guān)的數(shù)據(jù)赵刑,以便數(shù)據(jù)在諸如屏幕旋轉(zhuǎn)之類的配置更改中生存下來吁系。它還處理Activity/Fragment與應(yīng)用程序的其余部分的通信(例如調(diào)用業(yè)務(wù)邏輯類)。
??之所以要持久化是基于兩個原因:如果OS銷毀app釋放資源,用戶數(shù)據(jù)不會丟失;當網(wǎng)絡(luò)很差或者斷網(wǎng)的時候app可以繼續(xù)工作。Model是負責app數(shù)據(jù)處理的組件碟案。它們不依賴于View或者app 組件(Activity,F(xiàn)ragment等)颇蜡,因此它們不會受那些組件的生命周期的影響价说。保持UI代碼的簡單辆亏,業(yè)務(wù)邏輯分離可以讓它更易管理。
ViewModel的目的是獲取并保存Activity或Fragment所必需的信息鳖目。Activity或Fragment應(yīng)該能夠觀察到ViewModel中的變化
將視圖數(shù)據(jù)所有權(quán)與UI控制器邏輯分離是更容易和更有效的扮叨。生命周期提供了一個名為ViewModel的新類,一個用于UI控制器的幫助器類领迈,它負責準備UI的數(shù)據(jù)彻磁。在配置更改期間,ViewModel將自動保留狸捅,以便其保存的數(shù)據(jù)立即可用于下一個Activity或Fragment
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 async operation to fetch users
}
}
現(xiàn)在活動可以訪問這個列表如下:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
如果Activity重新創(chuàng)建衷蜓,它將收到由上一個Activity創(chuàng)建的相同的MyViewModel實例。當所有者Activity銷毀時尘喝,框架調(diào)用ViewModel的onCleared()方法磁浇,以便它可以清理資源。
由于ViewModel超出了具體的Activity和Fragment實例朽褪,所以它不應(yīng)該引用View或任何可能持有對活動上下文的引用的類置吓。如果ViewModel需要應(yīng)用程序上下文(例如,找到系統(tǒng)服務(wù))缔赠,則可以繼承AndroidViewModel類衍锚,并在構(gòu)造函數(shù)中接收應(yīng)用程序的構(gòu)造函數(shù),子類必須具有接受Application作為唯一參數(shù)的構(gòu)造函數(shù)嗤堰。(因為Application類繼承了Context)构拳。
在Fragments之間共享數(shù)據(jù)
Activity中的兩個或多個Fragment需要相互通信。因此這兩個Fragment需要定義一些接口描述梁棠,并且Activity必須將兩者綁定在一起。此外斗埂,兩個Fragment都必須處理其他Fragment尚未創(chuàng)建或不可見的情況符糊。
通過使用ViewModel對象可以解決這個問題。想象一下主從Fragment的常見情況呛凶,其中我們有一個Fragment男娄,用戶從列表中選擇一個項目,另一個Fragment顯示所選項目的內(nèi)容漾稀。
這些Fragment可以使用其Activity范圍共享一個ViewModel來處理此通信模闲。
每個片段可以通過其Activity使用相同的鍵獲取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 onActivityCreated() {
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends LifecycleFragment {
public void onActivityCreated() {
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// update UI
});
}
}
注意崭捍,在獲取ViewModelProvider時尸折,兩個Fragment都使用getActivity()。這意味著他們都將收到相同的SharedViewModel實例殷蛇,該實例是Activity的作用域实夹。
這種做法的好處:
- 該Activity不需要做任何事情橄浓,也不知道有關(guān)此通信的任何內(nèi)容。
- 除了SharedViewModel之外亮航,F(xiàn)ragment不需要彼此了解荸实。如果其中一個消失,另一個會照常工作缴淋。
- 每個Fragment都有自己的生命周期准给,不受其他Fragment的生命周期的影響。
ViewModel的生命周期
ViewModel對象在獲取ViewModel時被限定為傳遞給ViewModelProvider的生命周期重抖。ViewModel保留在內(nèi)存中露氮,直到Activity銷毀或Fragment分離之前。
