如何在 Jetpack Compose 中调试重组
本文是 Compose 相关的偏进阶文章,给出了一些可用于 Compose 调试的方法,并阐释了一些性能优化方面的小细节。
本文译自 How can I debug recompositions in Jetpack Compose?
原作者:https://twitter.com/vinaygaba
译:FunnySaltyFish
自从 Jetpack Compose 的第一个稳定版本上线以来,已经过去了好几个月(译注:本文写于2022年4月)。多家公司已经使用了 Compose 来参与构建他们的 Android 应用程序,成千上万的 Android 工程师每天都在使用 Jetpack Compose 。
虽然已经有大量的文档可以帮助开发人员接受这种新的编程模式,但仍有这么个概念让许多人摸不着头脑。它就是Recomposition,Compose 赖以运作的基础。
重组是在输入更改时再次调用可组合函数的过程。当函数的输入发生更改时,它便会发生。当 Compose 基于新输入进行重组时,它仅调用可能已更改的函数或 lambda,并跳过其余部分。通过跳过所有未更改参数的函数或 la ...
Jetpack Compose 自定义布局+物理引擎 = ?
效果废话不说,先上图!
所对应代码大致为:
123456789101112131415161718192021222324val physicsConfig = PhysicsConfig()PhysicsLayout(modifier = modifier, physicsLayoutState = physicsLayoutState, boundSize = boundSize.toFloat()) { RandomColorBox(modifier = Modifier .size(40.dp) .physics(physicsConfig, initialX = 300f, initialY = 500f)) // This one has a circle shape // so you need to modify it with not only a `clip()` Modifier to make it "looks like" a circle // but also a `phy ...
Jetpack Compose LazyGrid全解
本文参考自谷歌官方视频Lazy layouts in Compose - YouTube,基于Compose 1.2.0-beta02(截止发文时最新版本)
前言前段时间Compose发布了1.2.0beta版本,最大的变化之一莫过于LazyLayout去除了实验性标志。所以接下来,咱们不妨一起看看LazyGrid的用法(嗯?这和上一句有关系吗)
LazyGrid包含两种微件:LazyVerticalGrid和LazyHorizontalGrid。两者内部均由LazyLayout实现(包括LazyColumn和LazyRow也是由LazyLayout实现的)。不过今天我们不去考虑底层的LazyLayout,单纯着眼于Grid们
为行文方便,此处仅以LazyVerticalGrid为例。
基本使用最简单的使用如下所示:
12345678910111213@Composablefun SimpleLazyGrid(){ LazyVerticalGrid( modifier = Modifier.fillMaxWidth(), // 固定两列 ...
Jetpack Compose 自定义绘制——高仿Keep周运动数据页面
废话之前先上图吧,如果不是有人告诉,你可以一眼看出哪个是真哪个是假吗?
仿制整个页面(仅仅页面)大概花了我两个小时,不过仅仅是静态的、不可点击的。图有形似而无功能。
自定义绘制Jetpack Compose 自定义绘制的文章其实并不少了,基本代码上和View体系基本类似,就是方法上有所差异
详细的内容可以见其他作者的文章,如
路很长OoO的JetPack-Compose - 自定义绘制 - 掘金 (juejin.cn)
RugerMc的使用 Jetpack Compose 完成自定义绘制 - 掘金 (juejin.cn)
……
我就不赘述
上述代码中,中间那块数据图就是自己画的(Keep 用的是 RecyclerView)。大致上,包括这几个部分
四个浅色矩形和底部文字
三条浅色横线和一条深色横线
中间的深色矩形和底部文字
中间竖线、矩形和底部的小线段
其中1->3的顺序不能更改,因为三条浅色横线在浅色矩形之上,但是在深色矩形之下
浅色矩形页面上一共4个浅色矩形,观察Keep可知,它们的高度与 对应数据和运动记录中最长时间之比 成正比
所以先计算一下最大的数字,找一些变 ...
博客迁移完毕
鉴于 CDN jsdelivr 难以访问,以及 Gitee 于 2022/03/25 突然禁止图床链接,我于 2022/03/26-2022/03/28 进行了博客迁移工作主要内容包括:
更换 jsdelivr 为 cdn.jsdelivr.net
更换 图片链接 到个人服务器
基于 Lsky Pro 2.0 搭建新图床,之后的图片将保存于自建图床完毕!
更新:2022年6月23日,我又将 cdn 迁回 jsdelivr
深入Jetpack Compose——布局原理与自定义布局(四)
上一篇文章,我们接触了固有特性测量。这一篇,我们将探索ParentData
ParentData曾经的例子让我们回忆一下第一篇文章中提到的例子,为了实现如下效果
我们当时使用了这样一串修饰符:
12345Box(modifier = Modifier .fillMaxSize() .wrapContentSize(align = Alignment.Center) .size(50.dp) .background(Color.Blue))
也就是说,子微件的居中是它自己的wrapContentSize(align = Alignment.Center)调整的结果。那么,如果我们现在知道了子微件(小的蓝色方块)被包裹在另一个方块(Box)里,我们能不能让父布局帮忙确定居中位置呢?
答案是可以的!Box 在其content作用域中提供了align 方法,这可以让子微件自行告知父布局:我需要居中
12345678910111213@Composableinline fun Box( modifi ...
深入Jetpack Compose——布局原理与自定义布局(三)
在上一篇[文章](深入Jetpack Compose——布局原理与自定义布局(二))中,我们探索了Modifier的本质和原理。这一次我们看看Compose体系中的一个重要特性:固有特性测量。
固有特性测量或许不少人已经知道,Compose为了提高测绘性能,强行规定了每个微件只能被测量一次。也就是说,我们不能写出类似下面这样的代码:
123val placeables = measurables.map { it.measure(constrains) }// 尝试测量第二次,直接报错val placeablesSecond = measurables.map { it.measure(constrains) }
一个小问题那么接下来我们看一个小例子。我们想实现一个菜单,菜单里面有几个菜单栏。于是我们写出了类似这样按的代码
但是效果不怎么样,因为每个Text的宽度不一样。看起来有点丑
你可能会说,要解决这个问题很简单,为每个Text 添加修饰符fillMaxWidth,让它占满即可。效果如下:
但是这样新的问题来了:由于每个Text的C ...
深入Jetpack Compose——布局原理与自定义布局(二)
在上一篇文章深入Jetpack Compose——布局原理与自定义布局(一) - 掘金 (juejin.cn) 中,我们大致了解了Layout过程并简单实现了两个自定义布局。本次让我们将目光转向Modifier和固有特性测量
本文部分参考自Android官方视频:Deep dive into Jetpack Compose layouts
Modifier本质关于Modifier的本质,RugerMc大佬在图解 Modifier 实现原理 ,竟然如此简单这篇文章中已经解释地非常清楚了,我就不画蛇添足了。不过为了后续行文方便,我还是在此简单说几点:
Modifier 是个接口,包含三个直接实现类或接口:伴生对象 Modifier、内部子接口Modifier.Element和CombinedModifier。
伴生对象Modifier是日常使用最多的,后面两者均为内部实现,实际开发中无需关注
Modifier.xxx()方法实际上会创建一个Modifier接口的实现类的实例。如Modifier.size()会创建SizeModifer实例
123456@Stablefun Modifi ...
深入Jetpack Compose——布局原理与自定义布局(一)
Jetpack Compose 正式版发布也已半年了,对我来说,应用到项目中也很久了(参见本人开源项目:译站)。 目前很多文章还集中于初探上,因此萌生了写作本文的想法,算是为Compose中文资料提供绵薄之力。
本文的内容来自Android官方视频:Deep dive into Jetpack Compose layouts
总览Jetpack Compose 中,单个可组合项被显示出来,总体上经历三个过程
Composition(组合) -> Layout(布局) -> Drawing(绘制) ,其中Layout阶段又存在两个方面的内容:Measure(测量) 和 Place(摆放)
今天我们主要着眼于 Layout 阶段,看看各个 Composable 是如何正确确定各自位置和大小的
LayoutLayout阶段主要做三件事情:
测量所有子微件的大小
确定自己的大小
正确摆放所有子元素的位置
为简化说明,我们先给出一个简单例子。该例子中,所有元素只需要遍历一次。
如下图的 SearchResult微件,它的构成如下:
现在我们来看看Layout过程在这个例子中是什 ...
Jetpack Compose 中优雅完成数据持久化
Compose出来也好久了,各种remember和LocalXXX.current也是用得越来越熟。如果能在保持上述写法一致性的情况下完成数据的持久化工作,不是显得挺优雅的吗?基于此,我写出了开源库:ComposeDataSaver: 在Jetpack Compose中优雅完成数据持久化简单一瞥:
12345// booleanExample 初始化值为false// 之后会自动读取本地数据var booleanExample by rememberDataSaverState(KEY_BOOLEAN_EXAMPLE, false)// 直接赋值即可完成持久化booleanExample = true
可还行?
ComposeDataSaver项目有以下特点:
简洁:近似原生的写法
低耦合:抽象接口,不限制底层保存算法实现
轻巧:默认不引入除Compose外任何第三方库
灵活:支持基本的数据类型和自定义类型
引入在settings.gradle引入jitpack仓库位置
12345dependencyResolutionManagement { reposito ...