Compose中的附带效应(一)DisposableEffect

文章目录

  • 前言`
  • 一、基础概念
  • 二、举例
    • 1.使用原生webview
    • 2.DisposableEffect与LifecycleEventObserver
    • 3.代码分析
  • 总结


前言`

阅读本文需要一定compose基础,如果没有请移步Jetpack Compose入门详解(实时更新)

本文介绍Compose中DisposableEffect的基本概念。根据官网教程总结,如有不对请在评论区指教


一、基础概念

用官方的话来说
Compose 中的附带效应是指发生在可组合函数作用域之外的应用状态的变化。
基于此,衍生了一系列的附带效应,今天我们介绍的就是DisposableEffect,DisposableEffect可用于初始化或订阅密钥,并在提供不同的密钥时重新初始化,在初始化新操作之前对旧操作执行清理。用通俗易懂的话来解释就是

  • 用户登录/切换用户 的场景下可以使用
  • 在使用原生view时需要使原生view与activity生命周期绑定时使用
  • 在用了过后需要移除的非compose操作都可以使用

相关依赖

    implementation "androidx.compose.ui:ui:$compose_version"
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    

二、举例

这里用绑定生命周期举例

1.使用原生webview

代码如下(示例):

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()
    }

}

运行效果
Compose中的附带效应(一)DisposableEffect_第1张图片

可以看到运行时是没有异常的,但是我们开发安卓的都知道使用webview要绑定activity的生命周期,不然就容易造成内存泄漏的风险;所以我们需要使用到本文所介绍的附带效应DisposableEffect来添加和移除其生命周期

2.DisposableEffect与LifecycleEventObserver

所以我们将上诉代码修改如下
代码如下(示例):



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()
        }
    }

此时如果启动页面
可以看到日志打印
在这里插入图片描述
退出页面可以看到日志打印

运行正常!

3.代码分析

我们查看

 LocalLifecycleOwner.current.lifecycle

的源码

Compose中的附带效应(一)DisposableEffect_第2张图片
可以看到其返回的是一个提供给程序的生命周期

LifecycleEventObserver,我们查看他的源码
Compose中的附带效应(一)DisposableEffect_第3张图片
可以看到,此函数的作用是用于在生命周期发生改变是调用相应状态

我们再查看DisposableEffect的源码
Compose中的附带效应(一)DisposableEffect_第4张图片
其作用在于当key1,或key2发生改变时,系统会移除观察器并再次将其添加到正确的 lifecycle。因此通过这种方法我们使用webview与在xml中声明一个webview的效果并于activity绑定生命周期相同


总结

值得注意的是,因为附带效应是在compose外的一些操作,所以我们必须要有一个或多个key来指定附带效应的范围,如果没有key,则违反其设计规则,因此不带key的DisposableEffect被声明为弃用。

参考:DisposableEffect

你可能感兴趣的:(android,jetpack,android,kotlin,android,jetpack)