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

使用 Macrobenchmark 测试 Android 应用性能

etpack Compose 是推荐用于构建原生 Android 界面的新工具包。后续简称Jetpack Compose为Compose。

在了解State之前需要先对Compose及申明性编程式有个大概的了解。

State初体验

好了,在你有一定了解的基础上,我们先来运行几个Demo,初步了解为何使用state。这个例子主要是想通过点击按钮,改变文案的显示。(这个过程称之为重组)

Demo1:

classStateDemoActivity : AppCompatActivity() {overridefunonCreate(savedInstanceState: Bundle?) {supportActionBar?.hide()super.onCreate(savedInstanceState)WindowCompat.setDecorFitsSystemWindows(window, false)setContent {TestComposeTheme {var state = falseLog.e("StateDemoActivity", "hashcode:${state.hashCode()} value:${state}")Column(modifier = Modifier.fillMaxSize().systemBarsPadding()) {Button(onClick = {state = !stateLog.e("StateDemoActivity", "onClick hashcode:${state.hashCode()} value:${state}")}, modifier = Modifier.fillMaxWidth()) {Text(text = "Change State:${state}",color = MyColorTheme.textMain,fontSize = 20.sp)}}}}}
}
复制代码

对应输出如下:

StateDemoActivity        E  hashcode:1237 value:false
StateDemoActivity        E  onClick hashcode:1231 value:true
StateDemoActivity        E  onClick hashcode:1237 value:false
StateDemoActivity        E  onClick hashcode:1231 value:true
StateDemoActivity        E  onClick hashcode:1237 value:false复制代码

可以发现,点击按钮Text显示的文本没有改变,没有达到预想的目的。

Demo2:这次我们使用官方的MutableState

TestComposeTheme {var state = mutableStateOf(false)Log.e("StateDemoActivity", "hashcode:${state.hashCode()} value:${state.value}")Column(modifier = Modifier.fillMaxSize().systemBarsPadding()) {Button(onClick = {state.value = !state.valueLog.e("StateDemoActivity", "onClick hashcode:${state.hashCode()} value:${state.value}")}, modifier = Modifier.fillMaxWidth()) {Text(text = "Change State:${state.value}",color = MyColorTheme.textMain,fontSize = 20.sp)}}
}
复制代码

输出如下,显示的文案依然没有改变,但相比之前多了Column之前的打印,这表明方法体被重新执行了,state变量的哈希值也在变化。以上表现和普通java方法别无区别,state是方法中的局部变量。

StateDemoActivity        E  hashcode:103910553 value:false
StateDemoActivity        E  onClick hashcode:103910553 value:true
StateDemoActivity        E  hashcode:118168247 value:false
StateDemoActivity        E  onClick hashcode:118168247 value:true
StateDemoActivity        E  hashcode:245965755 value:false复制代码

Demo3:这次我们稍作改动,额外使用remember函数,其他不变

var state = remember {mutableStateOf(false)
}
复制代码

输出如下,按钮文字终于如预想的那样发生了变化,此外有个特别的现象是state变量的哈希值并没有发生变化,表明方法每次执行时,state变量并没有重新创建。

StateDemoActivity        E  hashcode:103910553 value:false
StateDemoActivity        E  onClick hashcode:103910553 value:true
StateDemoActivity        E  hashcode:103910553 value:true
StateDemoActivity        E  onClick hashcode:103910553 value:false
StateDemoActivity        E  hashcode:103910553 value:false复制代码

remember方法内部必然有全局容器存储变量,源码中可以很明显的看出

@Composable
inline fun <T> remember(crossinline calculation: @DisallowComposableCalls () -> T): T =currentComposer.cache(false, calculation)
复制代码

综上我们可以知道,Compose是依赖对State变化的观察来重新执行Compose方法(准确来说Compose基于参数的比较结果来决定是否重组)

重组与稳定类型

接上文一个 Composable 函数在重组中被调用时,如果参数与上次调用时相比没有发生变化,则函数的执行会跳过重组,提升重组性能。需要特别说明Compose不会因为被观察的对象与上次是同一个就跳过重组。详情参考 Compose类型稳定性注解:@Stable & @Immutable

Composable的重组范围

在之前的内容中,我们已经知道了参数的变化会影响重组是否执行,这就带了重组范围的问题。这方面大佬已经有了很好的文章。建议小伙伴先阅读# Jetpack Compose:理解composable的重组范围

当我阅读后用代码验证时却发现了异常,代码如下

classStateDemoActivity : AppCompatActivity() {privateval TAG = StateDemoActivity::class.java.simpleNameoverridefunonCreate(savedInstanceState: Bundle?) {supportActionBar?.hide()super.onCreate(savedInstanceState)WindowCompat.setDecorFitsSystemWindows(window, false)setContent {TestComposeTheme {Log.e(TAG, "Scope-1 run ")var counter by remember {mutableStateOf(0)}Column(modifier = Modifier.fillMaxSize().systemBarsPadding()) { Log.e(TAG, "Scope-2 run ")Button(onClick = run {Log.e(TAG, "Button-onClick")return@run { counter++ }}) {Log.e(TAG, "Scope-3 run ")Text(text = "+")}Text(text = "Counter:${counter}",color = MyColorTheme.textMain,fontSize = 20.sp)}}}}
}
复制代码

输出如下

StateDemoActivity        E  Scope-1 run 
StateDemoActivity        E  Scope-2 run 
StateDemoActivity        E  Button-onClick
StateDemoActivity        E  Scope-3 run 
复制代码

按照文章内的说法Scope-3 run 这行是不应该被打印出来的,即不应该参与重组的,可实际结果却相反。小伙伴可以自己思考下,稍后再往下翻看原因;

--------------完美的分割线^_^------------

classStateDemoActivity : AppCompatActivity() {companionobject {privateval TAG = StateDemoActivity::class.java.simpleName}....
}
复制代码
StateDemoActivity        E  Scope-1 run 
StateDemoActivity        E  Scope-2 run 
StateDemoActivity        E  Button-onClick
复制代码

日志终于和理解的一样了,现在我们回头找原因,知道问题就出在打印的变量“TAG”身上。方法中各作用域Scope都读取了变量“TAG”,在第一个代码中该变量是个非稳定类型,故按钮触发重组时,为了保证正确性,所有引用到该变量的Scope都会重组;而第二个代码中“TAG”已经是个静态变量了,故而是个稳定类型,所以重组时不会引发非必要的重组。

最后补充一点:

从Android View转Compose过程中,对LiveData的使用场景需要特别留意。因为原本对LiveData的观察是通过observe方法进行的,每次LiveData内容更新(即使值一样)回调依然会收到;转换为State之后,只有value变化了,才会引发重组;例如

val missOut = MutableLiveData(false)
...
val state = viewModel.missOut.observeAsState(false).value
复制代码

多次调用missOut.value = true,state只有在第一次设置为true时引发重组。如果希望行为和之前observe一样,应该如下调用:

LaunchedEffect(key1 = Unit) {viewModel.missOut.asFlow().collect {...}
}
复制代码

Android核心知识点笔记:

Android开发核心知识点笔记

Android Framework核心知识点笔记

音视频开发笔记,入门到高级进阶

Android Flutter核心知识点笔记与实战详解

性能调优核心知识点笔记

相关文章:

使用 Macrobenchmark 测试 Android 应用性能

etpack Compose 是推荐用于构建原生 Android 界面的新工具包。后续简称Jetpack Compose为Compose。在了解State之前需要先对Compose及申明性编程式有个大概的了解。State初体验好了&#xff0c;在你有一定了解的基础上&#xff0c;我们先来运行几个Demo&#xff0c;初步了解为何…...

【django】django-simpleui配置后,后台显示空白页解决方法

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 django后台显示空白页解决方法 1. 正文 添加完simpleui以后&#xff0c;后台显示一片空白&#xff0c;一脸问号&#xff1f;&#xff1f;&#xff1f; …...

【035】基于Vue的电商推荐管理系统(含源码数据库、超详细论文)

摘 要&#xff1a;基于Vue&#xff0b;Nodejs&#xff0b;mysql的电商推荐管理系统&#xff0c;这个项目论文超详细&#xff0c;er图、接口文档、功能展示、技术栈等说明特别全&#xff01;&#xff01;&#xff01; &#xff08;文末附源码数据库、课设论文获取方式&#xff0…...

【c++】模板1—函数模板

文章目录函数模板语法函数模板注意事项案例—数组选择排序普通函数和函数模板的区别普通函数和函数模板调用规则模板的局限性函数模板语法 函数模板作用&#xff1a; 建立一个通用函数&#xff0c;其函数返回值类型和形参类型可以不具体制定&#xff0c;用一个虚拟的类型来代表…...

windows10 wsl子系统固定ip启动分配网卡法

WSL设置添加固定IP 在Win端添加一个固定IP 192.168.50.99 用于X-Server界面显示.在WSL端添加一个固定IP 192.168.50.16 用于和Win端通讯 在win端创建批处理文件 创建一个批处理文件 我的文件位置是D:\powershell\static_ip.bat 向vEthernet (WSL)网卡添加一个IP 192.168.50.…...

ARM+Linux日常开发笔记

ARMLinux开发命令 文章目录ARMLinux开发命令一、虚拟机1.ssh服务项目2.文件相关3.系统相关4. 虚拟机清理内存二、ARM核板1.设备重启三、调试1. 应该调试一、虚拟机 1.ssh服务项目 启动ssh服务 sudo /etc/init.d/ssh restart2.文件相关 查看文件大小显示kb ll -h 查看目录文件…...

在线文档技术-编辑器篇

这是在线文档技术的第二篇文章&#xff0c;本文将对目前市面上所有的主流编辑器和在线文档进行一次深入的剖析和研究&#xff0c;从而使大家对在线文档技术有更深入的了解&#xff0c;也让更多人能够参与其开发与设计中来。 注意&#xff1a;出于对主流文档产品的尊重&#xf…...

top -p pid为什么超过100%

CPU&#xff1a;Cores, and Hyper-Threading 超线程&#xff08;Hyper-Threading &#xff09; 超线程是Intel最早提出一项技术&#xff0c;最早出现在2002年的Pentium4上。单个采用超线程的CPU对于操作系统来说就像有两个逻辑CPU&#xff0c;为此P4处理器需要多加入一个Logic…...

#高光谱图像分类#:分类的方法有哪些?

高光谱图像分类方法可以根据分类粒度的不同分为基于像素的分类和基于对象的分类 高光谱图像分类方法可以根据分类粒度的不同分为基于像素的分类和基于对象的分类。 基于像素的分类&#xff1a;这种分类方法是针对每个像素进行分类&#xff0c;将像素的光谱信息作为输入特征&am…...

观察者模式

观察者模式常常用于以下场景&#xff1a;事件驱动系统&#xff1a;当事件发生时&#xff0c;通知所有对该事件感兴趣的观察者。发布/订阅模型&#xff1a;一个主题&#xff08;发布者&#xff09;可以有多个订阅者&#xff08;观察者&#xff09;&#xff0c;当主题发生改变时&…...

前端组件库自定义主题切换探索-03-webpack-theme-color-replacer webpack 同时替换多个颜色改造

接上一篇《前端组件库自定义主题切换探索-02-webpack-theme-color-replacer webpack 的实现逻辑和原理-02》 这篇我们来开始改造&#xff0c;让这个插件最终能达到我们的目的&#xff1a; 首先修改plugin.config.js。 插件首先要在vue.config.js引用注册&#xff0c;因此先对…...

Redis高级-主从复制相关操作

2.1 主从复制简介 2.1.1 高可用 首先我们要理解互联网应用因为其独有的特性我们演化出的三高架构 高并发 应用要提供某一业务要能支持很多客户端同时访问的能力&#xff0c;我们称为并发&#xff0c;高并发意思就很明确了 高性能 性能带给我们最直观的感受就是&#xff1a;速…...

SPI总线设备驱动模型

SPI总线设备驱动模型 文章目录SPI总线设备驱动模型参考资料&#xff1a;一、平台总线设备驱动模型二、 数据结构2.1 SPI控制器数据结构2.2 SPI设备数据结构2.3 SPI设备驱动三、 SPI驱动框架3.1 SPI控制器驱动程序3.2 SPI设备驱动程序致谢参考资料&#xff1a; 内核头文件&…...

开发同事辞职,接手到垃圾代码怎么办?

小王新加入了一家公司&#xff0c;这家公司有点年头&#xff0c;所以连屎山都是发酵过的&#xff0c;味道很冲。和大多数时运不济的程序员一样&#xff0c;到了这种公司&#xff0c;做的大多数工作&#xff0c;就是修补这些祖传代码&#xff0c;为其添砖加瓦。每当被折腾的筋疲…...

gRPC简介

grpc简介 grpc介绍可以参考官网。无论是rpc还是grpc&#xff0c;可以这样理解&#xff0c;都知道过去使用的单单体架构&#xff0c;而在2011年5月威尼斯的一个软件架构会议上提出了微服务架构&#xff0c;围绕业务功能进行组织(organized around business capability)&#xf…...

《MySQL系列-InnoDB引擎25》表-InnoDB逻辑存储结构

InnoDB逻辑存储结构 从InnoDB存储引擎的逻辑存储结构看&#xff0c;所有数据都被逻辑地存放在一个空间中&#xff0c;称之为表空间(tablespace)。表空间又由段(segment)、区(extent)、页(page)组成。页在一些文档中有时也称为块(block)&#xff0c;InnoDB存储引擎的逻辑存储结构…...

YOLOv8之C2f模块——与YOLOv5的C3模块对比

一、源码对比 YOLOv8完整工程代码下载&#xff1a;ultralytics/ultralytic   C2f模块源码在ultralytics/nn/modules.py下&#xff0c;源码如下&#xff1a; class C2f(nn.Module):# CSP Bottleneck with 2 convolutionsdef __init__(self, c1, c2, n1, shortcutFalse, g1, e…...

动态规划实例——换零钱的方法数(C++详解版)

原写了 Java 版本的如何求解换钱的方法数&#xff0c;近期进行了一些细节上的补充&#xff0c;以及部分错误更正&#xff0c;将语言换为了 C 语言。 基础题目 假设你现在拥有不限量的 1 元、5 元、10 元面值纸币&#xff0c;路人甲希望找你换一些零钱&#xff0c;路人甲拿出的…...

linux c

射频驱动 管理硬件设备、分配系统资源 内核由中断服务程序 调度程序 内存管理程序 网络和进程间进程通信程序 linux支持动态加载内核模块 支持多处理smp机制 内核可以抢占preemptive linux系统拥有多个发行版&#xff0c;可能由一个组织 公司和个人发行 VGA兼容或者更…...

第十三章 系统错误消息 - 一般系统错误消息 S - Z

文章目录第十三章 系统错误消息 - 一般系统错误消息 S - Z第十三章 系统错误消息 - 一般系统错误消息 S - Z 错误代码描述<SUBSCRIPT>下标值不合法或Global引用过长。<SWIZZLE FAIL>打开了一个oref&#xff0c;然后试图在另一个无法引用的相关对象中进行搅拌。这可…...

移动web基础

初始缩小&#xff1a;布局视口大于视觉视口 初始放大&#xff1a;布局视口小于视觉视口 布局视口等于视觉视口&#xff08;这种动作行为叫做理想视口&#xff09; <meta name"viewport" content"width375" /> <meta name"viewport"…...

MyBatis和MyBatis_Plus有什么区别【面试常考题】

MyBatis和MyBatis_Plus的区别 MyBatis_Plus MyBatis_Plus 是一个 MyBatis 的增强工具&#xff0c;只是在 MyBatis 的基础上增强了却没有做改变&#xff0c;MyBatis-Plus支持所有MyBatis原生的特性&#xff0c;所有引入MyBatis-Plus不会对现有的MyBatis框架产生任何影响。 MyBa…...

华为OD机试用Python实现 -【统一限载货物数最小值】(2023-Q1 新题)

华为OD机试题 华为OD机试300题大纲统一限载货物数最小值题目描述输入描述输出描述说明示例一输入输出说明示例二输入输出说明Python 代码实现算法逻辑华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查…...

Vue入门小练习

文章目录Hello VueVue文本指令Vue属性绑定Vue双向绑定Vue事件绑定Vue猜数字Vue简单计算器Vue简单计算器升级版Vue循环遍历Vue员工列表练习Vue小练习Vue显示隐藏相关使用一些简单的小案例来熟悉Vue的基本使用方法 Hello Vue <!DOCTYPE html> <html lang"en"…...

Oracle-09-集合运算符篇

2022年4月13日23:01:25 通过本章学习,您将可以:1、描述 SET 操作符2、将多个查询用 SET 操作符连接组成一个新的查询目录 🏆一、SET OPERATORS ⭐️1.1、UNION /UNION ALL ⭐️1.2、INSTERSECT ⭐️1.3、MINUS dz...

获取浏览器(服务端)请求中特定的Cookie

有必要解释一下HttpServletRequest接口&#xff0c;因为我们需要从它里面获取Cookie。 HttpServletRequest HttpServletRequest是一个Java接口&#xff0c;提供了访问HTTP请求信息的方法&#xff0c;例如HTTP方法、请求URI、头部、参数和会话属性。它是Java Servlet API的一部…...

c++11 标准模板(STL)(std::unordered_set)(九)

定义于头文件 <unordered_set>template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templat…...

python实战应用讲解-【实战应用篇】文件操作(附python示例代码)

目录 知识储备 使用 python-libarchive-c 模块 创建压缩文件 解压文件 查看信息...

OpenCV-Python系列(二)—— 图像处理(灰度图、二值化、边缘检测、高斯模糊、轮廓检测)

一、【灰度图、二值化】 import cv2 img cv2.imread("lz2.png") gray_img cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图 # 二值化&#xff0c;(127,255)为阈值 retval,bit_img cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY) cv2.imshow(photo1,im…...

ccc-台大林轩田机器学习基石-hw1

文章目录Question1-14Question15-PLAQuestion16-PLA平均迭代次数Question17-不同迭代系数的PLAQuestion18-Pocket_PLAQuestion19-PLA的错误率Question20-修改Pocket_PLA迭代次数Question1-14 对于有明确公式和定义的不需要使用到ml 智能系统在与环境的连续互动中学习最优行为策…...

嘉兴专业网站建设/百度快照什么意思

up主0x000006b怎么办&#xff0c;开机就蓝屏&#xff0c;安全模式也是&#xff0c;好像是因为下载一个东西时我强制关机了&#xff0c;重新开机就蓝屏了。电脑小白[大哭][大哭][大哭][大哭]可能是你下载的“软件”和电脑中的“内存”有冲突了我给你12种方法调试,快试试吧&#…...

wordpress防垃圾注册/合肥seo排名扣费

1.左连接 left join左表全部保留&#xff0c;右表关联不上的用null表示 select * from t1 left join t2 on t1.idt2.id; 2.右连接 right join3. 内连接 inner join4. 查询左表独有部分数据5.查询右表边独有部分数据6.全连接在mysql中没有full join7....

网站开发需要先学数据库么/网络营销在哪里学比较靠谱

1、curl仍然是最好的HTTP库&#xff0c;没有之一。 可以解决任何复杂的应用场景中的HTTP 请求2. 文件流式的HTTP请求比较适合处理简单的HTTP POST/GET请求&#xff0c;但不适用于复杂的HTTP请求3. PECL_HTTP扩展写代码更加简洁&#xff0c;省事&#xff0c; 但成熟度不好&#…...

给漫画网站做推广/google推广专员招聘

什么是跨域 假设我们页面或者应用已在 http://www.test1.com 上了&#xff0c;而我们打算从 http://www.test2.com 请求提取数据。一般情况下&#xff0c;如果我们直接使用 AJAX 来请求将会失败&#xff0c;浏览器也会返回“源不匹配”的错误&#xff0c;"跨域"也就以…...

汕头吧 百度贴吧/优化疫情防控措施

2019独角兽企业重金招聘Python工程师标准>>> $(document).mousedown(function(e) {var clientY e.clientY;// .panel-body为需要点击滑动的容器&#xff0c;需要加style"overflow: auto;"var scrollTop $(.panel-body)[0].scrollTop;$(document).mousem…...

wordpress静态页面生成/电商平台怎么运营的

作为Hadoop生态圈中的重要组件&#xff0c;Hive在数据分析、处理方面扮演着异常重要的角色。另外&#xff0c;Hive作为大数据组件&#xff0c;处理的数据量往往很大&#xff0c;合适的优化技巧在运行效率方面往往可以起到非常好的效果。 1、筛选重复记录 这是在业务中经常遇到…...