使用CompositionLocal简化组合式函数参数

使用CompositionLocal简化组合式函数参数

目录

  • 1. 组合式函数难以维护状态
  • 2. 通过CompositionLocal对象隐式传递状态
  • 3. 重组
  • 4. 示例
  • 5. 参考资料

1. 组合式函数难以维护状态

和对象相比,组合式函数维护状态的能力比较弱。如果所有状态都通过参数列表显示传递,函数将难以维护。每次改动,调用树上所有的函数全部需要改动。如果使用一个全局对象包含所有的状态,一方面引入了全局依赖,一方面对象会变得非常复杂,难以维护一致性。为了解决这个问题,Jetpack通过CompositionLocal提供了一个带有层级结构的状态树,可以理解为OOP中把继承树中所有对象的行为移除之后的结果。

2. 通过CompositionLocal对象隐式传递状态

代码1  定义和使用CompositionLocal

import androidx.compose.runtime.compositionLocalOfval ActiveUser = compositionLocalOf<User> { User("someone") }@Composable
fun SomeScreen() {Text(ActiveUser.current.name) // 通过CompositionLocal的成员current访问具体对象。
}

代码2  提供/更换CompositionLocal

import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.CompositionLocalProvider@Composable
fun App() {Screen() // show default userval anotherUser by remember { mutableStateOf(User("another")) }CompositionLocalProvider(ActiveUser provides anotherUser) {Screen() // show another user}Screen() // show default user again
}

从上面的例子可以看到,通过CompositionLocal可以隐式传递对象,并且传递给组合式函数对象可以由父函数控制,限制在特定范围内。因为我们可以把哪些与组合式函数自身逻辑无关,同时又会影响函数结果的对象放到CompositionLocal中,简化函数参数列表。

假设组合式函数Screen依赖于某个特性Feature,我们可以通过CompositionLocal隐含的传递Feature对象。

val LocalFeatureNullable = compositionLocalOf<Feature?> { null }
val LocalFeatureMustProvide = compositionLocalOf<Feature> { error("No Feature provided.") }@Composable
fun Screen() {LocalFeatureNullable.current?.let { DisplayWithFeature() } :? DisplayWithoutFeature() Text(LocalFeatureMustProvide.current.name)
}

3. 重组

有两个函数可以创建CompositionLocal对象:

compositionLocalOf

  1. 用于值频繁变化的场景。
  2. 重组时只有依赖该值的代码重组。

staticCompositionLocalOf

  1. 用于值极少变化的场景。
  2. 重组时CompositionLocalProvider范围内的代码都参与重组。

4. 示例

代码3  使用CompositionLocal简化导航

val LocalNavController = compositionLocalOf<NavHostController> { error("No NavController provided.") }@Composable
fun Screen1() {Text(text = "Screen1")val navctl = LocalNavController.currentButton(onClick = {navctl.navigate("screen2")},modifier = Modifier.wrapContentSize()) {Text("打开屏幕2")}
}@Composable
fun Screen2() {Text(text = "Screen2")val navctl = LocalNavController.currentButton(onClick = {navctl.navigate("screen1")},modifier = Modifier.wrapContentSize()) {Text("打开屏幕1")}
}@Composable
fun MainScreen() {CompositionLocalProvider(LocalNavController provides rememberNavController()) {NavHost(LocalNavController.current, startDestination = "screen1") {composable("screen1") { Screen1() }composable("screen2") { Screen2() }}}
}

代码4  部分内置的CompositionLocal对象。文件:AndroidCompositionLocals.android.kt

package androidx.compose.ui.platform.../*** The Android [Configuration]. The [Configuration] is useful for determining how to organize the* UI.*/
val LocalConfiguration = compositionLocalOf<Configuration> {noLocalProvidedFor("LocalConfiguration")
}/*** Provides a [Context] that can be used by Android applications.*/
val LocalContext = staticCompositionLocalOf<Context> {noLocalProvidedFor("LocalContext")
}internal val LocalImageVectorCache = staticCompositionLocalOf<ImageVectorCache> {noLocalProvidedFor("LocalImageVectorCache")
}/*** The CompositionLocal containing the current [LifecycleOwner].*/
val LocalLifecycleOwner = staticCompositionLocalOf<LifecycleOwner> {noLocalProvidedFor("LocalLifecycleOwner")
}/*** The CompositionLocal containing the current [SavedStateRegistryOwner].*/
val LocalSavedStateRegistryOwner = staticCompositionLocalOf<SavedStateRegistryOwner> {noLocalProvidedFor("LocalSavedStateRegistryOwner")
}/*** The CompositionLocal containing the current Compose [View].*/
val LocalView = staticCompositionLocalOf<View> {noLocalProvidedFor("LocalView")
}...

代码5  MaterialTheme使用CompositionLocal控制组件样式

@Composable
fun MaterialTheme(colors: Colors = MaterialTheme.colors,typography: Typography = MaterialTheme.typography,shapes: Shapes = MaterialTheme.shapes,content: @Composable () -> Unit
) {...CompositionLocalProvider(LocalColors provides rememberedColors,LocalContentAlpha provides ContentAlpha.high,LocalIndication provides rippleIndication,LocalRippleTheme provides MaterialRippleTheme,LocalShapes provides shapes,LocalTextSelectionColors provides selectionColors,LocalTypography provides typography) {ProvideTextStyle(value = typography.body1) {PlatformMaterialTheme(content)}}
}

5. 参考资料

  1. Compose学习笔记(六):CompositionLocal的应用场景 - 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/729745.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javaSE-----继承和多态

目录 一.初识继承&#xff1a; 1.1什么是继承&#xff0c;为什么需要继承&#xff1a; 1.2继承的概念与语法&#xff1a; 二.成员的访问&#xff1a; 2.1super关键字 2.2this和super的区别&#xff1a; 三.再谈初始化: 小结&#xff1a; 四.初识多态&#xff1a; 4.1多…

CAS 登出方案

1.配置 CAS 服务器端 添加配置cas.logout.followServiceRedirects:true&#xff0c;使支持 CAS 退出时支持输入 service 参数为跳转路径 2.配置客户端服务,添加session清除操作 3.前端文件添加跳转重定向 1) 直接在客户端调用http请求/cas/logout去注销不能携带cookie信息, 无…

生信技能42 - Linux服务器CPU、内存、负载及高消耗进程监控信息写入本地日志

Linux服务器CPU、内存、负载及高消耗进程监控信息写入本地日志 可通过设置最大检测时间(小时)max_hour和循环检测休眠时间(秒)sleep_second调整监控程序的运行时间。 # Filename: monitor_server.py # -*- coding:utf-8 -*- - import sys import os, time from datetime…

97. 常用的HTTP服务压测工具

文章目录 导言一、ab二、wrk三、go-wrk 导言 在项目正式上线之前&#xff0c;我们通常需要通过压测来评估当前系统能够支撑的请求量、排查可能存在的隐藏bug&#xff0c;同时了解了程序的实际处理能力能够帮我们更好的匹配项目的实际需求(服务器实例个数&#xff0c;如需要部署…

ATM系统(Java)

ATM系统&#xff08;Java&#xff09; 1、实现要求 实现基本的ATM系统功能&#xff0c;包括注册&#xff0c;登录&#xff0c;查询&#xff0c;取款&#xff0c;存款&#xff0c;以及修改密码等。 2、代码实现 2.1 Test package com.ham;public class Test {public static v…

jmap-各种option参数说明

基本情况 jmap&#xff08;JVM Memory Map&#xff09;&#xff1a;作用一方面是获取dump文件&#xff08;堆转储快照文件&#xff0c;二进制文件&#xff09;&#xff0c;它还可以获取目标Java进程的内存相关信息&#xff0c;包括Java堆各区域的使用情况、堆中对象的统计信息…

高清数学公式视频素材、科学公式和方程式视频素材下载

适用于科普、解说的自媒体视频剪辑素材&#xff0c;黑色背景数学、科学公式和方程式视频素材下载。 视频编码&#xff1a;H.264 | 分辨率&#xff1a;3840x2160 (4K) | 无需插件 | 文件大小&#xff1a;16.12MB 来自PR视频素材&#xff0c;下载地址&#xff1a;https://prmuban…

浅学pymysql

pymysql 连接到MySQL数据库 使用pymysql.connect()函数连接到MySQL数据库服务器。你需要提供数据库的一些连接参数&#xff0c;如主机名、端口、用户名、密码和数据库名。 import pymysqlconn pymysql.connect(hostlocalhost,useryour_username,passwordyour_password,data…

阿里云服务器怎么使用?3分钟搭建网站教程2024新版

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网aliyunfuwuqi.com以搭建WordPress网站博客为例&#xff0c;来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流…

设计模式学习笔记 - 设计原则 - 10.实战:针对非业务的通用框架开发,如何做需求分析和设计及如何实现一个支持各种统计规则的性能计数器

前言 接下来我们在结合一个支持各种统计规则的性能计数项目&#xff0c;学习针对一个非业务的通用框架开发&#xff0c;如何来做需求分析、设计和实现&#xff0c;同时学习如何灵活应用各种设计原则。 项目背景 设计开发一个小的框架&#xff0c;能够获取接口调用的各种统计信…

编程笔记 html5cssjs 003 协作、约定与标准 50以内的乘法算式

编程笔记 html5&css&js 003 协作、约定与标准 50以内的乘法算式 一、代码二、解释 综合应用代码示例。50以内的乘法算式。 一、代码 <!DOCTYPE html> <html lang"en"> <head><title>20以内的乘法</title><meta charset&qu…

RocketMQ的事务消息是如何实现的?

RocketMQ的事务消息是通过 TransactionListener接口来实现的。 在发送事务消息时,首先向RocketMQ Broker 发送一条‘half消息’(半消息),半消息将被存储在broker端的事务消息日志中,但是这个消息还不能被消费者消费。 接下来,在半消息发送成功后,应用程序通过执行本地事务…

C#,煎饼排序问题(Pancake Sorting Problem)算法与源代码

1 煎饼排序问题 给定一个未排序的数组&#xff0c;任务是对给定数组进行排序。您只能在阵列上执行以下操作。 翻转&#xff08;arr&#xff0c;i&#xff09;&#xff1a;将数组从0反转为i 示例&#xff1a; 输入&#xff1a;arr[]{23、10、20、11、12、6、7} 输出&#xff1a…

开发Chrome扩展插件

1.首先开发谷歌chrome扩展插件&#xff0c;没有严格的项目结构目录&#xff0c;但是需要保证里面有一个mainfest.json文件 (必不可少的文件)。在这个文件里有三个属性必不可少&#xff1a;name、version、mainfest_version&#xff1b; // 清单文件的版本&#xff0c;这个必须写…

查看Linux服务器配置

# chkconfig --list # 列出所有系统服务 # chkconfig --list | grep on # 列出所有启动的系统服务 # ifconfig # 查看所有网络接口的属性 # iptables -L # 查看防火墙设置 # route -n # 查看路由表 # netstat -lntp # 查看所有监听端口 # netstat -antp # 查看所有已经建立的连…

二叉搜索树(BST)的创建及增,删,查,改(详解)

目录 初识二叉搜索树&#xff08;BST&#xff09;&#xff1a; 二叉搜索树查找元素&#xff1a; 二叉搜索树修改元素: 二叉搜索树中的增加元素&#xff1a; 二叉搜索树中的删除元素&#xff1a; 初识二叉搜索树&#xff08;BST&#xff09;&#xff1a; 一张图简要概括二…

Qt桌面白板工具其三(解决半透明桌面画布刷新透明像素时产生耗时,导致的画笔卡顿问题)

一、问题 前两篇文章写了很多有关桌面画板的实现方法&#xff0c;这个过程中&#xff0c;画笔的卡顿问题还是无法彻底解决。 先简单回顾一下我实现桌面画板的逻辑&#xff1b; 1.父窗口&#xff1a;一个透明窗口&#xff0c;通过设置带有透明度的QColor bg_color&#xff0c;以…

高级语言讲义2016计专(仅高级语言部分)

1.斐波那契序列的第n项可以表示成以下形式&#xff0c;编写一个非递归函数&#xff0c;返回该数列的第n项的数值 #include <stdio.h>int func(int n) {if(n1||n2)return 1;int p1,q1,num;for(int i3; i<n; i) {numpq;qp;pnum;}return num; } 2.在MXN的二维数组A中&am…

Django框架连接数据库

这里以同时连接sqlite、mysql、redis为例 首先要下载对应的sqlite、mysql、redis相应的模块插件 开始上代码 settings.py 配置文件 import os # 引入mysql模块 import pymysql # pymysql.install_as_MySQLdb()来确保pymysql能够兼容这些代码 pymysql.install_as_MySQLdb()# 数…

Go中的控制反转 IoC

以嵌入组合的方式实现控制反转 IoC: 控制反转是一种解耦思想&#xff0c;将原本耦合在业务逻辑中的控制逻辑单独拆出来实现&#xff0c;不再让业务逻辑在处理业务的同时还要去实现控制逻辑&#xff0c;而是专注处理业务。在业务逻辑代码中耦合进控制逻辑&#xff0c;会导致在编…