以注重生命周期的方式管理和界面相关的数据,Jetpack为咱们带来了ViewModel,从本文你能够学习到使用ViewModel的正确姿式。java
ViewModel被用来以注重生命周期的方式来保存数据和管理界面相关的数据。同时能够在相关配置发生变化是保存数据,例如屏幕旋转。android
因为Android framework管理着像Activity、Fragment这样具备生命周期的UI控制器,因此在用户的某些操做或者系统分发的某些事件,会致使framework在没有通过咱们控制下,销毁和重建UI控制器。例如,屏幕发生旋转时,framwork会调用Activity的onSaveIntanceState()
保存数据,在新Activity的onCreate()
方法中恢复这些数据,不过这仅仅是恢复可序列化和反序列化的小数据上,像list或者bitmap这种大数据就不合适了。此外,也会致使大量已经存在的数据被销毁,而后从新生成,形成资源的浪费。git
在LiveData
也说到,不要在Activity和Fragment作大量的逻辑操做,会致使代码臃肿,难以维护,建议把相关逻辑抽到单独的类进行维护,让UI控制器负责它们的本质工做。github
为此,使用ViewModel能够轻松解决以上问题。数据库
Architecture Components提供ViewModel工具类,用来为UI提供数据。ViewModel对象在配置发生变化时会自动保存数据,而且会在新建的Activity或Fragment实例使用。例如,在APP中须要显示持有多个user对象的list,应该将请求和保存users数据的动做在ViewModel对象实现,而不是Activity或Fragment。api
class MyViewModel : ViewModel() {
private val users: MutableLiveData<List<User>> by lazy {
MutableLiveData().also {
loadUsers()
}
}
fun getUsers(): LiveData<List<User>> {
return users
}
private fun loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
复制代码
在Activity中访问数据:bash
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Create a ViewModel the first time the system calls an activity’s onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
model.getUsers().observe(this, Observer<List<User>>{ users ->
// update UI
})
}
}
复制代码
当Activity被重建时,它会接收到来自第一个Activity的ViewModel对象,因此数据不会发生变化。当Activity销毁后,framework会自动调用ViewModel对象的onCleared()
方法来进行释放资源。记得,ViewModel必定不要持有View、Lifecycle或者任何有Activity context对象的引用。由于ViewModel的生命周期比它们的长,会致使内存泄漏。若是ViewModel须要持有应用的conetxt,例如用来获取系统服务,能够继承AndroidViewModel类,在它的构造方法中对接收应用的context。架构
若是Android Studio找不到ViewModelProviders,添加下面依赖哦。async
api "android.arch.lifecycle:extensions:1.1.1"
复制代码
ViewModelProvider获取ViewModel对象时,ViewModel的生命周期做用域会传递给ViewModelProvider,ViewModel会一直保持在内存中,直到其生命周期做用域失效。在下面两种状况,ViewModel对象生命周期会失效:一种是Activity对象finished,一种是Fragment对象detached。ide
下图(图来自官网)显示了Activity的生命周期和ViewModel的做用域,第一列显示了Activity对象的状态,第二列显示Activity生命周期方法,第三列ViewModel的做用域。
onCreate()
方法,咱们一般要在第一次时间建立ViewModel对象。在Activity对象的生命周期内,
onCreate()
方法可能因为系统配置改变而被系统调用屡次,而ViewModel对象只有一次,ViewModel对象会一直存在直到Activity被终结和销毁掉。
在实际开发中,常常会在两个或多个fragement对象共享数据,一般作法是实定义接口,由Activity绑定在fragment中。此外,Activity还要处理fragment的建立和可见的状况。
fragment之间能够在Activity的做用域内共享同个ViewModel对象来处理这个麻烦的数据交互问题。例如:
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).get(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).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer<Item> { item ->
// Update the UI
})
}
}
复制代码
因为两个Fragment对象绑定在同一个Activity对象,它们经过ViewModelProvider获取在Activity范围内的同一个ViewModel对象。
这样作的好处是:
加载器类像CursorLoader,常常用来保持UI中的数据与数据库的同步。能够经过ViewModel,和其余的类,替换Loader类。使用ViewModel分离UI控制器的数据加载动做,意味着能够减小更多的类强引用。 使用Loader一个常见的方法,就是在应用程序中使用一个CursorLoader观察的数据库内容,当数据库的值发生变化时,Loader自动从新加载数据和更新用户界面:
Jetpack讲到这里,基本都明白Jetpack是干吗了,Jetpack总结咱们日常开发的各类效率和架构,为咱们提供更标准的组件。Room操做数据库,LiveData通知数据更改,DataBinding更新View,Lifecycle管理周期,及其后面要讲的其余组件。都在给咱们应用层开发定义一套统一开发架构标准,以即可以开发更好APP。经过这么一套架构组件,能够快速开发可维护性高,扩展性好的APP。
本文是Jetpack系列文章第四篇