ViewModel 是Android 架構組件中負責管理UI相關數據與邏輯的,它的功能定義與MVP架構中的Persenter十分類似,配合其餘組件使用增長許多方便開發的功能。bash
定義一個ViewModel只須要繼承ViewModel
抽象類便可:markdown
public class MainViewModel extends ViewModel {
}
複製代碼
而後咱們就能夠在activity/fragment中實例化它:架構
MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
複製代碼
注意:若是想要正常使用ViewModel的所有功能,不能直接new
出ViewModel的實例,而是使用ViewModelProvider
類建立,上面的ViewModelProviders
其實就是對ViewModelProvider
的包裝類。ide
正是由於經過ViewModelProvider
建立ViewModel的方式,ViewModel才具有了一些比較方便實用的功能。this
由於建立ViewModel時傳入了activity/fragment對象實例(ViewModelProviders.of(this)
),因此ViewModel能夠感知宿主的生命週期。spa
當宿主onDestroy()
時候ViewModel便會自行銷燬掉,除此以前,當屏幕旋轉的時候,Activity會被recreate,Activity會通過幾個生命週期方法,可是這個時候ViewModel仍是以前的對象,並無被從新建立。指針
public class MainViewModel extends ViewModel{
}
public class Fragment1 extends Fragment{
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainViewModel ViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
}
}
public class Fragment2 extends Fragment{
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainViewModel ViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
}
}
複製代碼
上面的例子中,若是fragment1和fragment2的宿主activity是同一個的話,那麼它們建立的ViewModel是同一個,ViewModel中的數據兩者能夠共享。code
ViewModel配合LiveData使用能夠作到在不持有activity任何引用的狀況下更新UI數據,這是整個組件架構中最有亮點以及最有特點的地方。orm
public class MainViewModel extends ViewModel{ MutableLiveData<String> data = new MutableLiveData<>(); public LiveData<String> getData(){ return data; } public void loadData(){ // 模擬一個數據請求 data.setValue("test"); } } public class Fragment1 extends Fragment{ @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainViewModel ViewModel = ViewModelProviders.of(this).get(MainViewModel.class); ViewModel.getData().observe(this,new Observer(){ @Override public void onChanged(String s){ textView.setText(s); } }); } } 複製代碼
在上面的例子中,textView
會根據數據源的變化更新本身,而ViewModel中不須要考慮UI更新的問題,只須要關注數據的變化便可。server
ViewModel看似使用簡單,可是在實際使用中會有一些點須要關注的。
ViewModel本質上就是管理各類LiveData數據源的,但必定要注意的是在外界getData()
前必定要初始化數據源,由於外界得到數據源後通常會直接註冊觀察者,若是這時候數據源沒有初始化就會空指針異常。
上面的例子中loadData()
方法更新數據源是直接用當前data對象更新的,可是在實際使用中每次請求數據後極有可能會發生數據請求模塊返回一個新的LiveData實例,這種狀況不能直接將當前的data從新賦值:
data = newData;
複製代碼
這樣寫的話外界設置的觀察者就會失效了。