前言
ViewModel是google推出的一個數據處理框架,ViewModel類是被設計用來以可感知生命周期的方式存儲和管理 UI 相關數據ViewModel中數據會一直存活即使 activity configuration發生變化.另外它生來可能目的就是與Fragment在數據共享上進行配合的.
使用它常與LiveData數據前台類(類似觀察者模式的數據實體回調類)進行配合以前使用,如果你未了解LiveData建議你先了解它Android開發 LiveData與MutableLiveData詳解 然后在回頭在來看這篇博客
在總結下有的這些特征:
1.讓數據與UI隔離:讓ViewModel來獲取數據加工數據並且回調給UI層.明確職責工作分離(參考MVP,MVVM這些框架結構)
2.數據與生命周期綁定:ViewModel與注冊的Activity的生命周期綁定,有着與Activity同步的生命周期,如下圖.這樣就算網絡請求的數據的異步回來后Activity已經銷毀也不會出現問題,因為ViewModel也會被銷毀終止數據的回調.
3.數據持久化:ViewModel不會因為屏幕的旋轉導致Activity重新創建而重置數據.(這樣避免了Activity被旋轉數據丟失的問題)
4.與其他Activity獨立:ViewModel的數據是獨立的,它跟每一個綁定的Activity都是實例一個單獨的數據(意思是它無法跟多個Activity綁定后同步共享數據)
5.天生為了配合Fragment:ViewModel可以與一個Activity與多個Fragment綁定后共享數據.(你終於可以不用很蛋疼的把Fragment的數據暫存到Activity里了)並且可以都與他們的生命周期關聯.這樣Fragment短暫的生命周期將不在讓你煩惱數據的暫存問題.
依賴
implementation "androidx.fragment:fragment:1.1.0" implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0" implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
androidx.lifecycle:lifecycle-extensions:2.1.0 是ViewModelProviders的實現依賴,如果不導入就沒有這個。
創建與綁定Activity
創建ViewModel
public class DemoViewModel extends ViewModel { // TODO: Implement the ViewModel @Override protected void onCleared() { super.onCleared(); //清除的方法,這個方法需要讓你處理一些網絡請求的停止或者數據加工的邏輯停止,它與綁定的Activity在銷毀的時候觸發.你不需要手動在Activity里調用它 } }
綁定Activity
public class Demo1Activity extends AppCompatActivity { private static final String TAG = "Demo1Activity"; private DemoViewModel mDemoViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_demo); mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//獲取ViewModel,讓ViewModel與此activity綁定 } }
以上簡單繼承和注冊后就與Activity綁定了,它是單例模式的這點你可以在of()方法里看到它實現了單例(一個Activity只有一個單例),另外在Fragment的方式也是與Activity相同的方式如下:
mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class);
這樣你就將Activity和Fragment之間可以用ViewModel進行數據上的共享與同步了
簡單的demo
實際使用的時候是與LiveData一起配合使用的,這里提供一個簡單的demo了解下實際使用.
創建LiveData類
public class DemoData extends LiveData<DemoData> { private int tag1; private int tag2; public int getTag1() { return tag1; } public void setTag1(int tag1) { this.tag1 = tag1; postValue(this); } public int getTag2() { return tag2; } public void setTag2(int tag2) { this.tag2 = tag2; postValue(this); } }
創建ViewModel並且在內部實例化LiveData
public class DemoViewModel extends ViewModel { // TODO: Implement the ViewModel private DemoData mDemoData = new DemoData(); public DemoData getDemoData() { return mDemoData; } @Override protected void onCleared() { super.onCleared(); //清除的方法,這個方法需要讓你處理一些網絡請求的停止或者數據加工的邏輯停止 } }
綁定Activity,模擬數據變化
public class Demo2Activity extends AppCompatActivity { private static final String TAG = "Demo2Activity"; private Button mBtnAddData; private DemoViewModel mDemoViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_demo2); mBtnAddData = findViewById(R.id.btn_add_data); mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//獲取ViewModel,讓ViewModel與此activity綁定 mDemoViewModel.getDemoData().observe(this, new Observer<DemoData>() { //注冊觀察者,觀察數據的變化 @Override public void onChanged(DemoData demoData) { Log.e(TAG, "onChanged: 數據有更新"); } }); mBtnAddData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "onClick: 已經點擊"); mDemoViewModel.getDemoData().setTag1(123); //這里手動用按鍵點擊更新數據 } }); } }
綁定Fragment
public class DemoFragment extends Fragment { private static final String TAG = "DemoFragment"; private DemoViewModel mViewModel; @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.demo1_fragment, container, false); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // TODO: Use the ViewModel mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class); mViewModel.getDemoData().observe(this, new Observer<DemoData>() { @Override public void onChanged(DemoData demoData) { Log.e(TAG, "onChanged: 數據有更新"); } }); } }
Fragment綁定ViewModel , of(getActivity())與of(this)的區別
mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class); //使用getActivity()獲得的ViewModel 作用域在Activity里和所有他創建碎片的里,意思是你在其他Fragment也獲取相同內存地址的ViewModel mViewModel = ViewModelProviders.of(this).get(DemoViewModel.class); //這個ViewModel是獨立的,只為這個Fragment單獨服務,其他Fragment無法獲取到相同內存地址的ViewModel
end