Android Jetpack 之 ViewModel

Android Jetpack 之 ViewModel

参考文章

官方文档
“终于懂了“系列:Jetpack AAC完整解析(三)ViewModel 完全掌握

一、简介

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。

ViewModel(视图模型)
  • 第一个功能可以使 ViewModel 以及 ViewModel 中的数据在屏幕旋转或配置更改引起的 Activity 重建时存活下来, 重建后数据可继续使用。
  • 第二个功能可以帮助开发者轻松实现 Fragment 与 Fragment 之间, Activity 与 Fragment 之间的通讯以及共享数据。

ViewModel最重要的特点是 生命周期长于Activity。
Android Jetpack 之 ViewModel_第1张图片

看到在因屏幕旋转而重新创建Activity后,ViewModel对象依然会保留。 只有Activity真正Finish的时ViewModel才会被清除。

二、接入

添加依赖

// ViewModel
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'

三、基本使用

第一步 直接新建一个类继承ViewModel
class MyViewModel : ViewModel() {
    private val users: MutableLiveData> by lazy {
        MutableLiveData>().also {
            loadUsers()
        }
    }

    fun getUsers(): LiveData> {
        return users
    }

    private fun loadUsers() {
        // 执行异步操作以获取用户。
    }
}
第二步 在Activity/Fragment中使用ViewModelProvider获取MyViewModel实例
class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        //在系统第一次调用活动的onCreate()方法时创建ViewModel。
        //重新创建的活动接收由第一个活动创建的相同MyViewModel实例。

        //方法一:使用“by viewModels()”Kotlin属性委托来自activity-ktx工件
        val model: MyViewModel by viewModels()
        
        //方法二:使用ViewModelProvider
        val viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
        
        model.getUsers().observe(this, Observer>{ users ->
            // update UI
        })
    }
}

如果重新创建了该 Activity,它接收的 MyViewModel 实例与第一个 Activity 创建的实例相同。当所有者 Activity 完成时,框架会调用 ViewModel 对象的 onCleared() 方法,以便它可以清理资源。

注意:ViewModel 绝不能引用视图、Lifecycle 或可能存储对 Activity 上下文的引用的任何类。这样可以避免了可能的内存泄漏,同时实现了解耦。

四、组件通讯和共享数据

两个 fragment 可以使用其 activity 范围共享 ViewModel 来处理此类通信

 class SharedViewModel : ViewModel() {
    val selected = MutableLiveData()

    fun select(item: Item) {
        selected.value = item
    }
}

class ListFragment : Fragment() {

    private lateinit var itemSelector: Selector

    //方法一:使用“by activityViewModels()”Kotlin属性委托来自fragment-ktx
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}

class DetailFragment : Fragment() {
    
    //方法二:注意ViewModelProvider实例传入的是宿主Activity,requireActivity()
    private lateinit var pageViewModel: SharedViewModel
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
        model.selected.observe(viewLifecycleOwner, Observer { item ->
            // Update the UI
        })
    }
}

五、对比onSaveInstanceState()

使用场景不同
  • onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用;
  • ViewModel恢复数据 则 只有在 因配置更改界面销毁重建 的情况;
存储方式

ViewModel是存在内存中,读写速度快,而通过onSaveInstanceState是在 序列化到磁盘中。

存储数据的限制

ViewModel,可以存复杂数据,大小限制就是App的可用内存。而 onSaveInstanceState只能存可序列化和反序列化的对象,且大小有限制(一般Bundle限制大小1M)。

六、AndroidViewModel

如果 ViewModel 需要 Application 上下文(例如,为了查找系统服务),它可以扩展 AndroidViewModel 类并设置用于接收 Application 的构造函数,因为 Application 类会扩展 Context。

你可能感兴趣的:(知识点链接,android,android,jetpack,kotlin)