Jetpack系列(四) — ViewModel
ViewModel简单介绍
初步印象
在MVVM框架中
ViewModel
负责逻辑判断,承接View
和Repository
ViewModel
生命周期存活在整个Activity
生命周期,旋转不会重新创建
基本概念
ViewModelProviders
用户维护ViewModelStore
和ViewModelProvider.Factory
关键方法public static ViewModelProvider of(Fragment fragment, Factory factory)
ViewModelStore
通过HashMap
存储ViewModels
ViewModel基本使用
实现 ViewModel
-
创建
ViewModel
对象, 继承ViewModel
// HomeViewModel.kt class HomeViewModel : ViewModel() { private var tapCount = 0 private val _taps = MutableLiveData<String>("$tapCount taps") val taps: LiveData<String> get() = _taps fun updateTaps() { tapCount++ _taps.postValue("$tapCount taps") } } 复制代码
-
在View中间实例化
ViewModel
// HomeFragment.kt private val viewModel: HomeViewModel by viewModels() 复制代码
-
通过
LiveData
观察ViewModel
当中的数据变化//HomeViewModel.kt observe(viewModel.taps, ::tapsUpdate) // LifecycleOwner 扩展函数 private fun tapsUpdate(s: String?) { binding.tvCount.text = s ?: "" } 复制代码
共享Fragment数据
- 应用场景是在一个Fragment 中操纵数据,在另一个 Fragment用于显示该数据的内容。
-
创建
ViewModel
/** * ViewModel * 在 Fragment 之间共享数据 */ class MainViewModel : ViewModel() { private var _tapCount = 0 private var _taps = MutableLiveData<String>("$_tapCount taps") val taps: LiveData<String> get() = _taps fun updateTaps() { _tapCount++ _taps.value = "$_tapCount taps" } } 复制代码
-
在
HomeFragment
中观察和操作数据// HomeFragment.kt class HomeFragment : Fragment() { private lateinit var binding: FragmentHomeBinding // 方式一: 通过viewModels() 创建ViewModel private val viewModel: HomeViewModel by viewModels() private val mainViewModel: MainViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentHomeBinding.inflate(inflater, container, false) setHasOptionsMenu(true) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) ... initListener() subscribeUI() } private fun initListener() { binding.btnAdd.setOnClickListener { mainViewModel.updateTaps() } } private fun subscribeUI() { // viewModel.taps.observe(viewLifecycleOwner, ::tapsUpdate) // 扩展函数 observe(mainViewModel.taps, ::tapsUpdate) } private fun tapsUpdate(s: String?) { binding.tvCount.text = s ?: "" } } 复制代码
-
在
DeepLinkFragment
当中观察数据class DeepLinkFragment : Fragment() { private lateinit var binding: FragmentDeepLinkBinding private val mainViewModel: MainViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentDeepLinkBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) ... subscribeUI() } private fun subscribeUI() { observe(mainViewModel.taps, ::tapsUpdate) } private fun tapsUpdate(s: String) { binding.tap.text = s } } 复制代码
相关知识点
知识点一:实例 ViewModel
-
上述代码中直接使用
viewModels()
延时函数,将ViewModel
和ViewModelStoreOwner
自动绑定,然后直接使用ViewModel
实例// FragmentViewModelLazyKt.java @MainThread inline fun <reified VM : ViewModel> Fragment.viewModels( noinline ownerProducer: () -> ViewModelStoreOwner = { this }, noinline factoryProducer: (() -> Factory)? = null ) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer) @MainThread fun <VM : ViewModel> Fragment.createViewModelLazy( viewModelClass: KClass<VM>, storeProducer: () -> ViewModelStore, factoryProducer: (() -> Factory)? = null ): Lazy<VM> { val factoryPromise = factoryProducer ?: { defaultViewModelProviderFactory } return ViewModelLazy(viewModelClass, storeProducer, factoryPromise) } 复制代码
-
viewModels()
可以传入参数, 手动创建XxxxViewModel
// SearchFragment.kt private val viewModel: SearchViewModel by viewModels { LiveDataVMFactory } object LiveDataVMFactory : ViewModelProvider.Factory { override fun <T : ViewModel?> create(modelClass: Class<T>): T { @Suppress("UNCHECKED_CAST") return SearchViewModel(RepoRepository(GithubService.create())) as T } } 复制代码
-
viewModels()
实际上做了两个动作,一是创建ViewModel
实例,一是绑定ViewModel
对象,等效于下述代码// 注: 代码来自《Android 第一行代码》 // MainActivity.java lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) ... // 绑定ViewModel对象 viewModel = ViewModelProviders.of(this, MainViewModelFactory(countReserved)).get(MainViewModel::class.java) viewModel.counter.observe(this, Observer{ count -> infoText.text = count.toString() }) viewModel.user.observe(this, Observer { user -> infoText.text = user.firstName }) ... } // MainViewModelFactory.kt // 创建`ViewModel`实例 class MainViewModelFactory(private val countReserved: Int) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { return MainViewModel(countReserved) as T } } 复制代码
知识点二: ViewModel 生命周期
ViewModel
将一直留在内存中,直到限定其存在时间范围的Lifecycle
永久消失:对于 Activity,是在 Activity 完成时;而对于 Fragment,是在 Fragment 分离时。
相关链接
参考资料
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END