轻松解决Jetpack Compose中的一些痛点问题

公众号「稀有猿诉」        原文链接 轻松解决Jetpack Compose中的一些痛点问题

暑去秋来,金桂飘香,不知不觉中我们已经练完了『降Compose十八掌』,相信通过这一系列文章能够对Jetpack Compose有足够的理解,并能在实际项目中进行运用。今天将继续Compose之旅,总结一下Compose使用过程中经常会遇到的一些痛点问题,并学会如何优雅的解决这些问题。

banner

定义slot时要注明布局作用域

先来看一个比较常规的问题,Compose开发过程中,非常鼓励开发者把可以复用的部分抽象成为一个函数,然后接收一个尾部lambda作为参数进行差异化的定制。这种范式叫做slot模式,slot模式的好处在于能够大大加强代码复用,开发者在构建UI的时候,像搭积木那样把一个一个的slot叠在一起。Compose自己的API中都大量的采用了这种模式。

为了让slot更加的通用,我们需要明确传入的lambda与slot之间的约定,这就要求我们对lamdba的类型进行严格的限制。

首先要添加注解@Composable,这个是显而易见的,因为slot是为了绘制一些自定义UI元素而准备的,所以肯定是要加上@Composable,否则在lambda中无法写UI,因为非Composable不能调用Compose的方法。

另外,不是那么明显的就是这个lamdba的类型,要指定其Receiver,以限定它所在的布局。比如说slot是用在一个Column里面的,那么要给lamdba指定ColumnScope作为receiver,这样在实现lambada的时候就知道是作为Column的一部分,并且可以使用Column布局的特有相关参数,如左右居中和垂直排列:

@Composable
MyLayout(modifier: Modifier,content: @Composable ColumnScope.()->Unit
) {Column() {// 共用的一部分content()}
}// 调用的地方
MyLayout { // this = ColumnScope// 隐式this指针指向一个ColumnScope对象,就像在一个Column中一样// 定制的部分
}

UI元素很多都会涉及到居中,对齐的调整,以及内部元素的排列,而对齐和排列又会明确的受到所在父布局的影响,比如说Box与Column的对齐和排列方式就是不同的。所以在使用slot时一定要明确 标注它所在的布局,以让调用者能够明确地知道lambda所在的布局作用域。

扩展阅读:

  • Slotting in with Compose UI
  • Practical Compose Slot API example
  • Designing Slot APIs in Jetpack Compose
  • 初探 Jetpack Compose — Slot API

如何在ViewModel中使用平台相关的资源

我们在降Compose十八掌之『神龙摆尾』| Architecture中讨论过,ViewModel作为Domain层,目的是把逻辑尽可能的从UI层中抽出来,让UI尽可能的只做UI渲染。ViewModel也要做到平台独立,这样才方便移植和测试。ViewModel中吐出来的数据要是加工过的可以直接方便地在UI层展示的数据,如字符串或者图片。

但有一个问题,资源文件如何管理都是平台强相关的。对于要展示给用户的文案,也不可能直接把字符串传给UI,因为UI语言都要能够本地化以适应不同的国家和地区,当然了如果说不需要考虑多语言的问题,比如我的应用只给某一个语言使用,那当然也可以直接把处理好的字符串当作UiState传给UI层。

最为理想的解决方案就是ViewModel层定义一些状态码,对应着不同的提示语言,由UI负责一一对应的,把状态码再转成字符串。对于其他的资源也可以采用类似方式处理。这是从ViewModel输出到UI层的情况。

还会反过来,对于需要从UI层输入到ViewModel的资源,也是要去除平台的相关性,比如转成ViewModel中定义的状态码,或者转成原始数据类型String,或者转成平台无关的输入输出流等等。

字符串资源

对于Android平台来说,可以用一个简单的方式来解决字符串资源问题,因为资源的引用是一个整数,所以可以直接把资源的ID当作字段传给UI,Compose拿到后直接用函数stringResource取出来就可以了:

data class UiState(val loading: Boolean = false,@StringRes val errorMsg: Int = 0
)class HomeViewModel {val timeout = UiState(false, R.string.error_message_timeout)_state.update(timeout)
}// 在Compose中
HomeScreen() {Text(stringResource(uiState.errorMsg))
}

虽然说这并不太通用,因为换成其他平台时可能不是用资源ID来获取资源,但转成状态码的方式也会很容易,所以问题不大。

如果是输入的话,在Compose中直接读取资源变成String传给ViewModel就好了。

扩展阅读:

  • How should I get Resources(R.string) in viewModel in Android (MVVM and databinding)
  • Using String Resources in a ViewModel

图片资源

图片资源一般来说都是UI自己指定,但有些时候可能会有逻辑,比如一些需要经过运算才能得到的复杂的状态,其代表的Icon,由ViewModel来直接指定要好一些。图片资源也可以直接使用资源ID,然后在Compose中使用painterResource来获取:

data class UiState(@DrawableRes val icon: Int = 0
)// in ViewModel
val state = UiState(R.drawable.ic_windy)// in Compose
Icon(painterResource(uiState.icon))

如果是输入的话,可以在Compose中把图片资源转成输入流传给ViewModel去处理。

其他资源

其他资源如dimen或者color,也可以如法炮制。

输入的话,对于普通的资源像字符串资源,dimen或者color等读出来转成基础数据类型String,Int或者Array传给ViewModel就好。而像比较麻烦的资源,如Assets中的资源,就转成输入流传给ViewModel处理。

如何在常规函数中调用Composables

在Compose的开发过程中最为令人不爽的地方在于Compose 的API,只能在被注解@Composable标注的函数中调用,其他地方是无法调用的。一般来说,这个问题也不大,因为Compose的入口是肯定是一个composable啊,一坨坨的composables的调用最终会生成UI树。

但有些地方却跑出了Composable之外,比如像很多UI元素的事件响应,比如Button,它的事件响应onClick接收的就是一个普通的lambda:

@Composable
fun MainContent(modifier: Modifier = Modifier,serviceOn: Boolean,context: Context
) {Column() {Button(onClick = { AccessibilityHelper.gotoChronosSettings(context) },) {Text(stringResource(if (serviceOn) R.string.turn_off_service else R.string.enable_service))}}
}

在Button的onClick里面可以执行一些普通函数调用,比如调用ViewModel等,但是不可以调用Compose的API,因为它是非Composable的,已经跑到了Composable之外。有些场景,这会带来比较大的不方便。

响应点击按扭的方式可能有很多,有些是执行一些普通函数调用,但有些时候也会修改UI,大部分时候也会创建新UI,比如说会弹出对话框。对于修改UI,可以直接通过修改状态的值,状态的值发生改变会触发重组,进而UI状态就会改变(通过读取状态的值显示 不同的UI)。

对话框Dialog也是一个Composable,它只能被Composable调用,无法在Button的onClick中直接调用Dialog。解决的办法依旧是借助状态,用一个Boolean型值的状态,当其为true时显示Dialog,在Button的onClick中更改此状态为true,状态变了触发重组,在重组时值为true就会显示Dialog了:

@Composable
fun InputSettingsEntry(label: String,description: String,value: String,onChange: (String)->Unit
) {var showing by remember { mutableStateOf(false) }Button(onClick = { showing = true }) {Text(value)}if (showing) {InputDialog(title = label,message = description,value = value,onDismiss = { showing = false },onConfirm = {onChange(it)showing = false})}
}

另外,其实Dialog本身的一些事件响应也都是非Composable的,都是通过状态来控制Dialog的显示与否。

扩展阅读:

  • Not able to show AlertDialog from onClick in Jetpack Compose
  • Alert Dialog with Jetpack compose: A Step-by-Step Guide

总结

Jetpack Compose博大精深,看似简单就是一坨函数,但在实际项目使用中会遇到各种细节问题。遇到问题也不用慌,用我们的『降Compose十八掌』都能解决,没事就多读一读,理解了Compose的思想与原理,做到心中无剑,很多问题都能迎刃而解。

References

  • 10 Android Jetpack Compose Best Practices
  • 6 Jetpack Compose Best Practices for Optimizing Your App Performance

subscription

欢迎搜索并关注 公众号「稀有猿诉」 获取更多的优质文章!

保护原创,请勿转载!

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

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

相关文章

Linux memcg lru lock提升锁性能

目录 内核关于per memcg lru lock的重要提交: 计算虚拟地址转换基本机制 问题背景 swap换入流程 时奎亮的per memcg lru lock分享视频 内核关于per memcg lru lock的重要提交: f9b1038ebccad354256cf84749cbc321b5347497 6168d0da2b479ce25a4647d…

感知笔记:ROS 视觉- 跟随红球

- 目录 - 如何在 ROS 中可视化 RGB 相机。如何作为机器人切换主题。如何创建 blob 检测器。如何获取要跟踪的颜色的颜色编码。如何使用 blob 检测数据并移动 RGB 相机以跟踪 blob。 机器人技术中最常见的传感器是不起眼的 RGB 摄像头。它用于从基本颜色跟踪(blob 跟…

ssm自助购药小程序 LW PPT源码调试讲解

第二章开发技术介绍 此系统的关键技术和架构,Java技术、B/S结构、Ssm框架和Mysql数据库,是本系统的关键开发技术,对系统的整体、数据库、功能模块、系统页面以及系统程序等设计进行了详细的研究与规划。 2.1 系统开发平台 在线自助购药小程…

PMP--二模--解题--1-10

文章目录 4.整合管理--商业文件--商业论证(是否值得所需投资、高管们决策的依据)反映了:1、 [单选] 收到新项目的客户请求之后,项目经理首先应该做什么? 14.敏捷--角色--产品负责人PO–职责–1.创建待办列表并排序;2.确…

大数据概念与价值

文章目录 引言大数据的概念高德纳咨询公司的定义麦肯锡全球研究所的定义什么是大数据? 大数据的特征Volume(体积)Variety(种类)Velocity(速度)Value(价值)Veracity&#…

计算机毕业设计Python+Flask微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分析系统 大数据毕业设计 NLP文本分类 机器学习 深度学习 AI

首先安装需要的python库, 安装完之后利用navicat导入数据库文件bili100.sql到mysql中, 再在pycharm编译器中连接mysql数据库,并在设置文件中将密码修改成你的数据库密码。最后运行app.py,打开链接,即可运行。 B站爬虫数…

恢复已删除文件的可行方法,如何恢复已删除的文件

在清理 PC 或优化存储设备时无意中删除重要文件是一种常见的人为错误。不可否认,在批量删除文件时,您通常会一起删除垃圾文件和重要文件。您后来意识到一堆文件或文件中缺少一个重要的文档或文件。在这种情况下,您唯一的选择是寻找恢复已删除…

打点-heapdump信息泄露-shiro反序列化获得root权限shell

fscan 扫描结果 heapdump 下载 使用 JDumpSpider-1.1-SNAPSHOT-full.jar 分析,获取 shiro 密钥 验证 爆破利用链 命令执行

【小鹏汽车用户平台-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

iotop 命令:磁盘IO监控和诊断

一、命令简介 ​iotop​命令用于监视磁盘I/O,实时显示每个进程或线程的读写速率等信息。非常适合用于诊断系统中的I/O瓶颈。 ‍ ​​ ‍ 安装 iotop 在大多数Linux发行版中,iotop​可能不是预装的。可以使用包管理器来安装它。 例如,在…

uniapp出现 下拉框等组件被遮挡 的分析

目录 1. 问题所示2. 代码复现3. 解决方法3.1 下拉框被遮挡3.2 uni-collapse-item 无法下拉的问题 1. 问题所示 下拉框被遮挡的问题&#xff1a; uni-collapse-item组件无法下拉的问题&#xff1a; 2. 代码复现 博主的代码精简如下&#xff1a; <template><view>…

K-means 算法的介绍与应用

目录 引言 K-means 算法的基本原理 表格总结&#xff1a;K-means 算法的主要步骤 K-means 算法的 MATLAB 实现 优化方法与改进 K-means 算法的应用领域 表格总结&#xff1a;K-means 算法的主要应用领域 结论 引言 K-means 算法是一种经典的基于距离的聚类算法&#xff…

微信支付 02 加深理解密钥,加密解密,数字签名,数字证书

1.0 1.1 公钥&#xff08;Public Key&#xff09; 定义&#xff1a; 公钥是在非对称加密系统中使用的一个密钥&#xff0c;可以安全地公开和广泛分发。功能&#xff1a; 主要用于加密数据和验证数字签名。在加密过程中&#xff0c;公钥用于加密信息&#xff0c;只有对应的私钥…

计算机网络:概述 --- 体系结构

目录 一. 体系结构总览 1.1 OSI七层协议体系结构 1.2 TCP/IP四层(或五层)模型结构 二. 数据传输过程 2.1 同网段传输 2.2 跨网段传输 三. 体系结构相关概念 3.1 实体 3.2 协议 3.3 服务 这里我们专门来讲一下计算机网络中的体系结构。其实我们之前…

.NET常见的几种项目架构模式,你知道几种?(附带使用情况投票)

前言 项目架构模式在软件开发中扮演着至关重要的角色&#xff0c;它们为开发者提供了一套组织和管理代码的指导原则&#xff0c;以提高软件的可维护性、可扩展性、可重用性和可测试性。 假如你有其他的项目架构模式推荐&#xff0c;欢迎在文末留言&#x1f91e;&#xff01;&a…

道路红外目标检测数据集 6500张 带标注 voc yolo

道路红外目标检测数据集 6500张 带标注 voc yolo 道路红外目标检测数据集 数据集描述 该数据集旨在用于道路环境中的红外目标检测任务&#xff0c;涵盖了多种场景下的红外图像。数据集包含大量的图像及其对应的标注信息&#xff0c;可用于训练计算机视觉模型&#xff0c;以识…

006.MySQL_查询数据

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

Java中的Stack(栈)(如果想知道Java中有关Stack的知识点,那么只看这一篇就足够了!)

前言&#xff1a;栈&#xff08;Stack&#xff09;是一种基础且重要的数据结构&#xff0c;以其后进先出&#xff08;LIFO, Last In First Out&#xff09;的特性广泛应用于计算机科学和编程中。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼…

VS code EXPLORER 中不显示指定文件及文件夹设置(如.pyc, __pycache__, .vscode 文件)

VS code EXPLORER 中不显示指定文件及文件夹设置 引言正文方法1打开方式1打开方式2 方法2 引言 VS code 号称地表最强轻量级编译器&#xff0c;其最大的优势在于用户可以根据自己的需求下载适合自己的 extension。从而定制个性化的编译器。然而&#xff0c;本人今天遇到了一个…

【machine learning-七-线性回归之成本函数】

监督学习之cost function 成本函数权重、偏置如何实现拟合数据成本函数是如何寻找出来w和b&#xff0c;使成本函数值最小化&#xff1f; 在线性回归中&#xff0c;我们说到评估模型训练中好坏的一个方法&#xff0c;是用成本函数来衡量&#xff0c;下面来详细介绍一下 成本函数…