阅读本文需要一定compose基础,如果没有请移步Jetpack Compose入门详解(实时更新)
本文介绍Compose中DisposableEffect的基本概念。根据官网教程总结,如有不对请在评论区指教
用官方的话来说
Compose 中的附带效应是指发生在可组合函数作用域之外的应用状态的变化。
基于此,衍生了一系列的附带效应,今天我们介绍的就是DisposableEffect,DisposableEffect可用于初始化或订阅密钥,并在提供不同的密钥时重新初始化,在初始化新操作之前对旧操作执行清理。用通俗易懂的话来解释就是
相关依赖
implementation "androidx.compose.ui:ui:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
这里用绑定生命周期举例
代码如下(示例):
import android.webkit.WebView
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.zyf.electronicwoodfish.R
@Composable
fun DisposableEffectView(){
Row (
Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center ,
verticalAlignment = Alignment.CenterVertically
) {
val context = LocalContext.current
val webView : WebView = WebView(context).apply {
id = R.id.webView
loadUrl("https://blog.csdn.net/shop_and_sleep?spm=1010.2135.3001.5343")
}
AndroidView(factory = { context ->
webView
},
modifier = Modifier.fillMaxSize()
}
}
可以看到运行时是没有异常的,但是我们开发安卓的都知道使用webview要绑定activity的生命周期,不然就容易造成内存泄漏的风险;所以我们需要使用到本文所介绍的附带效应DisposableEffect来添加和移除其生命周期
所以我们将上诉代码修改如下
代码如下(示例):
import android.webkit.WebView
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.zyf.electronicwoodfish.R
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.runtime.DisposableEffect
/**
* @author zengyifeng
* @date createDate:2023-03-21
* @brief description 附带效应 DisposableEffect
*/
@Composable
fun DisposableEffectView(){
Row (
Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center ,
verticalAlignment = Alignment.CenterVertically
) {
val context = LocalContext.current
val webView : WebView = WebView(context).apply {
id = R.id.webView
}
AndroidView(factory = { context ->
webView
},
modifier = Modifier.fillMaxSize(),
update = { view ->
})
val lifecycle = LocalLifecycleOwner.current.lifecycle
DisposableEffect(key1 = lifecycle, key2 = webView) {
val lifecycleObserver = getWebViewLifecycleObserver(webView)
lifecycle.addObserver(lifecycleObserver)
onDispose {
lifecycle.removeObserver(lifecycleObserver)
}
}
}
}
fun getWebViewLifecycleObserver(webView: WebView): LifecycleEventObserver =
LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_CREATE ->
{
Log.w("webView", "ON_CREATE ", )
webView.loadUrl("https://blog.csdn.net/shop_and_sleep?spm=1010.2135.3001.5343")
}
Lifecycle.Event.ON_START -> {
Log.w("webView", "ON_START ", )
}
Lifecycle.Event.ON_RESUME ->{
Log.w("webView", "ON_RESUME ", )
webView.onResume()}
Lifecycle.Event.ON_PAUSE ->
{
Log.w("webView", "ON_PAUSE ", )
webView.onPause()
}
Lifecycle.Event.ON_STOP -> {
Log.w("webView", "ON_STOP ", )
}
Lifecycle.Event.ON_DESTROY ->
{
Log.w("webView", "ON_DESTROY ", )
webView.destroy()
}
else -> throw IllegalStateException()
}
}
此时如果启动页面
可以看到日志打印
退出页面可以看到日志打印
运行正常!
我们查看
LocalLifecycleOwner.current.lifecycle
的源码
而LifecycleEventObserver,我们查看他的源码
可以看到,此函数的作用是用于在生命周期发生改变是调用相应状态
我们再查看DisposableEffect的源码
其作用在于当key1,或key2发生改变时,系统会移除观察器并再次将其添加到正确的 lifecycle。因此通过这种方法我们使用webview与在xml中声明一个webview的效果并于activity绑定生命周期相同
值得注意的是,因为附带效应是在compose外的一些操作,所以我们必须要有一个或多个key来指定附带效应的范围,如果没有key,则违反其设计规则,因此不带key的DisposableEffect被声明为弃用。
参考:DisposableEffect