Overview
ViewModel 為 Android Architecture Component 其中一部分,主要的用途為以生命週期方式來儲存與管理UI相關數據。好處為當配置更改(螢幕旋轉)之後能夠予許數據繼續存在。
以架構來說通常是作為 MVVM 的 VM(ViewModel) 角色來呈現, 透過把和 View 不相關的邏輯提取出來放到 VM,一方面可以減輕 View 的職責,一方面提高其它模組內聚力,也讓測試更容易撰寫。
Dependency
參考官網
實作 ViewModel
實作方式非常簡單,只要繼承 ViewModel 即可。通常 ViewModel 會和 LiveData 同時使用,關於 LiveDate 請參考這裡
如同 Overview 提到的 ViewModel 可以在配置改變時自動保留數據,因此應該盡量把數據部分放到 ViewModel 而不是 Actvity 或 Fragment。
public class MyViewModel extends ViewModel {
private static final String TAG = MyViewModel.class.getSimpleName();
}
Note:通常會和 LiveData一起使用,但這裡為了方便說明,先不加入LiveData。
Using in Activity
public class ViewModelMainActivity extends AppCompatActivity {
private static final String TAG = ViewModelMainActivity.class.getSimpleName();
private MyViewModel mViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_model_main_activity);
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
Log.d(TAG,"mViewModel.toString():"+ mViewModel.toString());
}
}
第12行透過 ViewModelProviders.of(this).get(MyViewModel.class); 初始化 mViewModel。
第13行用來測試旋轉螢幕後是否為同一個 ViewModel 實體。接著你可以開始旋轉螢幕了。
Note :
1.注意在 ViewModel 內絕不可引用 View, Lifecycle, 或是任何本身還會引用 activity context 的類別。若 ViewModel 內需要使用 context 就繼承 AndroidViewModel。
2.當呼叫 ViewModelProviders.of(this).get(MyViewModel.class); 之後,ViewModel 就會保存在記憶體中,直到它的作用域消失。也就是當ViewModelMainActivity 為 finish 狀態時,ViewModel 即會消失。
LiveDate 和 ViewModel 共用
LiveData 的用途為提供 observer 可以觀察本身所擁有的數據,而 ViewModel 則是提供 View 數據並可自動處理配置變化所引發的事件。
這 2 者共同使用對於 View 來說便可發揮極大的功效。
public class MyViewModel extends ViewModel {
private static final String TAG = MyViewModel.class.getSimpleName();
private MutableLiveData<List<User>> mUsers;
public LiveData<List<User>> getUsers() {
if (mUsers == null) {
mUsers = new MutableLiveData<>();
loadUsers();
}
return mUsers;
}
private void loadUsers() {
...
}
}
Scope of ViewModel
從圖中可以看到當 Activity 在 onCreate 時,ViewModel 就跟著產生。而當 Activity finish 之後,呼叫完 onDestroy 方法後,ViewModel 就跟著消失。
在 Fragment 之間分享數據
若同一個 Activity 擁有 2 個 fragment , 也可以使用 ViewModel 讓這 2 個 fragment 共享數據。
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 都使用了 getActivity 來取得 ViewModelProvider,因此,這 2 個 fragment 都接受相同的 SharedViewModel 實體。
這個做法有以下優點
1. Activity 不需要做任何事,也不需要了解 Fragment 之間的溝通。
2. Fragment 不需要彼此了解。若其中一個 Fragment 發生問題,另一個 Fragment 繼續正常工作。
Orignal From: ViewModel 基本紀錄(Android Architecture Component)
0 意見:
張貼留言