Jetpack-Compose 学习笔记(一)—— Compose 初探(下)

简介: Jetpack-Compose 学习笔记(一)—— Compose 初探(下)

4.2 Compose 可构建容器函数


Compose 支持构建容器函数,容器函数类似于 Theme 主题,可以将一些基础的设置信息放在容器函数中,这样放入这个容器函数中的 Composable 函数就会根据设置的信息进行绘制、渲染。举个简单的栗子:

// code 5
// 声明一个容器函数
@Composable
fun MyApp(content: @Composable () -> Unit) {
    MaterialTheme() {
        Surface(color = Color.Yellow, modifier = Modifier.padding(10.dp)) {
            content()
        }
    }
}
// 实际运用
MyApp {
    Text(text = "被容器函数所修饰的 Text")
}

所有放入 MyApp 容器中的 Composable 函数都会带上容器函数中设置的属性。这样可提高代码复用性和可读性。


4.3 Compose 状态初探


Compose 的核心内容就是响应 state 状态的改变。Compose 通过调用 Composable 函数可以将 data 数据展示在 UI 上,Compose 本身也提供了工具去观察 data 数据的变化,从而可以自动地回调展示 UI,这一过程官方称为重组,前面也有说到。可以理解为更新 UI。

在 Composable 函数内部我们可以使用 mutableStateOf 方法去添加一个可变的 state,为了避免每次重组都会出现不同的状态,所以可以用 remember 记住这个可变状态。

// code 6
@Composable
fun Counter() {
    val count = remember { mutableStateOf(0)}  // 初始化为 0
    Button(onClick = { count.value++ }) {
        Text(text = "已点击了 ${count.value} 次!")
    }
}

这样每次点击 Button,都会更新点击的次数值。


4.4 Compose 列表初探


列表布局使用频率还是比较高的,像 ListView 和 RecyclerView 都是耳熟能详的用于展示列表的 View 控件。那么 LazyColumn 就相当于 Compose 中的 RecyclerView,用于展示可滑动的长列表。它提供了 items API 用于展示简单的列表布局。

// code 7
@Composable
fun NameList(names: List<String>, modifier: Modifier = Modifier) {
    LazyColumn(modifier = modifier) {
        items(items = names) { name ->
            Greeting(name = name)
            Divider(color = Color.Black)    // 分割线类对象
        }
    }
}

然而,LazyColumn 不会像 RecyclerView 一样缓存列表中的布局,而是在滚动浏览它时,它会渲染新的列表 View,并没有回收机制,但是相比于实例化 Android View,渲染 Composable UI 组件效率更高。


4.5 Compose 自定义主题


Compose 中有自带的一些主题,比如 MaterialTheme,被这些 Theme 包裹,就可以呈现出这些 Theme 所设置的属性了。当然也可以单独将这些 Theme 中某些属性拿出来,比如字体。然后就可以使用该主题下设置的各种字体样式了,同样的还有色值:

// code 8
@Composable
fun Greeting(name: String) {
    val greetingTypography = MaterialTheme.typography // 获取 MaterialTheme 字体样式
    val greetingColors = MaterialTheme.colors // 获取 MaterialTheme 色值
    Text(text = "Hello $name",
        color = greetingColors.onBackground,    // 使用 MaterialTheme 的 onBackground 色值
        style = greetingTypography.body2)
}

还可以调用 copy 方法复制某主题的样式,然后在此基础上改写自己的一些样式属性:

// code 9
@Composable
fun Greeting(name: String) {
    val customStyle = MaterialTheme.typography.h5.copy(color = Color.Green)
    Text(text = "Hello $name",
        style = customStyle)
}

如何自定义一个自己的 Theme?其实也很简单,下面是一个例子:

// code 10
// 主要方法,被此方法包裹的 Composable 函数都会被设置为自定义主题
@Composable
fun CustomTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),  // 默认根据系统来设置是否为暗夜模式
    content: @Composable () -> Unit  // 被传入的 Composable 函数
){
    val colors = if (darkTheme) {
        DarkColors
    } else {
        LightColors
    }
    MaterialTheme(colors = colors) { // 将设置好的色值传入
        content()
    }
}
private val DarkColors = darkColors( // 暗夜模式下的色值
    primary = Red300,
    primaryVariant = Red700,
    onPrimary = Color.Black,
    secondary = Red300,
    onSecondary = Color.Black,
    error = Red200
)
private val LightColors = lightColors( // 白天模式下的色值
    primary = Red700,
    primaryVariant = Red900,
    onPrimary = Color.White,
    secondary = Red700,
    secondaryVariant = Red900,
    onSecondary = Color.White,
    error = Red800
)

是不是觉得简单?是的,在 Compose 中自定义一个主题就是这么简单。


5. 编程思想


再来说一说官方文档里提到的 Compose 的编程思想吧。它采用的是声明性界面模型,该模型工作原理是先从开始生成整个屏幕,然后仅执行必要的更改。重组就是使用新数据再次调用 Composable 函数,从而进行更新的。当然重组过程仅调用可能已更改的函数或 lambda,而跳过其余函数或 lambda,所以 Compose 可以高效地重组。

其中,官方建议在更新时,不要依赖于执行 Composable 函数所产生的附带效应,因为可能会跳过函数的重组。附带效应指的是对应用的其余可见部分的任何更改。危险的附带效应有1)写入共享对象的属性(这个应该是怕有其他的逻辑正在读取共享对象属性来更新 UI 等,使得 UI 变化不准确。);2)更新 ViewModel 中的可观察项(原理同1));3)更新 SharedPreference(原理同1))。(不是很理解,可能日后真正使用后会更有体会吧~欢迎一起讨论)

Composable 函数可能会像每一帧一样频繁地重新执行,例如在呈现动画时。Composable 函数应快速执行,避免在播放动画期间出现卡顿。如果需要执行耗时操作,如从 SharedPreference 中读取数据,那么建议在后台协程中处理,然后使用回调传递当前值来触发更新。还有几个值得注意的 Tips:

1、Composable 函数可以按任何顺序执行 如果某个 Composable 函数中包含有几个 Composable 函数,那么这些 Composable 函数可能按任何顺序运行,Compose 会识别出哪些界面元素的优先级高于其他的界面元素,从而优先绘制这些元素。

2、 Composable 函数可以并行运行 Compose 可以通过并行运行 Composable 函数来优化重组。所以,Compose 可以利用多个核心,并以较低的优先级运行 Composable 函数。因此,Composable 函数可能会在后台线程池中执行。调用某个 Composable 函数时,调用可能发生在与调用方不同的线程中。

3、重组会跳过尽可能多的内容 Compose 会尽力只重组需要更新的部分,每个 Composable 函数和 lambda 又可以自行重组更新。Compose 若在一次重组时发现参数又更新了,则会取消当前的重组,并用新参数重新开始。

官方推荐将 Composable 函数写在顶级函数,方便以后复用。

Compose 博大精深,许多概念性的东西并没有理解得很透彻,还需慢慢实践才能得出真知啊!欢迎留言交流,互相学习!

ps. 简单的 Demo:gitee.com/xiuzhizhu/C…

官方教程网站:developer.android.google.cn/courses/pat…


参考文献


  1. Jetpack Compose 1.0 正式发布!打造原生 UI 的 Android 现代工具包
  2. Jetpack Compose 基础知识
  3. Compose 编程思想


尾巴:这是 Compose 系列笔记的首篇,相信细心的同学也发现了,这篇笔记是根据官方教程网站上的学习路线进行记录学习的。自己在学习的过程中,遇到不明白的地方也会查阅大量的资料进行补充,喜欢的话,欢迎分享转发加关注~

目录
相关文章
|
5月前
|
存储 缓存 Android开发
安卓Jetpack Compose+Kotlin, 使用ExoPlayer播放多个【远程url】音频,搭配Okhttp库进行下载和缓存,播放完随机播放下一首
这是一个Kotlin项目,使用Jetpack Compose和ExoPlayer框架开发Android应用,功能是播放远程URL音频列表。应用会检查本地缓存,如果文件存在且大小与远程文件一致则使用缓存,否则下载文件并播放。播放完成后或遇到异常,会随机播放下一首音频,并在播放前随机设置播放速度(0.9到1.2倍速)。代码包括ViewModel,负责音频管理和播放逻辑,以及UI层,包含播放和停止按钮。
|
5月前
|
存储 数据库 Android开发
安卓Jetpack Compose+Kotlin,支持从本地添加音频文件到播放列表,支持删除,使用ExoPlayer播放音乐
为了在UI界面添加用于添加和删除本地音乐文件的按钮,以及相关的播放功能,你需要实现以下几个步骤: 1. **集成用户选择本地音乐**:允许用户从设备中选择音乐文件。 2. **创建UI按钮**:在界面中创建添加和删除按钮。 3. **数据库功能**:使用Room数据库来存储音频文件信息。 4. **更新ViewModel**:处理添加、删除和播放音频文件的逻辑。 5. **UI实现**:在UI层支持添加、删除音乐以及播放功能。
|
2月前
|
安全 Java Android开发
探索安卓应用开发的新趋势:Kotlin和Jetpack Compose
在安卓应用开发领域,随着技术的不断进步,新的编程语言和框架层出不穷。Kotlin作为一种现代的编程语言,因其简洁性和高效性正逐渐取代Java成为安卓开发的首选语言。同时,Jetpack Compose作为一个新的UI工具包,提供了一种声明式的UI设计方法,使得界面编写更加直观和灵活。本文将深入探讨Kotlin和Jetpack Compose的特点、优势以及如何结合使用它们来构建现代化的安卓应用。
62 4
|
4月前
|
存储 移动开发 Android开发
使用kotlin Jetpack Compose框架开发安卓app, webview中h5如何访问手机存储上传文件
在Kotlin和Jetpack Compose中,集成WebView以支持HTML5页面访问手机存储及上传音频文件涉及关键步骤:1) 添加`READ_EXTERNAL_STORAGE`和`WRITE_EXTERNAL_STORAGE`权限,考虑Android 11的分区存储;2) 配置WebView允许JavaScript和文件访问,启用`javaScriptEnabled`、`allowFileAccess`等设置;3) HTML5页面使用`<input type="file">`让用户选择文件,利用File API;
|
5月前
|
JavaScript Java Android开发
kotlin安卓在Jetpack Compose 框架下跨组件通讯EventBus
**EventBus** 是一个Android事件总线库,简化组件间通信。要使用它,首先在Gradle中添加依赖`implementation &#39;org.greenrobot:eventbus:3.3.1&#39;`。然后,可选地定义事件类如`MessageEvent`。在活动或Fragment的`onCreate`中注册订阅者,在`onDestroy`中反注册。通过`@Subscribe`注解方法处理事件,如`onMessageEvent`。发送事件使用`EventBus.getDefault().post()`。
|
5月前
|
安全 JavaScript 前端开发
kotlin开发安卓app,JetPack Compose框架,给webview新增一个按钮,点击刷新网页
在Kotlin中开发Android应用,使用Jetpack Compose框架时,可以通过添加一个按钮到TopAppBar来实现WebView页面的刷新功能。按钮位于右上角,点击后调用`webViewState?.reload()`来刷新网页内容。以下是代码摘要:
|
5月前
|
缓存 Android开发 Kotlin
【安卓app开发】kotlin Jetpack Compose框架 | 先用OKhttp下载远程音频文件再使用ExoPlayer播放
使用 Kotlin 的 Jetpack Compose 开发安卓应用时,可以结合 OkHttp 下载远程音频文件和 ExoPlayer 进行播放。在 `build.gradle` 添加相关依赖后,示例代码展示了如何下载音频并用 ExoPlayer 播放。代码包括添加依赖、下载文件、播放文件及简单的 Compose UI。注意,示例未包含完整错误处理和资源释放,实际应用需补充这些内容。
|
5月前
|
JavaScript 前端开发 Android开发
kotlin安卓在Jetpack Compose 框架下使用webview , 网页中的JavaScript代码如何与native交互
在Jetpack Compose中使用Kotlin创建Webview组件,设置JavaScript交互:`@Composable`函数`ComposableWebView`加载网页并启用JavaScript。通过`addJavascriptInterface`添加`WebAppInterface`类,允许JavaScript调用Android方法如播放音频。当页面加载完成时,执行`onWebViewReady`回调。
|
5月前
|
存储 Android开发 Kotlin
开发安卓app OKhttp下载后使用MediaPlayer播放
在Android Jetpack Compose应用程序中,要使用OkHttp下载远程音频文件并在本地播放,你需要完成以下几个步骤: 1. **添加依赖**:确保`build.gradle`文件包含OkHttp和Jetpack Compose的相关依赖。 2. **下载逻辑**:创建一个`suspend`函数,使用OkHttp发起网络请求下载音频文件到本地。 3. **播放逻辑**:利用`MediaPlayer`管理音频播放状态。 4. **Compose UI**:构建用户界面,包含下载和播放音频的按钮。
|
5月前
|
存储 Android开发
安卓app,MediaPlayer播放本地音频 | 按钮控制播放和停止
在Jetpack Compose中,不直接操作原生Android组件如`Button`和`MediaPlayer`,而是使用Compose UI构建器定义界面并结合ViewModel管理音频播放逻辑。以下示例展示如何播放本地音频并用按钮控制播放/停止:创建一个`AudioPlayerViewModel`管理`MediaPlayer`实例和播放状态,然后在Compose UI中使用`Button`根据`isPlaying`状态控制播放。记得在`MainActivity`设置Compose UI,并处理相关依赖和权限。