簡介
- 使用Android AAC組件構建自己的應用之後,爲了不讓自己停留在僅僅是使用的層面,所以從頭開始總結一邊AAC組件的使用以及注意的要點
- ViewModel旨在以注重生命週期的方式存儲和管理界面相關的數據, ViewModel 類讓數據可在發生屏幕旋轉等配置更改後繼續存在
作用:
- 將View中的數據模塊進行單獨的管理,使得Activity和Fragment更加簡單,只需要專注於界面本身不需要管理界面複雜的數據
- 使用ViewModel的意義在於,平時當一個界面create或者destory的時候,我們需要使用onSaveInstanceState()從onCreate()中的捆綁包回覆其數據,但是當數據較大且序列化、反序列化較困難的時候,當採用ViewModel時候,數據是不會丟失的
- 同時針對某些業務中的異步回調,我們可以利用ViewModel處理數據回調來解決這個問題
ViewModel使用
class MyViewModel : ViewModel() {
public var number : Int = 0
}
class MainActivity : AppCompatActivity() {
private lateinit var myViewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
// 首次調用onCreate時創建一個ViewModel ,重新創建的活動也會接受第一次創建的MyViewModel的實例,從而保證數據的一致性
myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
button.setOnClickListener({
myViewModel.number++
textView.setText(myViewModel.number.toString())
})
button2.setOnClickListener({
myViewModel.number += 2
textView.setText(myViewModel.number.toString())
})
textView.setText(myViewModel.number.toString())
}
}
- 注意
- 當Activity finish的時候,框架會調用ViewModel的onCleared()方法來清理資源
ViewModel生命週期
- ViewModel生命週期是貫穿整個activity生命週期,包括Activity因旋轉造成的重創建,直到Activity銷燬纔會結束
使用ViewModel在Fragment之間共享數據
- 之前在項目中如果兩個fragment需要通信,就會在Activity中將兩者綁定在一起,並且fragment之間還需要互相持有對方的引用
- 使用ViewModel之後兩個fragment可以通過ViewModel關聯起來實現數據在兩個fragment之間的共享
class SharedViewModel : ViewModel() {
val selected = MutableLiveData<Item>()
fun select(item: Item) {
selected.value = item
}
}
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")
itemSelector.setOnClickListener { item ->
// Update the UI
}
}
}
class DetailFragment : Fragment() {
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer<Item> { item ->
// Update the UI
})
}
}
如何保證數據不會丟失
首先我們創建ViewModel
ViewModelProviders.of(this).get(MyViewModel::class.java)
of和get方法
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
if (factory == null) {
factory = activity.getDefaultViewModelProviderFactory();
}
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
// 通過key從viewModelStore中取出viewModel
ViewModel viewModel = mViewModelStore.get(key);
// 橫屏或者重建判斷取出的viewmodel和傳入的viewmodel的類型是否一致
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
// 重新查詢該ViewModel
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
// 初始進入將ViewModel保存在viewmodelstore中
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
- 注意:
- 從上面的代碼可以分析出,Activity的銷燬重建都是從ViewModelStore中獲取的ViewModel----獲得的是同一個ViewModel,所以它可以保證數據不會丟失