android 布局优化

news2024/11/13 10:23:30

1.绘制和布局加载原理

 本文仅供个人学习记录,详细介绍可查看下面链接

Android布局优化,多套方案全面解析

布局优化的原因:布局嵌套过深,或者其他原因导致布局渲染性能不佳,可能会导致应用卡顿。

android绘制原理:

  • CPU:执行应用层的measure、layout、draw等操作,绘制完成后将数据提交给GPU

  • GPU:进一步处理数据,并将数据缓存起来

  • 屏幕:由一个个像素点组成,以固定的频率(16.6ms,即1秒60帧)从缓冲区中取出数据来填充像素点

总结一句话就是:CPU 绘制后提交数据、GPU 进一步处理和缓存数据、最后屏幕从缓冲区中读取数据并显示。

  • 双缓冲机制

GPU只向Back Buffer中写入绘制数据,且GPU会定期交换Back Buffer和Frame Buffer(频率也是60次/秒),

掉帧当布局复杂或设备性能较差,CPU并不能保证在16.6ms内就完成绘制数据的计算,系统会将Back Buffer锁定,到了GPU交换两个Buffer的时间点,应用还在往Back Buffer中填充数据,GPU会发现Back Buffer被锁定了,它会放弃这次交换。

导致掉帧的原因是CPU无法在16.6ms内完成绘制数据的计算。

  • 布局加载原理

setContentView中主要有两个耗时操作

1. 解析xml,获取XmlResourceParser,这是IO过程 

2.通过createViewFromTag,创建View对象,用到了反射

2.获取布局文件加载耗时的方法

  • 常规获取

val start = System.currentTimeMillis()
setContentView(R.layout.activity_layout_optimize)
val inflateTime = System.currentTimeMillis() - start

setContentView是同步方法,直接将前后时间计算相减

优点:简单;

缺点:不够优雅,代码有侵入性,监听所有麻烦。

  • AOP(Aspectj,ASM)

 @Around("execution(* android.app.Activity.setContentView(..))")
    public void getSetContentViewTime(ProceedingJoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String name = signature.toShortString();
        long time = System.currentTimeMillis();
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        Log.i("aop inflate",name + " cost " + (System.currentTimeMillis() - time));
    }
  • 获取任一控件耗时

利用setFactory2来监听每个控件的加载耗时

  private fun initItemInflateListener(){
        LayoutInflaterCompat.setFactory2(layoutInflater, object : Factory2 {
            override fun onCreateView(
                parent: View?,
                name: String,
                context: Context,
                attrs: AttributeSet
            ): View? {
                val time = System.currentTimeMillis()
                val view = delegate.createView(parent, name, context, attrs)
                Log.i("inflate Item",name + " cost " + (System.currentTimeMillis() - time))
                return view
            }

            override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
                return null
            }
        })
    }

initItemInflateListener需要在onCreate之前调用

 布局加载优化的一些方法介绍

  • AsyncLayoutInflater方案

帮助做异步加载 layout 的,inflate(int, ViewGroup, OnInflateFinishedListener) 方法运行结束之后 OnInflateFinishedListener 会在主线程回调返回 View;这样做旨在 UI 的懒加载或者对用户操作的高响应。

优点在于将UI加载过程迁移到了子线程,保证了UI线程的高响应 缺点在于牺牲了易用性,同时如果在初始化过程中调用了UI可能会导致崩溃

  • X2C方案

// this.setContentView(R.layout.activity_main);
X2C.setContentView(this, R.layout.activity_main);

优点:

1.在保留xml的同时,又解决了它带来的性能问题

2.据X2C统计,加载耗时可以缩小到原来的1/3

缺点:

1.部分属性不能通过代码设置,Java不兼容

2.将加载时间转移到了编译期,增加了编译期耗时

3.不支持kotlin-android-extensions插件(已被废弃),牺牲了部分易用性

  • Anko方案

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
        super.onCreate(savedInstanceState, persistentState)
        MyActivityUI().setContentView(this)
    }
}

class MyActivityUI : AnkoComponent<MyActivity> {
    override fun createView(ui: AnkoContext<MyActivity>) = with(ui) {
        verticalLayout {
            val name = editText()
            button("Say Hello") {
                onClick { ctx.toast("Hello, ${name.text}!") }
            }
        }
    }
}

Anko使用kotlin DSL实现布局,它比我们使用Java动态创建布局方便很多,主要是更简洁,它和拥有xml创建布局的层级关系,能让我们更容易阅读,去除了IO与反射过程,性能更好

  • Compose方案

主要优点就在于它的简单好用

1.它的声明式 UI

2.去掉了 xml,只使用 Kotlin 一种语言

3.优化布局层级及复杂度

1.使用ConstraintLayout,可以实现完全扁平化的布局,减少层级

2.RelativeLayout本身尽量不要嵌套使用

3.嵌套的LinearLayout中,尽量不要使用weight,因为weight会重新测量两次

4.推荐使用merge标签,可以减少一个层级

//假定自定义View为RelativeLayout
public class LoginButton extends RelativeLayout {
 	。。。
}
//在xml标签中使用merge作为根标签,而不要再次使用RelativeLayout作为根标签,可以省去一个层级

5.使用ViewStub延迟加载

<ViewStub
        android:id="@+id/contentPanel"
        android:inflatedId="@+id/inflatedStart"
        android:layout="@layout/delayInflateLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        />

6.去掉多余背景色,减少复杂shape的使用

7.避免层级叠加

8.自定义View使用clipRect屏蔽被遮盖View绘制

4布局查看工具

1.使用Layout Inspater检查布局层级

1、在连接的设备或模拟上运行你的应用

2、点击Tools > Layout Inspector

3、在出现的Choose Process对话框中,选择你想要检查的应用进程,然后点击OK。

或者直接在布局文件查看

 2.使用调试GPU过度绘制功能检查过度绘制

从开发者模式中找到调试GPU过度绘制功能开关

检查 GPU 渲染速度和过度绘制  |  Android 开发者  |  Android Developers

参考

Android性能优化(三)-绘制优化 - 掘金 

检查 GPU 渲染速度和过度绘制  |  Android 开发者  |  Android Developers

Android布局优化,多套方案全面解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/448257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.3 牛顿-科茨公式

学习目标&#xff1a; 理解微积分基础知识&#xff0c;例如导数和微分的概念。学习牛顿-科茨公式的推导过程。这个公式实际上是使用泰勒公式对被积函数进行展开&#xff0c;并使用微积分的基本原理进行简化得到的。学习如何使用牛顿-科茨公式进行数值积分。这通常涉及到将被积…

Ajax超详解(新手入门指南)

文章目录 1. AJAX简介2. 前后端交互3. XHR3.1 XMLHttpRequest对象3.2 获取模拟的后端数据3.3 获取网络数据3.4 使用json-server模拟服务器3.4.1 安装node.js3.4.2 安装并使用json-server 3.5 常见的请求方式3.5.1 GET请求3.5.2 POST请求3.5.3 PUT请求3.5.4 PATCH请求3.5.5 DELE…

【图像分割】Segment Anything(Meta AI)论文解读

文章目录 摘要一、引言二、segment anything任务1.任务2.预训练3.zero shot transfer4.相关任务5.讨论 三*、Segment Anything 模型四、Segment Anything 数据引擎五、Segment Anything 数据集六、Segment Anything RAI分析七、Zero-Shot Transfer 实验1.zero shot 单点有效掩模…

springboot本地local配置覆盖远程Apollo配置(含Apollo配置加载顺序说明)

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/130302692 目录 前言 Apollo配置加载顺序 步骤 第一步&#xff1a;Apollo创建properties 第二步&#xff1a;添加namespaces&…

js的dom事件流、事件委托和阻止绑定事件触发

主要讲解事件绑定和事件委托&#xff0c;onclick事件和addEventListener的区别 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&l…

IT项目管理计算题【太原理工大学】

计算题好像也没多少考点&#xff0c;主要就是记公式吧&#xff0c;其他的不想看了&#xff0c;直接考啥看啥&#xff0c;就看两个&#xff1a; ① 根据进度网络图写出时间参数表&#xff0c;ES、EF、LS、LF、TF 以及 FF&#xff0c;关键路径&#xff0c;总工期&#xff1b;② 挣…

volatile 保证内存变量可见性的实现原理解析

目录 volatile 的定义 可见性问题 JMM&#xff08;JavaMemoryModel&#xff09; 保证可见性 现代计算机的内存模型 MESI&#xff08;缓存一致性协议&#xff09; 嗅探 总线风暴 volatile 的两条实现原则 volatile 的定义 Java代码在编译后会编程 Java …

GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相操作

写在前面 本文主要针对使用GD&#xff08;兆易创新&#xff09;系列的FLASH做启动配置片时&#xff0c;遇到的相关问题进行简单整理复盘&#xff0c;避免后人踩坑。 本人操作固化芯片型号为&#xff1a;ZYNQ7045、690T&#xff08;复旦微替代型号V7 690T&#xff09;。 7系列…

02-waf绕过漏洞发现之代理池指纹被动探针

WAF绕过-漏洞发现之代理池指纹被动探针 思维导图 漏洞发现触发WAF点-针对xray工具&#xff0c;awvs工具等 1.扫描速度&#xff08;绕过方法&#xff1a;代理池&#xff0c;延迟&#xff0c;爬虫白名单&#xff09;2.工具指纹&#xff08;绕过方法&#xff1a;特征指纹&#x…

Qt Quick - Container

Qt Quick - Container使用总结 一、概述二、使用容器三、管理当前索引四、容器实现 一、概述 Container 提供容器通用功能的抽象基类。Container是类容器用户界面控件的基本类型&#xff0c;允许动态插入和删除Item。DialogButtonBox, MenuBar, SwipeView, 和 TabBar 都是继承…

测试工程师为什么要关注研发效能?

研发效能中的“研发”&#xff0c;指的是广义的研发团队&#xff0c;包含开发、测试、和研发团队内部的产品经理&#xff08;不包含业务部门的产品经理&#xff09;。测试工程师身处其中&#xff0c;作为研发团队的一员&#xff0c;对于整体的效能如何提升也应该了然于胸。这篇…

【论文写作】如何写科技论文?万能模板!!!(以IEEE会议论文为例)

0. 写在前面 常言道&#xff0c;科技论文犹如“八股文”&#xff0c;有固定的写作模式。本篇博客主要是针对工程方面的论文的结构以及写作链条的一些整理&#xff0c;并不是为了提高或者润色一篇论文的表达。基本上所有的论文&#xff0c;都需要先构思好一些点子&#xff0c;有…

「计算机控制系统」5. 模拟设计法

模拟控制器的离散化 数字PID控制器 Smith预估控制 文章目录 模拟控制器的离散化数值积分法一阶后向差分法一阶前向差分法双线性变换法&#xff08;Tustin&#xff09; 零极点匹配法其他方法 数字PID控制器模拟PID控制器的离散化数字PID的改进PID控制各环节的作用PID参数的整定扩…

win11删除的文件不在回收站原因及找回文件方法

win11是微软最新推出的操作系统&#xff0c;它的外观和功能都有所升级。但是&#xff0c;在使用win11的过程中&#xff0c;有时候你会误删一些重要的文件&#xff0c;而这些文件并没有进入回收站&#xff0c;这该怎么办呢&#xff1f;win11删除的文件不在回收站怎么找回&#x…

[强化学习]学习路线和关键词拾零

强化学习学习方法和路线 学习路线 先从基础教材开始&#xff0c;构建RL的知识框架&#xff0c;熟悉关键名词和公式推导&#xff0c;扩展到Model-Free的Value-Based和Policy-Based方法&#xff0c;同时参考github的代码练习。接下来精读几篇经典论文&#xff0c;如DQN,PPO等。…

Node内置模块 【压缩zlib模块】

文章目录 &#x1f31f;前言&#x1f31f;zlib模块&#x1f31f;关于gzip与deflate&#x1f31f;使用zlib&#x1f31f;压缩与解压缩&#x1f31f;案例&#xff1a;压缩&#x1f31f;案例&#xff1a;解压缩 &#x1f31f;服务端gzip压缩&#x1f31f;HTTP配置&#x1f31f;HTT…

Android Binder图文详解和驱动源码分析

文章目录 前言一、跨进程通讯的过程1. AIDL客户端代码2. AIDL服务端代码3. 通信过程a. 发送请求时序图b. 接收请求时序图 二、Binder一次拷贝1. 发送给Binder驱动的数据2. 一次拷贝示意图 三、Binder驱动源码1. 相关数据结构2. 阅读Binder驱动源码 参考 前言 最近在学习Binder…

Jupyter Notebook的安装与使用

Jupyter Notebook Jupyter Notebook介绍Jupyter Notebook使用安装启动创建文件编写代码和文本常用命令配置文件 Anaconda Jupyter Notebook介绍 Jupyter Notebook是一个基于Web的交互式计算环境&#xff0c;可以让用户以文档形式记录代码、数据分析结果和说明文本&#xff0c;并…

认识ThinkPHP框架

认识ThinkPHP框架 前言一、MVC框架体系二、 ThinkPHP框架文件夹结构三. ThinkPHP下载和基本配置四. ThinkPHP其他东西 前言 ThinkPHP框架是一款非常优秀的PHP框架&#xff0c;是完全由中国人发明的框架 一、MVC框架体系 ThinkPHP框架由MVC框架体系构成&#xff0c;MVC的解释如下…

ubuntu下安装配置grpc

目录 1.准备环境 2.安装protobuf 3.安装cares库 3.安装grpc-1.17.x 1.准备环境 sudo apt-get install pkg-config sudo apt-get install autoconf automake libtool make g unzip sudo apt-get install libgflags-dev libgtest-dev sudo apt-get install clang libc-dev 如…