Android Jetpack -- ViewModel篇(一)


ViewModel的出現主要為了解決兩個問題:
1.當Actvitiy銷毀重建過程中的數據恢復問題,雖然原來可以使用onSaveInstanceState()來完成,但是只支持能被序列化的數據而且是小量數據,對於大量數據則顯得有點無力。
2.UI控制器的工作繁忙,UI控制器主要用於處理顯示,交互,其他的額外操作可以委托給其他類完成,將不應該分配給UI的任務分離出來是必要的,這也就是上面所說的分離關注點原則。
下面是示意圖

ViewModel實例

ViewModel在配置更改期間能自動保留其對象,以便它們所持有的數據可立即用於下一個 Activity 或片段 Fragment

具體的實例我在以前的一篇博客中講過了,想要了解請點擊  Android學習進度二  進行查看。

 

回到最上面的那個圖,圖說明了ViewModel的作用域涉及到整個生命周期,當獲取ViewModel時,ViewModel的生命周期限定為傳入ViewModelProvider的對象的生命周期。也就是對於以下場景(引用官方示例)

    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.
             });
         }
     }
     

由於傳入的是Activity,所以其作用域為整個Activity,不同的Fragment可以通過ViewModelProviders獲取到同一個ViewModel,這樣有以下的好處:

  • Activity無須參與Fragment之間的交互。Activity與Fragment無關
  • Fragment之間也無需互相建立聯系,Fragment與Fragment無關
  • 每個Fragment都有自己的生命周期,即使被替換也不會有任何影響

ViewModel加強,支持異常生命周期

有些時候在Activity被意外殺死,如清理后台等會直接跳過onDestory()而是回調onSaveInstanceState()異常殺死下的生命周期,這個時候ViewModel也會被殺死,再次恢復的時候便會被重建,這樣,原來的數據也就丟失了,因此我們需要改進一下ViewModel以支持異常退出情況下的重建。
首先很容易是想到通過onSaveInstanceState() 來保存,然后通過SaveInstanceState 來恢復,雖然也是一種可行的方法,但是跟ViewModel沒什么關聯,ViewModel也提供了類似SavedInstanceState的方法。

SavedStateHandle :用於保存狀態的數據類型,是一個key-value的map,類似於Bundle。

具體用法

 public class ViewModelWithData extends ViewModel {
 
     private MutableLiveData<Integer> number;
     private SavedStateHandle handle;
 
     private static final String KEY_NUMBER = "number";
 
     public ViewModelWithData(SavedStateHandle handle) {
         this.handle = handle;
         number = new MutableLiveData<>();
         number.setValue(0);
     }
 
     public MutableLiveData<Integer> getNumber() {
         if (!handle.contains(KEY_NUMBER)) {
             handle.set(KEY_NUMBER, 0);
         }
         return handle.getLiveData(KEY_NUMBER);
     }
 
     public void addNumber(int n) {
         getNumber().setValue(getNumber().getValue() + n);
     }
 }
 public class LiveDataActivity extends AppCompatActivity {
 
     private ViewModelWithData viewModelWithData;
 
     ActivityLiveDataBinding binding;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         binding = DataBindingUtil.setContentView(this, R.layout.activity_live_data);
         viewModelWithData = ViewModelProviders.of(this, new SavedStateVMFactory(this)).get(ViewModelWithData.class);
         binding.setData(viewModelWithData);
         binding.setLifecycleOwner(this);
     }
 
 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM