当前位置: 首页 > news >正文

Jetpack Compose初体验

入门学习

由于工作需要,我们当前要在老代码的基础上使用 Compose 进行新页面的开发,这项工作主要落在我的身上。因此,我需要先了解 Compose。

这里我入门看的是写给初学者的Jetpack Compose教程,Lazy Layout,有兴趣可以看看。

了解 Compose

Compose 是 Google 推出的用于构建原生界面的现代工具包,专门用于 Android 平台的声明式 UI 开发。基于 Kotlin 语言,Compose 利用 Kotlin 的特性来简化 UI 开发过程,核心思想是使用函数来描述 UI 的外观和行为。

Compose 与传统 Android 开发的区别

1. 编程范式
  • 传统 Android 开发:采用命令式编程范式,开发者需要手动管理 UI 组件的创建、更新和销毁。
  • Compose 开发:采用声明式编程范式,开发者只需描述 UI 的最终状态,Compose 会自动更新 UI。
2. 布局系统
  • 传统 Android 开发:使用 XML 布局文件和 Java/Kotlin 代码分离的方式。
  • Compose 开发:使用 Kotlin 代码直接构建布局,布局代码和逻辑代码可以放在一起。
3. 状态管理
  • 传统 Android 开发:手动处理状态的保存和恢复。
  • Compose 开发:内置状态管理机制,使用 mutableStateOf,状态变化会自动更新 UI。
4. 开发效率
  • 传统 Android 开发:代码量较大,开发效率相对较低。
  • Compose 开发:代码简洁,声明式编程和内置状态管理机制提高了开发效率。

初试 Compose

从 AI 的搜索结果来看,Compose 开发具有以下特点:声明式编程、基于 Kotlin、高效的状态管理、简洁的布局系统、实时预览、与现有代码兼容。

环境搭建

想要进行 Compose 开发,首先要引入 Compose 环境。Android Studio 新版可以直接创建 Compose 项目,但我当前的版本暂未提供这一功能。可以通过在 build.gradle 文件中添加相关依赖来引入 Compose。

公共基类

我创建了一个 BaseComposeActivity 作为 Compose 页面的公共基类,它继承自 AppCompatActivity,并在 onCreate 方法中使用 setContent 来设置 Compose UI。

基本布局

根据产品的原型图,我基于平板和手机做出了不同的响应式布局。只需通过 @Composable 函数来组合不同的组件,即可实现 Activity 显示不同的信息。

主页面逻辑

我注册了一个主页面 DevicePolicyActivity,在其中定义了基本布局并对平板和手机进行了区分。通过 TopBarRow 组件来安排导航栏和内容区域,使用 navigationNumberhideSelectTac 来控制不同的页面显示。

响应式布局
  • 平板端工作台:显示两列布局,左侧是目录,右侧是内容详情。
  • 非平板端工作台:基于页面跳转来显示详情页面。
策略目录菜单

目录菜单通过 DirectoryItemStrategyItem 组件来实现。通过点击菜单项更新选中状态,并相应地改变页面显示。对于非平板逻辑页面,点击后触发页面跳转,通过 forceRecompose 来手动触发页面重组。

DP根据逻辑生成的

这是ai根据我描述逻辑生成的,基本逻辑是一样的,但状态管理我都是基于remember和mutableIntStateOf进行管理的,其他意思到了就行:

代码实现细节

以下是基于 Compose 实现的核心代码逻辑和关键设计思路,结合具体场景进行说明:


1. BaseComposeActivity 基类
abstract class BaseComposeActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {MyAppTheme {  // 自定义主题配置AppContent() // 主 UI 入口}}}@Composableabstract fun AppContent()
}

设计要点:

  • 统一 Activity 入口模板
  • 强制子类实现 AppContent 方法作为 UI 入口
  • 集成 Material Design 主题系统

2. 主页面 DevicePolicyActivity 实现
class DevicePolicyActivity : BaseComposeActivity() {private val viewModel: PolicyViewModel by viewModels()@Composableoverride fun AppContent() {val isTablet = LocalConfiguration.current.screenWidthDp >= 600if (isTablet) {TabletLayout(viewModel)} else {PhoneLayout(viewModel)}}
}

设备检测逻辑:

@Composable
fun isTabletMode(): Boolean {val configuration = LocalConfiguration.currentreturn configuration.screenWidthDp >= 600 || configuration.smallestScreenWidthDp >= 600
}

3. 平板双栏布局实现
@Composable
private fun TabletLayout(viewModel: PolicyViewModel) {Scaffold(topBar = { AppTopBar(viewModel.selectedTitle) }) { padding ->Row(Modifier.padding(padding)) {// 左侧目录(占30%宽度)NavigationColumn(Modifier.weight(0.3f),viewModel.policies,viewModel::selectPolicy)// 右侧详情(占70%宽度)PolicyDetail(Modifier.weight(0.7f),viewModel.selectedPolicy)}}
}

关键交互逻辑:

// 状态管理示例
class PolicyViewModel : ViewModel() {private val _selectedPolicy = mutableStateOf<Policy?>(null)val selectedPolicy: State<Policy?> = _selectedPolicyfun selectPolicy(policy: Policy) {_selectedPolicy.value = policy}
}

4. 手机端列表-详情跳转
@Composable
private fun PhoneLayout(viewModel: PolicyViewModel) {val navController = rememberNavController()NavHost(navController, startDestination = "policyList") {composable("policyList") {PolicyListScreen(viewModel) { policy ->navController.navigate("policyDetail/${policy.id}")}}composable("policyDetail/{policyId}") { backStackEntry ->PolicyDetailScreen(policyId = backStackEntry.arguments?.getString("policyId"),onBack = { navController.popBackStack() })}}
}

5. 策略目录组件实现
@Composable
fun NavigationColumn(modifier: Modifier = Modifier,policies: List<Policy>,onSelect: (Policy) -> Unit
) {LazyColumn(modifier) {items(policies) { policy ->DirectoryItem(policy = policy,isSelected = policy == viewModel.selectedPolicy,onClick = { onSelect(policy) })}}
}@Composable
private fun DirectoryItem(policy: Policy,isSelected: Boolean,onClick: () -> Unit
) {Surface(color = if (isSelected) MaterialTheme.colors.primary.copy(alpha = 0.1f) else Color.Transparent,modifier = Modifier.fillMaxWidth().clickable { onClick() }) {Text(text = policy.title,modifier = Modifier.padding(16.dp),style = MaterialTheme.typography.subtitle1)}
}

6. 强制重组逻辑优化
// 使用 remember 配合 key 控制重组
var recomposeKey by remember { mutableStateOf(0) }LaunchedEffect(Unit) {// 当需要强制重组时recomposeKey++
}Column(modifier = Modifier.remember(recomposeKey) { /*...*/ }) {// 动态内容
}

替代方案:

// 使用 derivedStateOf 精细化控制
val filteredPolicies = remember(policies, searchQuery) {derivedStateOf {policies.filter { it.contains(searchQuery) }}
}

遇到的典型问题与解决方案

问题 1:状态更新未触发重组

现象: 修改 mutableStateOf 的值后 UI 未更新
解决方案:

// 错误写法
var count = mutableStateOf(0)
Button(onClick = { count.value++ }) // 正确写法
val count = remember { mutableStateOf(0) }
Button(onClick = { count.value++ })
问题 2:列表性能问题

现象: LazyColumn 滚动卡顿
优化方案:

items(policies, key = { it.id }) { policy ->// 使用稳定唯一的 key
}
问题 3:主题配置冲突

解决方案: 创建独立主题配置

@Composable
fun MyAppTheme(content: @Composable () -> Unit) {MaterialTheme(colors = darkColors(primary = Color(0xFFBB86FC),secondary = Color(0xFF03DAC6)),typography = MyTypography,content = content)
}

相关文章:

Jetpack Compose初体验

入门学习 由于工作需要&#xff0c;我们当前要在老代码的基础上使用 Compose 进行新页面的开发&#xff0c;这项工作主要落在我的身上。因此&#xff0c;我需要先了解 Compose。 这里我入门看的是写给初学者的Jetpack Compose教程&#xff0c;Lazy Layout&#xff0c;有兴趣可…...

ceph部署-14版本(nautilus)-使用ceph-ansible部署实验记录

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、环境信息二、部署步骤2.1 基础环境准备2.2 各节点docker环境安装2.3 搭建互信集群2.4 下载ceph-ansible 三、配置部署文件3.1 使用本地docker3.2 配置hosts…...

【C++】C++ 旅馆管理系统(含 源码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 系列文章目录 目录 系列文章目录一、设计要求二、设…...

快速排序

目录 什么是快速排序&#xff1a; 图解&#xff1a; 递归法&#xff1a; 方法一&#xff08;Hoare法&#xff09;&#xff1a; 代码实现&#xff1a; 思路分析&#xff1a; 方法二&#xff08;挖坑法&#xff09;&#xff1a; 代码实现&#xff1a; 思路分析&#xff1a; 非递…...

国内 ChatGPT Plus/Pro 订阅教程

1. 登录 chat.openai.com 依次点击 Login &#xff0c;输入邮箱和密码 2. 点击升级 Upgrade 登录自己的 OpenAI 帐户后&#xff0c;点击左下角的 Upgrade to Plus&#xff0c;在弹窗中选择 Upgrade plan。 如果升级入口无法点击&#xff0c;那就访问这个网址&#xff0c;htt…...

易仓科技ai面试

请解释PHP中的面向对象编程的基本概念&#xff0c;并举例说明如何在PHP中定义一个类。 回答思路&#xff1a;需理解类、对象、继承和多态等基本概念&#xff0c;并能通过实例代码展示如何定义类及其属性和方法。 . 类&#xff08;Class&#xff09; 类是一个封装了数据和操作…...

LabVIEW用户界面(UI)和用户体验(UX)设计

作为一名 LabVIEW 开发者&#xff0c;满足功能需求、保障使用便捷与灵活只是基础要求。在如今这个用户体验至上的时代&#xff0c;为 LabVIEW 应用程序设计直观且具有美学感的界面&#xff0c;同样是不容忽视的关键任务。一个优秀的界面设计&#xff0c;不仅能提升用户对程序的…...

字玩FontPlayer开发笔记14 Vue3实现多边形工具

目录 字玩FontPlayer开发笔记14 Vue3实现多边形工具笔记整体流程临时变量多边形组件数据结构初始化多边形工具mousedown事件mousemove事件监听mouseup事件渲染控件将多边形转换为平滑的钢笔路径 字玩FontPlayer开发笔记14 Vue3实现多边形工具 字玩FontPlayer是笔者开源的一款字…...

低代码与 Vue.js:技术选型与架构设计

在当下数字化转型的浪潮中&#xff0c;企业对应用开发的效率和质量有着极高的追求。低代码开发平台的兴起&#xff0c;为企业提供了一条快速构建应用的捷径&#xff0c;而 Vue.js 作为热门的前端框架&#xff0c;与低代码开发平台的结合备受关注。如何做好两者的技术选型与架构…...

比较循环与迭代器的性能:Rust 零成本抽象的威力

一、引言 在早期的 I/O 项目中&#xff0c;我们通过对 String 切片的索引和 clone 操作来构造配置结构体&#xff0c;这种方法虽然能确保数据所有权的正确传递&#xff0c;但既显得冗长&#xff0c;又引入了不必要的内存分配。随着对 Rust 迭代器特性的深入了解&#xff0c;我…...

一文了解zookeeper

1.ZooKeeper是什么 简单来说&#xff0c;她是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务 具体来说&#xff0c;他可以做如下事情&#xff1a; 分布式配置管理&#xff1a;ZooKeeper可以存储配置信息&#xff0c;应用程序可以动态读取配置信息。分布式同步&a…...

算法题(67):最长连续序列

审题&#xff1a; 需要我们在O&#xff08;n&#xff09;的时间复杂度下找到最长的连续序列长度 思路&#xff1a; 我们可以用两层for循环&#xff1a; 第一层是依次对每个数据遍历&#xff0c;让他们当序列的首元素。 第二层是访问除了该元素的其他元素 但是此时时间复杂度来到…...

大中型企业专用数据安全系统 | 天锐蓝盾终端安全 数据安全

天锐蓝盾系列产品是专门为大中型企业量身定制的数据安全防护产品体系&#xff0c;涵盖天锐蓝盾DLP、天锐蓝盾终端安全管理系统、天锐蓝盾NAC以及其他搭配产品&#xff0c;致力于实现卓越的数据安全防护、施行严格的网络准入控制以及构建稳固的终端安全管理体系。通过全方位的防…...

Deepseek解读 | UE像素流送与实时云渲染技术的差别

为了实现UE引擎开发的3D/XR程序推流&#xff0c;绝大多数开发者会研究像素流送&#xff08;Pixel Streaming&#xff09;的使用方法&#xff0c;并尝试将插件集成在程序中。对于短时、少并发、演示场景而言&#xff0c;像素流送可以满足基本需求。当3D/XR项目进入落地交付周期后…...

CTFSHOW-WEB入门-PHP特性109-115

题目&#xff1a;web 109 1. 题目&#xff1a; 2. 解题思路&#xff1a;题目要求获得两个参数&#xff0c;v1 v2&#xff0c;if语句中的意思是要求两个参数都包含字母&#xff0c;条件满足的话&#xff0c;执行 echo new 类名&#xff08;方法&#xff08;&#xff09;&#xf…...

模糊综合评价法:原理、步骤与MATLAB实现

引言 在复杂决策场景中&#xff0c;评价对象往往涉及多个相互关联的模糊因素。模糊综合评价法通过建立模糊关系矩阵&#xff0c;结合权重分配与合成算子&#xff0c;实现对多因素系统的科学评价。本文详细讲解模糊综合评价法的数学原理、操作步骤&#xff0c;并辅以MATLAB代码…...

【数据结构-红黑树】

文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff08;Binary Search Tree, BST&#xff09;&…...

【STM32】舵机SG90

1.舵机原理 舵机内部有一个电位器&#xff0c;当转轴随电机旋转&#xff0c;电位器的电压会发生改变&#xff0c;电压会带动转一定的角度&#xff0c;舵机中的控制板就会电位器输出的电压所代表的角度&#xff0c;与输入的PWM所代表的角度进行比较&#xff0c;从而得出一个旋转…...

【Linux】Socket编程—TCP

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…...

c++11 for auto不定参数

数量不定的模板参数。参数分为一个和一包两部分。 ​ 冒号的左边声明一个变量。右手边必须是一个容器。从容器(某种数据结构)中找出每一个元素设置到左边这个变量。11之前可以用容器的迭代器去取数据。或者标准库里的foreach...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...