Compose CompositionLocal(类似于LocalContext.current)高层提供值低层访问

184 阅读2分钟

一、CompositionLocal是什么?

CompositionLocal是一种Compose特有的依赖注入方式,用于在外层布局提供访问,在内部使用。

二、什么时候使用?为什么使用?

一般用于在某个视图(作用域)内都有可能访问的值或方法,比如Context,官方提供一个LocalContext.cuttent供我们在底层视图访问context。

使用场景示例:NavHost-> 官方提供了NavHost控件供我们在一个Activity中管理Screen,一般来讲为了复用,一个页面是有很多个控件组合而成的,这些控件可能会被复用,比如ToolBar。在NavHost中有一个MianScreen,在MianScreen中有...反正嵌套很多就对了,那么我们如何在最底层的控件中实现退栈的操作呢?无论是NacHost管理实例一层一层传下去,还是把点击事件通过高级函数一层一层传上来都不是一个好的解决方案,这时候就需要用到CompositionLocal了。
PS:当然如果是我以前的同事,他或许会把NavHost管理实例写成静态。

三、使用示例:

基于上一个NavHost,我提供了一个使用示例。 首先需要创建一个值传递的管理:

object LauncherUIManage {
    //staticCompositionLocalOf 值改变时不触发重组,一般用于不常变化的值,如主题导航。
    //与此相对还有一个compositionLocalOf 值改变时触发使用处重组,适用于经常变化的值,如当前颜色
    private val Local = staticCompositionLocalOf<LauncherUIManageImpl> {
        error("No LauncherUIManage provided")
    }

    //获取提供的值
    val current: LauncherUIManageImpl
        @Composable
        get() = Local.current

    //中缀表达式 类似于 provides LauncherUIManageImpl()   ->    provides(LauncherUIManageImpl())
    infix fun provides(navController: LauncherUIManageImpl) = Local provides navController
}

在该类中,我们通过provides方法传入实例,通过current访问传递的值。

使用:

val navigationManager = remember { LauncherUIManageImpl(navController) }
//提供值
CompositionLocalProvider(
    LauncherUIManage provides navigationManager
) {
    //获取值
    LauncherUIManage.current.navigateBack()
}

LauncherUIManageImpl即是我提供的值,根据你自己的需要提供值吧。