Jetpack Compose 架构层

点击查看:Jetpack Compose 架构层 官网

本页面简要介绍了组成 Jetpack Compose 的架构层,以及这种设计所依据的核心原则。

Jetpack Compose 不是一个单体式项目;它由一些模块构建而成,这些模块组合在一起,构成了一个完整的堆栈。通过了解组成 Jetpack Compose 的不同模块,您可以:

  • 使用适当的抽象级别来构建应用或库
  • 了解何时可以“降级”到较低级别,以获取更多的控制权或更高的自定义程度
  • 尽可能减少依赖项

Jetpack Compose 的主要层包括:
在这里插入图片描述
图 1. Jetpack Compose 的主要层。
每一层均基于较低的层逐级构建,并通过组合功能来创建更高级别的组件。每一层都是基于较低层的公共 API 构建的,用于验证模块边界,还支持您根据需要替换任何层。让我们自下而上地分析这些层。

运行时
此模块提供了 Compose 运行时的基本组件,例如 remember、mutableStateOf、@Composable 注释和 SideEffect。如果您只需要 Compose 的树管理功能,而不需要其界面,则可以考虑直接基于此层进行构建。

界面
界面层由多个模块(ui-text、ui-graphics 和 ui-tooling 等)组成。这些模块实现了界面工具包的基本组件,例如 LayoutNode、Modifier、输入处理程序、自定义布局和绘图。如果您只需要用到界面工具包的基本概念,则可以考虑基于此层进行构建。

基础
此模块为 Compose 界面提供了与设计系统无关的构建块,例如 Row 和 Column、LazyColumn、特定手势的识别等。您可以考虑基于基础层构建自己的设计系统。

Material
此模块为 Compose 界面提供了 Material Design 系统的实现,同时提供了一个主题系统以及若干样式化组件、涟漪效果指示元素和图标。在您的应用中使用 Material Design 时,不妨基于此层进行构建。

设计原则

Jetpack Compose 的一个指导原则是提供可以组合在一起的重点突出的小块功能片段,而不是几个单体式组件。这种方法有许多优点。

控制

更高级别的组件往往能完成更多操作,但您拥有的直接控制权较少。如果您需要更多控制权,可以“下拉”使用较低级别的组件。

例如,如果您想为某个组件的颜色添加动画效果,可以使用 animateColorAsState API:

val color = animateColorAsState(if (condition) Color.Green else Color.Red)

不过,如果您需要组件始终以灰色开头,则不能使用此 API。您可以改为下拉菜单使用较低级别的 Animatable API:

val color = remember { Animatable(Color.Gray) }
LaunchedEffect(condition) {color.animateTo(if (condition) Color.Green else Color.Red)
}

较高级别的 animateColorAsState API 本身基于较低级别的 Animatable API 构建而成。使用较低级别的 API 的过程更为复杂,但可提供更多的控制权。请选择最符合您需求的抽象化级别。

自定义

通过将较小的构建块组合成更高级别的组件,可大幅降低按需自定义组件的难度。例如,可以考虑使用 Material 层提供的 Button 的实现:

@Composable
fun Button(// …content: @Composable RowScope.() -> Unit
) {Surface(/* … */) {CompositionLocalProvider(/* … */) { // set LocalContentAlphaProvideTextStyle(MaterialTheme.typography.button) {Row(// …content = content)}}}
}

Button 由 4 个组件组合而成:

  1. Material Surface:用于提供背景、形状和点击处理方式等。
  2. CompositionLocalProvider:用于在启用或停用相应按钮时更改内容的 Alpha 值
  3. ProvideTextStyle:用于设置要使用的默认文本样式
  4. Row:用于为相应按钮的内容提供默认布局政策

为了使结构更加清晰,我们省略了一些参数和注释,但整个组件只有 40 行左右的代码,因为它只是组合了这 4 个组件来实现该按钮。Button 等组件会自行判断它们需要公开哪些参数,同时在实现常见的自定义项和可能使组件更难使用的参数突增之间创造平衡。例如,Material 组件可提供 Material Design 系统中指定的自定义项,这样可以轻松遵循 Material Design 原则。

不过,如果您希望在组件参数之外进行自定义,则可以“降级”某个级别并复刻某个组件。例如,Material Design 指定按钮应具有纯色背景。如果您需要渐变背景,Button 参数就不适用了,因为它不支持此选项。在此类情况下,您可以将 Material Button 实现作为参考,并构建您自己的组件:

@Composable
fun GradientButton(// …background: List<Color>,modifier: Modifier = Modifier,content: @Composable RowScope.() -> Unit
) {Row(// …modifier = modifier.clickable(onClick = {}).background(Brush.horizontalGradient(background))) {CompositionLocalProvider(/* … */) { // set material LocalContentAlphaProvideTextStyle(MaterialTheme.typography.button) {content()}}}
}

上述实现继续使用 Material 层中的组件,例如 Material 的当前内容 Alpha 值和当前文本样式的概念。不过,它会将 Material Surface 替换为 Row 并设置其样式,以获得所需的外观。

注意:当“降级”到较低层以自定义组件时,请确保不会因忽视无障碍功能支持等原因而使任何功能发生降级。您要为哪个组件创建分支,就应以哪个组件作为指导。

如果您根本不想使用 Material 概念(例如,如果您要构建自己的定制设计系统),则可以选择仅使用基础层组件:

@Composable
fun BespokeButton(// …backgroundColor: Color,modifier: Modifier = Modifier,content: @Composable RowScope.() -> Unit
) {Row(// …modifier = modifier.clickable(onClick = {}).background(backgroundColor)) {// No Material components usedcontent()}
}

Jetpack Compose 为最高级别的组件保留了最为简洁的名称。例如,androidx.compose.material.Text 基于 androidx.compose.foundation.text.BasicText 构建。这样一来,如果您想替换更高级别,则可以为自己的实现提供更易于发现的名称。

注意:为组件创建分支意味着,您不会从上游组件的任何未来增补项或 bug 修复中受益。

选择合适的抽象化级别

Compose 以构建可重复使用的分层组件作为理念,这意味着您不应该始终以构建较低级别的构建块为目标。许多较高级别的组件不仅能够提供更多功能,而且通常还会融入最佳实践,例如支持无障碍功能等。

例如,如果您想为自己的自定义组件添加手势支持,可以使用 Modifier.pointerInput 从头开始构建;但在此之上还有其他更高级别的组件,它们可以提供更好的起点,例如 Modifier.draggable、Modifier.scrollable 或 Modifier.swipeable。

一般来讲,最好基于能提供您所需功能的最高级别的组件进行构建,以便从其包含的最佳实践中受益。

了解详情

如需查看构建自定义设计系统的示例,请参阅 Jetsnack 示例。

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

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

相关文章

VSCODE include错误 找不到 stdio.h

解决办法&#xff1a; Ctrl Shift P 打开命令面板&#xff0c; 键入 “Select Intellisense Configuration”&#xff08;下图是因为我在写文章之前已经用过这个命令&#xff0c;所以这个历史记录出现在了第一行&#xff09; 再选择“Use gcc.exe ”&#xff08;后面的Foun…

C语言-数组指针与指针数组

一、简介 对于使用C语言开发的人来说&#xff0c;指针&#xff0c;大家都是非常熟悉的。数组&#xff0c;大家也同样熟悉。但是这两个组合到一起的话&#xff0c;很多人就开始蒙圈了。这篇文章&#xff0c;就详细的介绍一下这两个概念。 指针数组和数组指针&#xff0c;听起来非…

PyTorch概述(二)---MNIST

NIST Special Database3 具体指的是一个更大的特殊数据库3&#xff1b;该数据库的内容为手写数字黑白图片&#xff1b;该数据库由美国人口普查局的雇员手写 NIST Special Database1 特殊数据库1&#xff1b;该数据库的内容为手写数字黑白图片&#xff1b;该数据库的图片由高…

互联网广告投放与IP地理位置定位

随着互联网的发展和普及&#xff0c;互联网广告投放成为各行业推广营销的重要方式之一。而结合IP地理位置定位技术&#xff0c;可以实现精准定向&#xff0c;提高广告投放的效果和精准度。IP数据云将探讨互联网广告投放与IP地理位置定位的关系&#xff0c;分析其优势和应用场景…

动态规划算法学习(基础)

做题步骤&#xff1a; 确定dp数组的含义(一维或者二维) 获取递推公式 dp数组如何初始化 确定遍历顺序 打印dp数组&#xff08;检查&#xff09; 题目&#xff1a; 1. 斐波那契数 509 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 …

留子厨房开发日志

以下记录了使用go语言框架Beego&#xff0c;Mysql数据库&#xff0c;Redis数据库实现一个点菜/菜谱应用API的全过程。 技术方案 github地址 数据库设计 新建数据库&#xff1a; CREATE DATABASE menu;新建数据表&#xff1a; CREATE TABLE menu ( id int(10) unsigned NOT …

2024 CKS 题库 | 11、AppArmor

不等更新题库 CKS 题库 11、AppArmor Context: APPArmor 已在 cluster 的工作节点node02上被启用。一个 APPArmor 配置文件已存在&#xff0c;但尚未被实施。 Task: 在 cluster 的工作节点node02上&#xff0c;实施位于 /etc/apparmor.d/nginx_apparmor 的现有APPArmor 配置…

Python 实现 ADTM 指标计算:股票技术分析的利器系列(9)

Python 实现 ADTM 指标计算&#xff1a;股票技术分析的利器系列&#xff08;9&#xff09; 介绍算法解释 核心代码rolling函数介绍计算 DTMnp.where 使用介绍np.maximum 计算 DBM计算 STM计算 SBM计算 ADTM 完整代码 介绍 ADTM&#xff08;动态买卖气指标&#xff09;是一种用…

C++奇怪的 ::template

答疑解惑 怎么会有::template的写法 起初 在阅读stl的源码的时候&#xff0c;发现了一条诡异的代码 // ALIAS TEMPLATE _Rebind_alloc_t template<class _Alloc,class _Value_type> using _Rebind_alloc_t typename allocator_traits<_Alloc>::template rebind…

【misc | CTF】攻防世界 simple_transfer

天命&#xff1a;这题其实不简单啊 拿到流量包&#xff0c;丢进去wireshare&#xff0c;题目都说了flag在里面 ctrl f 直接搜索字符串 右键&#xff0c;追踪流 -> TCP流 查找 .pdf 文件&#xff0c;其实这里思路是比较奇怪的&#xff0c;毕竟是的确比较多内容&#xff0c…

基于PostGIS的慢查询引起的空间索引提升实践

目录 前言 一、问题定位 1、前端接口定位 2、后台应用定位 3、找到问题所在 二、空间索引优化 1、数据库查询 2、创建空间索引 3、geography索引 4、再看前端响应 总结 前言 这是一个真实的案例&#xff0c;也是一个新入门的工程师很容易忽略的点。往往在设计数据库的…

NestJS入门4:MySQL typeorm 增删改查

前文参考&#xff1a; NestJS入门1 NestJS入门2&#xff1a;创建模块 NestJS入门3&#xff1a;不同请求方式前后端写法 1. 安装数据库相关模块 npm install nestjs/typeorm typeorm mysql -S 2. MySql中创建数据库 ​ 3. 添加连接数据库代码 app.module.ts ​ import { M…

给自己留个备忘,blender是右手坐标系

所谓右手坐标系&#xff0c;就是三个轴的方向和右手三根手指的方向一致&#xff08;当然&#xff0c;有要求的&#xff0c;这个要求是大拇指指向x轴方向&#xff0c;食指指向y轴方向,中指指向z轴方向&#xff09;。 不过blender默认是z轴朝上的&#xff0c;如下图。 右手坐标系…

element导航菜单el-menu添加搜索功能

element导航菜单-侧栏&#xff0c;自带的功能没有搜索或者模糊查询。 找了找资料 找到一个比较可行的&#xff0c;记录一下&#xff1a; //index.vue的代码 <div style"overflow:auto"><el-menu :default-active"$route.path":default-openeds&…

<网络安全>《49 网络攻防专业课<第十三课 - 华为防火墙的使用(2)>

6 防火墙的防范技术 6.1 ARP攻击防范 攻击介绍 攻击者通过发送大量伪造的ARP请求、应答报文攻击网络设备&#xff0c;主要有ARP缓冲区溢出攻击和ARP拒绝服务攻击两种。 ARP Flood攻击&#xff08;ARP扫描攻击&#xff09;&#xff1a;攻击者利用工具扫描本网段或者跨网段主机时…

构造器详解

定义: 是一种特殊类型的方法&#xff0c;用于创建对象时初始化对象的状态。 使用new关键字创建对象 构造器特点: 1.和类名相同 2.没有返回值 public class Person {String name;public Person() {this.name"John";}}public class Test {public static void main…

vue2+element医院安全(不良)事件报告管理系统源代码

目录 安全不良事件类型 源码技术栈 医院安全&#xff08;不良&#xff09;事件报告管理系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件…

测试环境搭建整套大数据系统(六:搭建sqoop)

一&#xff1a;下载安装包 https://archive.apache.org/dist/sqoop/ 二&#xff1a;解压修改配置。 tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /opt cd /opt mv sqoop-1.4.7.bin__hadoop-2.6.0/ sqoop-1.4.7修改环境变量 vi /etc/profile#SQOOP_HOME export SQOOP_…

nginx-------- 高性能的 Web服务端 (四)

一、高级配置 1 .1网页的状态页 基于nginx 模块 ngx_http_stub_status_module 实现&#xff0c;在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module&#xff0c;否则配置完成之后监测会是提示语法错误注意: 状态页显示的是整个服务器的状态,而非虚拟主机…

【Android 性能优化:内存篇】——ExoPlayer 释放后内存没有恢复问题探索

背景 最近笔者承接项目的内存优化指标&#xff0c;在内存调研的过程中发现项目中视频播放结束后&#xff0c;内存没有恢复到播放前到水平。项目中用的 EXO 版本为2.19.1&#xff0c;并且笔者自己也写了个简单的 Demo&#xff0c;发现也是如此。虽然有一些偏门方法可以优化&…