探索 Jetpack Compose

Flutter 与 Compose怎么选?小孩子才做选择 写在开头 其实自从 Jetpack Compose 面世以来,关于 Flutter 与 Compose 之间的选择问题就开始在 Android 开发中出现,就如同之前有 iOSer 纠结在 Flutter 和 SwiftUI 之间选谁一样,首先 Compose 是 Jetpack 系列的全新 UI 库,理解下这点!Compose 是 Jetpack 系列的成员之一,所以可以被应用到 Android 界面开发中,所以你也可以选择不用,用不用都能开发 Android 的 UI 。然后再说 Compose 出生的 阅读详情

前言

在大前端概念快速发展下,出现了很多声明式 UI 写法的语言或框架,像前端的 react、iOS 的 Swift UI,还有 Google 的 Flutter,但很少会听到 Android 原生有什么革命性的声明式 UI 的技术或支持跨平台,这不,Google 推出了 Compose。下面,文中会对 Compose 做一些简要的剖析,以及带大家简单认识一下 KMM 的神秘面纱。

Compose 是什么?

发展路线

  • 2019 年 Google I/O 大会上公布的新的 UI 库 Compose,Jetpack 中的一个新成员
  • 2021 年 7 月,Compose 终于迎来 1.0 正式版
  • 2022 年 2 月,Compose 发布 1.1 正式版

简介

官方:更少的代码、直观、加速开发、功能强大
声明式 UI;更简单的自定义;实时的、带交互的预览功能;还有更强的性能和功能。

AndroidView 与 Compose 写法对比

AndroidView 写法

普遍写在 xml,大多数命令式 UI,代码去指挥、去命令界面更新,但结合 DataBinding 能做到声明式,写的时候要注意层级,view 树 measure 多次测量耗时

既生瑜何生亮?

Compose 写法

声明式 UI,通过订阅机制可以自动的刷新 UI,并且是 diff,层级随便套,Compose 禁用了二次测量,但加入了一个新东西:Intrinsic Measurement,官方把它翻译做「固有特性测量」

所谓的 Intrinsic Measurement,指的是 Compose 允许父组件在对子组件进行测量之前,先测量一下子组件的「固有尺寸」,直白地说就是「你内部内容的最大或者最小尺寸是多少」


xml 的写法进行多次测量时,以每个子 view 需要二次测量为例
旧的测量复杂度.png
每个 View 的测量算法的时间复杂度是 O(2ⁿ)

而 Intrinsic Measurement 是怎样做的呢

compose测量复杂度.png
Compose 会先对整个组件树进行一次 Intrinsic 测量,然后再对整体进行正式的测量。这样开辟两个平行的测量过程,就可以避免因为层级增加而对同一个子组件反复测量所导致的测量时间的不断加倍了。复杂度从 O(2ⁿ) 降到了 O(n)

Compose 怎么用?

api 太多,不一一示例,力求举一反三,以点到面


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeStudyTheme {
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
                    Greeting()
                }
            }
        }
    }
}

@Composable
fun Greeting() {
    var addCount by remember { mutableStateOf(0) }
    Column {
        Text(
            text = "Hello World $addCount",
            modifier = Modifier.clickable { addCount += 1 }
        )
        for (i in 0 until addCount) {
            HelloWord(text = "我是第 ${i + 1} 个 动态 add 的 Text")
        }
    }
}

@Composable
fun HelloWord(text: String) {
    Text(text = text)
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeStudyTheme {
        Greeting()
    }
}

compose demo.png

Compose 简要原理

从上面的 demo 我们看到 Column、Text,还看到了 @Composable、remember 等,那我们深入分析下

@Composable

Compose 没有使用注解处理器,Compose 在 Kotlin 编译插件在类型检查和代码生成阶段工作,因此不需要使用注解处理器。这个注解更像是一个关键字,就像协程的 suspend 关键字一样,添加了 @Composable 注解时,就改变了这个函数类型,相同函数类型没有注解和有注解是不兼容的。

@Composable
fun HelloWord(text: String) {
    Text(text = text)
}

反编译代码如下:

public static final void HelloWord(String text, Composer $composer, int $changed) {
        int i;
        Composer $composer2;
        Intrinsics.checkNotNullParameter(text, "text");
        Composer $composer3 = $composer.startRestartGroup(1404424604,"C(HelloWord)7@159L17:Hello.kt#nlh07n");
        if (($changed & 14) == 0) {
            i = ($composer3.changed(text) ? 4 : 2) | $changed;
        } else {
            i = $changed;
        }
        if (((i & 11) ^ 2) != 0 || !$composer3.getSkipping()) {
            $composer2 = $composer3;
            TextKt.m855Text6FffQQw(text, null, Color.m1091constructorimpl(ULong.m2915constructorimpl(0)), TextUnit.m2481constructorimpl(0), null, null, null, TextUnit.m2481constructorimpl(0), null, null, TextUnit.m2481constructorimpl(0), null, false, 0, null, null, $composer2, i & 14, 0, 65534);
        } else {
            $composer3.skipToGroupEnd();
            $composer2 = $composer3;
        }
        ScopeUpdateScope endRestartGroup = $composer2.endRestartGroup();
        if (endRestartGroup != null) {
            endRestartGroup.updateScope(new HelloKt$HelloWord$1(text, $changed));
        }
    }

Composer 其实是贯穿整个 Composable 函数作用域的上下文,提供了一些创建内部 Group 等方法。内部的数据结构是 Slot Table

Slot Table 是一个在连续空间中存储数据的类型,底层是数组实现。但是区别在于它的剩余空间,称为 Gap。
Gap具有移动到任何区域的能力,所以在数据插入与删除时更高效。
Slot Table 其本质是一个线性的数据结构,所以支持将 View 树存储在 Slot Table 中。
根据 Slot Table 可移动插入点的特性,让View树在变动之后无需重新创建整个View树的数据结构。

remeber

remeber 是一个 Composable 函数,内部实现类似于委托,实现了 Composable 函数调用链中的对象记忆。
Composable 函数在调用链位置不变的情况下,调用 remember 即可获取上次调用时记忆的内容

  • 同一个 Composable 函数在不同位置被调用,其 remember 函数获取的内容也不同
  • 同一个 Composable 函数被多次调用,将会产生多个实例。每次调用都有其自己的生命周期

mutableStateOf

mutableStateOf 真正的内部实现是 SnapshotMutableStateImpl

fun <T> mutableStateOf(
    value: T,
    policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy()
): MutableState<T> = createSnapshotMutableState(value, policy)

internal actual fun <T> createSnapshotMutableState(
    value: T,
    policy: SnapshotMutationPolicy<T>
): SnapshotMutableState<T> = ParcelableSnapshotMutableState(value, policy)

internal class ParcelableSnapshotMutableState<T>(
    value: T,
    policy: SnapshotMutationPolicy<T>
) : SnapshotMutableStateImpl<T>(value, policy), Parcelable {
    ...
}

internal open class SnapshotMutableStateImpl<T>(
    value: T,
    override val policy: SnapshotMutationPolicy<T>
) : StateObject, SnapshotMutableState<T> {
    override var value: T
        get() = next.readable(this).value
        set(value) = next.withCurrent {
            if (!policy.equivalent(it.value, value)) {
                next.overwritable(this, it) { this.value = value }
            }
        }
}

在 SnapshotMutableStateImpl value 的 set 方法之中,其完成了对观察者的通知

Snapshot.kt

internal inline fun <T : StateRecord, R> T.overwritable(
    state: StateObject,
    candidate: T,
    block: T.() -> R
): R {
    var snapshot: Snapshot = snapshotInitializer
    return sync {
        snapshot = Snapshot.current
        this.overwritableRecord(state, snapshot, candidate).block()
    }.also {
        notifyWrite(snapshot, state)
    }
}

internal fun notifyWrite(snapshot: Snapshot, state: StateObject) {
    snapshot.writeObserver?.invoke(state)
}

Snapshot.current获取当前的Snapshot,具体场景分析如下:

  • 如果通过异步操作更新,因为 Snapshot 是一个 ThreadLocal ,所以会返回当前执行线程的 Snapshot
  • 如果当前执行线程的 Snapshot 为空时默认返回 GlobalSnapshot
  • 如果在Composable中直接对 mutableState 进行更新操作,当前 Composable 执行线程的 Snapshot 就是 MutableSnapshot

最终调用 notifyWrite 方法完成观察者的通知

那么问题来了,是在什么时候进行观察者的订阅呢?
我们看回 setContent 函数,经过层层调用会调到 ViewGroup.setContent

internal fun ViewGroup.setContent(
    parent: CompositionContext,
    content: @Composable () -> Unit
): Composition {
    GlobalSnapshotManager.ensureStarted()
    ....
}

internal object GlobalSnapshotManager {
    fun ensureStarted() {
        ...
        Snapshot.registerGlobalWriteObserver {
                channel.trySend(Unit)
        }
    }
}

Snapshot.kt

fun registerGlobalWriteObserver(observer: ((Any) -> Unit)): ObserverHandle {
            sync {
                globalWriteObservers.add(observer)
            }
            advanceGlobalSnapshot()
            return ObserverHandle {
                sync {
                    globalWriteObservers.remove(observer)
                }
                advanceGlobalSnapshot()
            }
}

private fun <T> advanceGlobalSnapshot(block: (invalid: SnapshotIdSet) -> T): T {
    val previousGlobalSnapshot = currentGlobalSnapshot.get()
    val result = sync {
        takeNewGlobalSnapshot(previousGlobalSnapshot, block)
    }

    // If the previous global snapshot had any modified states then notify the registered apply
    // observers.
    val modified = previousGlobalSnapshot.modified
    if (modified != null) {
        val observers: List<(Set<Any>, Snapshot) -> Unit> = sync { applyObservers.toMutableList() }
        observers.fastForEach { observer ->
            observer(modified, previousGlobalSnapshot)
        }
    }

    return result
}

advanceGlobalSnapshot 方法会将发生状态修改的值,通知给 observer,最终上文的notifyWrite 方法就会通知给 Compose,完成 UI 驱动

ComposeView

Compose 在渲染时并不会转化成View,而是只有一个入口 View,即 AndroidComposeView
我们声明的 Compose 布局在渲染时会转化成 NodeTree, AndroidComposeView 中会触发 NodeTree 的布局与绘制
总得来说,Compose 会有一个 View 的入口,但它的布局与渲染还是在 LayoutNode 上完成的,基本脱离了 View

Compose 树.png

public fun ComponentActivity.setContent(
    parent: CompositionContext? = null,
    content: @Composable () -> Unit
) {
    //判断ComposeView是否存在,如果存在则不创建
    if (existingComposeView != null) with(existingComposeView) {
        setContent(content)
    } else ComposeView(this).apply {
        //将Compose content添加到ComposeView上
        setContent(content)
        // 将ComposeView添加到DecorView上
        setContentView(this, DefaultActivityContentLayoutParams)
    }
}

在 setContent 的过程中,会创建 ComposeView 与 AndroidComposeView,其中AndroidComposeView 是 Compose 的入口,并添加到DecorView上
AndroidComposeView 在 dispatchDraw 中会通过 root 向下遍历子节点进行测量布局与绘制,这里是 LayoutNode 绘制的入口
在Android平台上,Compose 的布局与绘制已基本脱离 View 体系,但仍然依赖于 Canvas

AndroidComposeView.kt

override fun dispatchDraw(canvas: android.graphics.Canvas) {
        // Compose测量与布局入口
        measureAndLayout()
        
        // Compose绘制入口
        canvasHolder.drawInto(canvas) { root.draw(this) }
        ...
    }

    override fun measureAndLayout() {
        val rootNodeResized = measureAndLayoutDelegate.measureAndLayout()
        measureAndLayoutDelegate.dispatchOnPositionedCallbacks()
    }

AndroidComposeView 会通过 root,向下遍历它的子节点进行测量布局与绘制,这里就是 LayoutNode 绘制的入口

什么是 KMM

在说 KMM 之前,我们先来了解一下 Compose Multiplatform

Compose Multiplatform

  • 2021 年 12 月,JetBrains 发布了 Compose Multiplatform 1.0 正式版

Compose Multiplatform 可以看做是 Jetpack Compose 的超集,在 Jetpack Compose 的基础上扩展出了跨平台的能力,两者共享了大部分的核心公共 API,所以 Compose Multiplatform 的很多基础库均还是以 androidx.compose.xxx 作为包名,这使得已经通过 Jetpack Compose 实现的 Android 应用可以比较方便地移植到其它平台,两者具有完美的互操作性。

Compose Multiplatform 支持市面上的大部分主流平台

支持平台.png

支持平台.png
@ 图源 INFOQ 微信公众号

Compose Multiplatform 通过用不同的编译器编译同一份代码来生成各端的不同产物,从而达到跨平台的目的,最终的编译产物和目标平台完全相容。例如,通过 Kotlin/JVM 为 JVM 和 Android 平台生成 jar/aar 文件、通过 Kotlin/Native 为 IOS 平台生成 framework 文件、通过 Kotlin/JS 为 Web 平台生成 JavaScript 文件,最终调用的还是原生 API,这使得采用 Compose Multiplatform 不会导致性能损耗,且不会像 Flutter 那样明显增大应用体积。

Kotlin Multiplatform Mobile(KMM)

Compose Multiplatform 在移动端的跨平台框架子集叫做 Kotlin Multiplatform Mobile(KMM)。
和 Flutter 不同,KMM 并不追求在各个平台使用一套完全相同的 UI 和 代码,没有像 Flutter 那样内置一个统一的图型绘制引擎,因此 KMM 虽然支持多端复用 UI,但功能还比较弱,在构建 UI 时还是需要依赖于平台 API。KMM 侧重于在 UI 层以下共享一套适用于所有平台的通用业务逻辑,统一通过 Kotlin 来编写业务代码,并同时保持和原生开发语言(Java、Objective-C、Swift、JavaScript 等)之间的互通性,具备灵活性的同时也保留了原生编程的优势。

后话

思考点:

  1. 业务选择 Compose 时应该怎样循序过渡?
    支持原生 AndroidView 和 Compose 混用

  2. 目前 Compose 还有很长的路发展,该不该学和用?
    什么是未来?我不知道,但我知道,谷歌推过的都逐渐成为了开发主流

  3. 对中台思考

  • KMM 能解决两端统一性问题,人力资源问题
  • 往往来说直播中台更侧重于公共逻辑层,业务怎样写 view 不太关心但需要都能兼容好
  1. Compose 应该搭配什么架构开发?
  • MVVM、MVI?
    “没有最好的架构,只有最合适的架构”

参考

  • https://developer.android.com/jetpack/compose/documentation?hl=zh-cn
  • https://juejin.cn/post/6844903999347359751
  • https://rengwuxian.com/tag/compose/
Jetpack Compose 介绍和快速上手 是围绕着Composable函数建立的。要创建一个Composable函数,只需在函数名称中添加注解。Composable函数只能从其他Composable函数的范围内调用。为了更好的理解,定义一个函数,它包含了一个name参数,并使用这个参数来配置文本元素) {!!// Composable 函数一般用大写开头,为了和普通的函数作为区分可以让你在IDE中预览你的Composable函数,而不需要部署到设备上。但是有个限制, 需要预览的Composable函数必须不能有任何参数。 阅读详情

相关推荐

Android开发实战班 - 现代 UI 开发之 Jetpack Compose 基础

Jetpack Compose 的历史与发展Jetpack Compose 由 Google 于 2019 年发布,旨在为 Android 开发提供现代化的声明式 UI 框架。Jetpack Compose 1.0 于 2021 年正式发布,目前已成为 Android UI 开发的推荐方式。Jetpack Compose 的优势声明式编程: 使用声明式编程范式,代码更简洁、可读性更高。Kotlin 原生支持: 完全使用 Kotlin 编写,与 Kotlin 语言特性无缝集成。简化 UI 开发。

知道者 2397

什么是Jetpack Compose?带你走进Jetpack Compose~

一、Jetpack Compose的概念 Jetpack Compose是用于构建原生Android UI的现代工具包。 Jetpack Compose使用更少的代码,强大的工具和直观的Kotlin API,简化并加速了Android上的UI开发。这是Android Developers 官网对它的描述。 二、为什么我们需要一个新的UI 工具 在Android中,UI工具包的历史可追溯到至少10年前。自那时以来,情况发生了很大变化,例如我们使用的设备,用户的期望,以及开发人员对他们所使用的开发工具和语言的期

老皮的博客 8748

跨越移植陷阱:ESP-IDF下LVGL与ILI9341的组件化集成与常见避坑指南

本文详细解析了在ESP-IDF环境下将LVGL图形库与ILI9341显示屏驱动进行组件化集成的完整流程。重点介绍了移植过程中的关键配置策略、内存管理优化技巧以及常见问题解决方案,帮助开发者有效规避内存溢出、显示异常等典型陷阱,实现高效稳定的嵌入式GUI开发。

yhn456789的博客 623

新年就搞新技术,Jetpack Compose 完全开发手册,从入门到精通

为了可以进行模板式的开发,Google 在2018年推出了 Android Jetpack。现在 Google 的应用市场中,大部分 APP 已经开始使用 Android Jetpack。 Android Jetpack 组件的集合可以帮助我们写大量重复的代码的任务,并且可以简化复杂的任务,让我们的 BUG 减少,以便让我们把更多的精力放在业务逻辑上,放在打造应用本身上。 使用此架构能带来的具体好处如下: UI和业务逻辑解耦。 有效避免生命周期组件内存泄漏。 提高模块可测试性。 提高应用稳定

老皮的博客 2650

MacOS下微信小程序源码提取与逆向实战:从找到.wxapkg到完整还原

本文详细介绍了在MacOS系统下进行微信小程序源码提取与逆向分析的完整实战流程。从定位沙盒机制中的.wxapkg缓存文件,到搭建Node.js环境与配置wxappUnpacker工具链,再到执行核心反编译命令并处理分包等复杂情况,提供了清晰的操作步骤。文章还汇总了Node版本、依赖缺失、文件乱码等常见问题的解决方案,旨在帮助开发者、安全研究人员高效完成小程序安全审计与学习。

weixin_29246195的博客 1598

YOLOv8改进 - 注意力篇 - 引入CAA注意力机制

YOLOv8改进 - 注意力篇 - 引入CAA注意力机制

浪子L的博客 5223

探索Android Jetpack Compose的无限可能 —— Android Compose_samples项目深度解析

探索Android Jetpack Compose的无限可能 —— Android Compose_samples项目深度解析 在快速迭代的移动开发领域,Jetpack Compose作为谷歌力推的现代UI工具包,正引领着Android应用界面设计的新潮流。今天,我们向您隆重介绍一款宝藏项目——Android Compose Samples Repository,这不仅是一个项目,更是一扇通往Co...

gitblog_00032的博客 1074

9.23华为OD机试真题 新系统 - 小菊的寻宝之旅 (Java/Py/C/C++/Js/Go)

9.23华为OD机试真题 新系统 - 小菊的寻宝之旅 (Java/Py/C/C++/Js/Go)

算法大师! 985

探索 Android Jetpack Compose

传统的 Android UI 开发基于 XML 布局和 View 系统,随着应用复杂度的增加,代码的可维护性和扩展性面临诸多挑战。Jetpack Compose 则采用了全新的理念,允许开发者使用 Kotlin 代码直接构建 UI 组件,通过组合多个简单的组件来创建复杂的界面。Button(onClick = { /* 处理点击事件 */ },) {Text(text = "点击我")这种方式相较于传统的 XML 布局方式,代码更加简洁直观,逻辑与界面的结合更加紧密。

lrm2272699447的博客 1021

YOLOv8 超参数调优教程! 使用Ray Tune进行高效的超参数调优!

YOLOv8超参数调优教程!😎 使用Ray Tune进行高效的超参数调优!

Coding... 1万+

基于单光子探测的高重频多通道符合测距

TDC专栏之基于单光子探测的高重频多通道符合测距

sdau2005的博客 1202

Jetpack-Compose-Video-Games-Example:打造极致视频游戏探索体验

Jetpack-Compose-Video-Games-Example:打造极致视频游戏探索体验 项目介绍 Jetpack-Compose-Video-Games-Example 是一款基于 Jetpack Compose 构建的视频游戏探索应用。该应用通过优雅的 UI 设计,使用户能够轻松浏览和发现各种视频游戏。所有数据均来源于著名的 RAWG API,确保信息的实时性和准确性。 项目技术分析 ...

gitblog_00524的博客 1059

基于YOLOv8的水果新鲜程度检测系统设计与实现

数据采集与预处理模块:负责收集水果图像数据并进行标注和增强深度学习模型:基于YOLOv8的目标检测模型新鲜度评估模块:根据检测结果评估水果新鲜程度用户界面:提供友好的交互界面系统集成:将各模块整合为完整系统水果新鲜程度检测需要包含多种水果在不同新鲜度状态下的图像数据集。:包含5种常见水果(苹果、香蕉、橙子、葡萄、草莓)在不同新鲜度下的图像包含约8,000张图像,分为新鲜和腐烂两类AgriVision:大型农业图像数据集,包含水果检测和分类任务Fruit-360:包含120种水果的高质量图像。

YOLO 444

jetpack_在JetPack Compose中探索约束布局

jetpack 介绍 (Introduction) These days JetPack-compose is evolving rapidly; one of the significant developments I’ve observed recently is constraint-layout in compose. Constraint layout is a compelling ...

weixin_26739079的博客 1126

vs code , 配置 claude code 插件, 默认选项 : --dangerously-skip-permission

摘要:本文介绍如何在VS Code中为Claude Code插件配置--dangerously-skip-permission参数,包含两种方法:图形界面设置(适合新手)和直接编辑settings.json(精准配置)。该参数会跳过权限检查,仅建议在本地测试环境中使用。配置后需通过命令面板验证参数是否生效,并注意安全风险,避免在生产环境使用。多参数配置时需用数组格式,不同版本插件可能键名略有差异。

AI天才研究院 4991

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

探索未来UI——Neumorphism与Jetpack Compose的美妙碰撞

探索未来UI——Neumorphism与Jetpack Compose的美妙碰撞 在寻求创新和前沿设计的时代,Android开发界迎来了一位新星——将Neumorphism设计理念融入Jetpack Compose的【Neumorphism UI with Jetpack Compose】库。本文旨在带您深入了解这一开源项目,探索它如何以优雅的方式结合新旧视觉语言,为您的应用赋予独特的魅力。 项目...

gitblog_01106的博客 838

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

探索Jetpack Compose的咖啡饮品应用

探索Jetpack Compose的咖啡饮品应用 在这个数字化的时代,构建美观且易用的移动应用变得越来越重要。Android平台的开发世界也不例外,Google推出了一项革命性的UI工具包——Jetpack Compose,它为开发者提供了更简洁、更直观的方式来构建原生Android界面。今天,让我们一起探索一个用Jetpack Compose打造的优雅咖啡饮品应用——Coffee Drinks。...

gitblog_00034的博客 497

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

探索Jetpack Compose的神奇:Compose Modifiers Playground

探索Jetpack Compose的神奇:Compose Modifiers Playground 在Android开发领域,Jetpack Compose的兴起如一股清风,带来了高效、直观的UI构建方式。今天,我们要推荐的是一个让开发者深入学习和实践Compose修饰符的神器——Compose Modifiers Playground。这是一个专为IntelliJ IDEA设计的插件,旨在通过交...

gitblog_00099的博客 1062

Jetpack Compose 深入探索系列四: Compose UI

Compose UI 是一个 Kotlin 多平台框架。它提供了通过可组合函数发出 UI 的构建块和机制。除此之外,这个库还包括 Android 和 Desktop 源代码,为 Android 和 Desktop 提供集成层。当使用 Compose runtime 集成 UI 时,目标是构建用户可以在屏幕上体验的布局树。这个树是通过执行发出 UI 的 Composable 函数来创建和更新的。用于树的节点类型只有 Compose UI 知道,所以 Compose runtime 可以不知道它。即使 Comp

川峰的博客 3877

Jetpack Compose 深入探索系列三:Compose runtime

slot table(插槽表)是一个优化的内存结构,runtime 使用它来存储组合的当前状态。它在初始组合时填充数据,并在每次重新组合时更新。我们可以把它看作是所有Composable函数调用的跟踪,包括它们在源码中的位置、参数、记住的值、CompositionLocals等等。它包含了在合成过程中发生的一切内容。所有这些信息将被 Composer 稍后用于生成下一个更改列表,因为对树的任何更改总是依赖于当前状态。 slot table 记录Composable的状态,而 change list 则是对

川峰的博客 1310

Jetpack Compose 现代应用界面特性探索

Jetpack Compose作为Android UI开发的未来,正在重新定义我们构建用户界面的方式。通过本博客,我们不仅探索了11个令人兴奋的新特性,还深入分析了其与Android系统架构的深度整合,并分享了实际开发中的BUG发现与解决经验。在当今竞争激烈的移动应用市场中,拥有一个现代化、高性能且视觉上吸引人的用户界面是成功的关键。Jetpack Compose不仅使这一切成为可能,而且让整个开发过程变得更加高效和愉快。

huangxuanjing的博客 864

探索 Jetpack Compose 的魅力:《Jetpack Compose实战教程》资源全面解析

探索 Jetpack Compose 的魅力:《Jetpack Compose实战教程》资源全面解析 去发现同类优质开源项目:https://gitcode.com/ 在安卓开发的璀璨星空中,Jetpack Compose 如同一颗耀眼的新星,以其简洁高效的声明式编程模型,让UI设计变得前所未有的直观与轻松。今天,我们为您特别推荐源自Kodeco的《Jetpack Compose实战教程》配套资源...

gitblog_00062的博客 657

探索Joomia:一款基于Jetpack Compose的虚拟购物应用

探索Joomia:一款基于Jetpack Compose的虚拟购物应用 项目介绍 Joomia 是一款使用Jetpack Compose构建的虚拟购物应用,它通过消费FAKE STORE API来模拟真实的购物体验。尽管API的某些端点(如添加商品到购物车、用户注册等)并未实现实际功能,但Joomia仍然提供了一系列精美的UI界面,为用户带来视觉上的享受。此外,项目欢迎开发者贡献代码,共同完善这一...

gitblog_00199的博客 1036

Jetpack Compose 深入探索系列二:Compose 编译器

Jetpack Compose由一系列的库组成,但我们需要重点关注三个特定的库:Compose compiler、Compose runtime 和 Compose UI。 其中 Compose编译器 和 Compose runtime 是Jetpack Compose的支柱。从技术上讲,Compose UI 不是Compose体系结构的一部分,因为运行时和编译器被设计为通用的,并由符合其需求的任何客户端库使用。Compose UI 只是其中一个可用的客户端。还有其他的客户端库正在开发中,比如JetBra

川峰的博客 1921

探索Bonsai:Jetpack Compose中的树状视图新星

探索Bonsai:Jetpack Compose中的树状视图新星 在当今高度交互的移动和桌面应用中,高效展示层次结构数据变得日益重要。为此,一款名为 Bonsai 的开源库映入我们的眼帘,它为Kotlin和Jetpack Compose生态带来了强大的树状视图解决方案。 项目介绍 Bonsai,以其日本盆栽艺术之名命名,象征着精致与精简,在代码的世界里呈现了无限深度的树状结构,其核心在于简洁易用的...

gitblog_00446的博客 921
上一篇: LeakCanary 源码深挖
下一篇: Android 协程使用到原理详解
胡小明同学
博客等级 码龄10年 35粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值