Jet_ViewModel

2019/01/04

Jetpack ViewModel

  1. ViewModel用来存储和管理UI相关数据,在生命周期内的一种有意识的方式。
  2. 解决3个问题:
    • 通常我们通过onSaveInstanceState()恢复一些可序列化的小的数据,大数据比较bitmap就不管了
    • UI控制器需要异步调用,这可能需要一段时间才能恢复。(destroy销毁)
    • UI控制器主要的目的是显示UI数据,反映用户行为,处理与OS的通信,比如权限等。网络请求,数据库昂文,所以需要将逻辑从UI控制器中分离。

1. 实现VM

class MyViewModel: ViewModel() {
	private lateinit var users: MutableLiveData<List<User>>
	
	fun getUsers(): LiveData<List<User>> {
		if (!::users.isInitiabized) {
			users = MutableLiveData()
			loadUsers()
		}
		return users
	}
	
	// 异步获取users
	private fun loadUsers() {}

}

// 使用
val model = ViewModelProviders.of(getContext()).get(MyViewModel::class.java)
model.getUsers().observe(getContext(), Observer<List<User>>) {Users -> // updata UI })

2. VM的生命周期

  1. ViewModel Scope贯穿Activity整个生命周期,直到Finished后系统会调用ViewModel的onCleared()

3. 在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(saveInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		model = activity?.run {
			ViewModelProviders.of(this).get(SharedViewModel::class.java) ?: throw Exception("Invalid Activity") itemSelector.setOnClickListener {item -> // update UI }
		}
	}
}

class DetailFragment : Fragment() {
	private lateinit var model: SharedViewModel
	
	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		model = activity?.run {
			ViewModelProviders.of(this).get(SharedViewModel::class.java) } ?. throw Exception("Invalid Activity") model.selected.observe(this, Observer<Item> { item -> // update UI })
		}
	}
}

该方法具有如下优点

  1. Activity不需要做任何事情,也不需要了解这种沟通
  2. 除了SharedViewModel外,Fragment不需要彼此了解,如果其中一个Fragment销毁,也另一个仍然可以继续工作
  3. 每个Fragment都有自己的生命周期,不受另一个影响。如果一个Fragment替换为别的Fragment,也没有任何问题。

4. 用VM替换Loaders

  1. 使用ViewModel与Room和LiveData一起替换CursorLoader

5. 其他资源

  1. 替换AsyncTaskLoader
  2. Architecture Components BasicSample
dataBinding {
      enabled =true
  }

文内导航