Jetpack Compose简介

embedded/2024/9/24 17:13:41/

文章目录

Jetpack_Compose_2">Jetpack Compose简介

概述

Jetpack Compose是谷歌推出的全新Android UI开发框架,它采用更为先进的声明式开发思想,极大地提升了应用界面的开发效率,Compose代码与基于Android View系统的传统代码可以共存。

声明式UI和命令式UI

  • 命令式用命令的方式告诉计算机如何去做事情(how to do),计算机通过执行命令达到结果。
  • 声明式直接告诉计算机用户想要的结果(what to do),计算机自己去想该怎么做。

Android View 属于命令式的编程范式,使用 XML 定义的布局是静态的,无法根据响应状态自行更新。开发者需要通过 findViewById 等获取视图对象,然后通过命令式的代码调用对象方法驱动UI变更;而 Jetpack Compose 采用声明式编程范式,开发者只需要根据状态描述UI,当状态变化时,UI会自动更新。

Jetpack_ComposeAndroid_View_19">Jetpack Compose和Android View对比

Android View劣势:

  • 代码臃肿:View.java本身也变得越发臃肿,目前已超过三万行,早已不堪重负。臃肿的父类视图控件也造成了子类视图功能的不合理。以最常见的Button类为例,为了能让按钮具备显示文字的功能,Button被设计成了继承自TextView的子类:这显然是不合理的。
  • 兼容性差:像Button这类基础控件只能跟随系统的升级而更新,即使发现了问题也得不到及时修复,长期下来积重难返,破窗效应也越发突出。如今很多新的视图组件都以Jetpack扩展库的形式单独发布,目的也是为了不受系统版本的制约。

Jetpack Compose优势:

  • 先进的开发范式:Compose采用声明式的开发范式,开发者只需要聚焦在对UI界面的描述上,当需要渲染的数据发生变化时,框架将自动完成UI刷新。
  • 直观易用的API:基于Kotlin DSL打造的API紧贴函数式编程思想,相对于传统的视图开发方式,代码效率更高,实现同样的功能只需要以前一半的代码量。
  • 良好的兼容性:Compose代码与基于Android View系统的传统代码可以共存,用户可以按照喜欢的节奏将既有代码逐步过渡到Compose
  • 广泛的适用性:Compose最低兼容到API 21,支持市面上绝大多数手机设备的使用;Jetpack以及各种常用三方库也都第一时间与Compose进行了适配。
Android ViewJetpack Compose
类职责不单一,继承关系不合理函数声式编程,规避了面向对象的弊病
依赖系统版本,问题修复不及时独立迭代,良好的系统兼容性
命令式编程,开发效率低下声明式编程,DSL开发效率高

Compose_API_41">Compose API设计原则

一切皆为函数

Compose 声明式UI的基础是 Composable 函数,Composable 函数通过多级嵌套形成结构化的函数调用链,函数调用链经过运行后生成UI视图树;视图树一旦生成后不能随意改变,视图的刷新依靠 Composable 函数的反复执行实现。

说明:Kotlin编码规范中要求函数的首字母小写,但是 Compose 推荐 Composable 使用首字母大写的名词来命名,且不允许有返回值。这样在DSL中书写时可读性更好。有的 Composable 函数并不代表UI组件,此时可以遵循一般的函数命名规范。

组合优于继承

Android View 中的所有组件都直接或间接继承自 View 类,处于末端的子 View 会继承很多无用的功能。反观 Jetpack Compose,Composable 作为函数相互间没有继承关系,有利于促使开发者使用组合的视角思考问题。

在这里插入图片描述

单一数据源

传统的 Android View 中的 EditText,它的文字变化可能来自用户的输入,也有可能来自 setText() 方法,也就是所谓的多数据源,数据的变化不容易跟踪。而 Compose 则是数据是自上而下的单向流动,事件是自下而上传递。

Jetpack_ComposeAndroid_View_61">Jetpack Compose和Android View关系

在这里插入图片描述

  • Android View 是由 View 和 ViewGroup构成视图树。
  • Compose 是由 LayoutNode 构成视图树。ComposeView 继承自 AbstractComposeView,,ComposeView 负责对Android平台的Activity窗口的适配,AndroidComposeView 负责连接LayoutNode视图系统与View视图系统。

Compose_70">使用Compose

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {MyAndroidComposeTheme {Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colors.background) {Greeting("Android")}}}}
}@Composable
fun Greeting(name: String) {Text(text = "Hello $name!")
}@Preview(showBackground = true)
@Composable
fun DefaultPreview() {MyAndroidComposeTheme {Greeting("Android")}
}

使用 setContent() 方法替代以前的 setContentView() 方法。

setContent()源码

public fun ComponentActivity.setContent(parent: CompositionContext? = null,content: @Composable () -> Unit
) {val existingComposeView = window.decorView.findViewById<ViewGroup>(android.R.id.content).getChildAt(0) as? ComposeViewif (existingComposeView != null) with(existingComposeView) {setParentCompositionContext(parent)setContent(content)} else ComposeView(this).apply {// Set content and parent **before** setContentView// to have ComposeView create the composition on attachsetParentCompositionContext(parent)setContent(content)// Set the view tree owners before setting the content view so that the inflation process// and attach listeners will see them already presentsetOwners()setContentView(this, DefaultActivityContentLayoutParams)}
}

说明:setContent() 方法是 ComponentActivity 的一个扩展方法,通过Activity中的Window的DecorView获取到ContentView根布局,接着将 ContentView 的第一个子元素强转为 ComposeView,ComposeView 如果不存在则创建,然后通过 setContent() 给 ComposeView 设置内容,最后调用 setContentView()。

@Composable

@Composable 注解表示可组合函数,表示告知 Compose 编译器将该函数转换为界面。

@Preview

@Preview 注解表示可以在Android Studio中快速预览这些可组合函数的渲染结果,无需在设备或模拟器上运行应用。

annotation class Preview(val name: String = "",  // 名字val group: String = "",  // 分组@IntRange(from = 1) val apiLevel: Int = -1,  // API的等级val widthDp: Int = -1,  // 宽度val heightDp: Int = -1,  // 高度val locale: String = "",  // 语言设定@FloatRange(from = 0.01) val fontScale: Float = 1f, // 字体缩放比val showSystemUi: Boolean = false,  // 是否显示设备的状态栏和操作栏val showBackground: Boolean = false, // 是否显示背景val backgroundColor: Long = 0, // 背景颜色设置@UiMode val uiMode: Int = 0, // UI模式,比如深色模式@Device val device: String = Devices.DEFAULT  // 要在预览中使用的设备
)

使用:

@Preview(name = "测试", widthDp = 100, heightDp = 200, showBackground = true)
@Composable
fun DefaultPreview() {Greeting("Compose")
}

http://www.ppmy.cn/embedded/33432.html

相关文章

【算法小白周赛1E】ET表题解与代码(算法与数据结构刷题计划)

题目链接&#xff1a;https://www.starrycoding.com/contest/3/E 题目描述 小e发明了一种奇怪的数据结构——ET表&#xff0c;这一奇怪的数据结构有以下两种奇怪的操作&#xff1a; 将前 i i i 个数减去 k k k。将后 i i i 个数减去 k k k。 为了测试ET表的性能&#x…

【银角大王——Django课程——用户表的基本操作2】

用户表的基本操作2 编辑用户按钮删除按钮入职日期——不显示时分&#xff0c;只显示年月日——使用DataField函数不使用DateTimeField修改models记得重新执行命令&#xff0c;更新数据库结构修改前修改后 编辑用户按钮 点击编辑&#xff0c;跳转到编辑页面&#xff08;将编辑的…

大数据BI可视化(Echarts组件)项目开发-熟悉交互API5.0

全局echarts对象 init初始化 registerTheme注册主题 var mCharts echarts.init(document.querySelector("div"), itcast)registerMap地图图表 connect 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&qu…

BUUCTF——web题目练习

[极客大挑战 2019]LoveSQL 输入1 123 输入1 123 输入2 123 这里可以看出注入位置为password的后面&#xff0c;开始手动注入 闭合方式为1 [极客大挑战 2019]Secret File 查看页面源代码&#xff0c;发现里面有一个跳转页面的连接&#xff0c;点击进去&#xff0c;查看这个…

软设之文件管理

文件:具有符号名&#xff0c;在逻辑上具有完整意义的一组相关信息项的集合。一个文件包括文件体和文件说明。 逻辑结构:有结构的记录式文件&#xff0c;无结构的流式文件 物理结构:连续结构&#xff0c;链接结构&#xff0c;索引结构&#xff0c;多个物理块结构 文件目录 基…

Java ~ Lock【源码】

前言 相关系列 《Java ~ Lock【目录】》&#xff08;持续更新&#xff09;《Java ~ Lock【源码】》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Java ~ Lock【总结】》&#xff08;学习总结/最新最准/持续更新&#xff09;《Java ~ Lock【问题】》&#xf…

微服务----nacos配置及简单使用

目录 什么是nacos 项目在nacos上进行注册 注入nacos依赖 配置application.yml文件 nacos写入配置文件 首先&#xff0c;还是需要导入依赖 然后在nacos中编写配置文件 prod是我自定义的一个命名空间&#xff0c;在这里面进行配置文件编写~ 启动类上加上注解 编写Patt…

Slave SQL线程与PXB FTWRL死锁问题分析

1. 问题背景 2.27号凌晨生产环境MySQL备库在执行备份期间出现因FLUSH TABLES WITH READ LOCK未释放导致备库复制延时拉大&#xff0c;慢日志内看持锁接近25分钟未释放。 版本&#xff1a; MySQL 5.7.21PXB 2.4.18 慢查询日志&#xff1a; 备份脚本中的备份命令&#xff1a;…