使用 Android View 时
在使用 Android View 进行开发时,使用 ViewModel 管理 Fragment 或 Activity 的生命周期事件是很简单的。
在 Fragment 或 Activity 生命周期中将 ViewModel 添加为观察者,在 ViewModel 中实现 DefaultLifecycleObserver
接口并监听 onCreate,onStart 和 onStop 等生命周期事件即可。
如下代码是通过实现 DefaultLifecycleObserver
在 ViewModel 处理生命周期:
package cn.itmob.sample.ui
class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
val homeViewModel: HomeViewModel by viewModels()
lifecycle.addObserver(homeViewModel)
// ...
}
}
package cn.itmob.sample.ui
class HomeViewModel : ViewModel(), DefaultLifecycleObserver {
private val _text = MutableLiveData<String>().apply {
value = "This is home Fragment"
}
val text: LiveData<String> = _text
override fun onCreate(owner: LifecycleOwner) {
// TODO Handle lifecycle event
}
override fun onStart(owner: LifecycleOwner) {
// TODO Handle lifecycle event
}
override fun onResume(owner: LifecycleOwner) {
// TODO Handle lifecycle event
}
}
使用 Jetpack Compose 时
使用 Jetpack Compose 开发应用时,官方推荐使用单个 Activity 并且不使用Fragment。使用 Activity 来管理可组合项,页面的导航是将一个可组合项换成另一个可组合项。因此,由于 Activity 比它管理的可组合项的生命周期更长,我们不能依赖 Activity 的生命周期来管理可组合项对应的 ViewModel 中依赖生命周期的任务(可组合项切换显示,它的生命周期发生了变化,但是 Activity 的生命周期并不一定会发生变化)。
如何在我们的 ViewModel
中实现类似于在视图系统中拥有的生命周期事件的可组合事件? DisposableEffect
先看代码:
@HiltViewModel
class HomeScreenViewModel @Inject constructor() : ViewModel() {
fun onStart() {
// TODO
}
fun onStop() {
// TODO
}
}
@Composable
fun HomeScreen(
viewModel: HomeScreenViewModel,
modifier: Modifier = Modifier,
) {
val state = viewModel.state.collectAsState()
DisposableEffect(Unit) {
viewModel.onStart()
onDispose { viewModel.onStop() }
}
// ...
}
DisposableEffect
可组合项会在进入组合时,运行 Effect 的 lambda,它会调用 ViewModel 的 onStart 方法,并注册一个 lambda 在可组合项离开组合时运行。这样,当可组合项离开该屏幕时,将调用 ViewModel 的 onStop。
DisposableEffect
的构造函数具有不同数量的参数,命名为 key。每当作为参数的任何 key 更改时,DisposableEffect
将调用其 onDispose,然后再次触发 DisposableEffect
的 lambda 表达式。