android 布局优化

news/2024/7/16 9:22:25 标签: android studio, android, ide

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.niftyadmin.cn/n/260962.html

相关文章

【13 Listener 学习笔记】

Listener 笔记记录 1. Listener监听器2. 监听对象的监听器2.1 ServletContetListener2.2 HttpSessionListener2.3 ServletRequestListener 3. 监听域对象属性变化的监听器3.1 ServletContextAttributeListener3.2 HttpSessionAttributeListener3.3 ServletRequestAttributeList…

什么是内存?什么是内存逃逸?怎么做内存逃逸分析

内存 平时我们在电脑上听歌&#xff0c;聊天&#xff0c;或者启动某个程序&#xff0c;那么这个启动过程&#xff0c;其实就是把程序从硬盘读入到内存中去。就像安卓手机&#xff0c;内存不够了很卡&#xff0c;杀掉几个软件&#xff0c;内存就升上来了。但也不是所有的程序都…

React入门学习

参考资料&#xff1a;https://bright-boy.gitee.io/technical-notes/#/react/React%E5%85%A5%E9%97%A8 https://github.com/xzlaptt/React react学习01: https://docs.qq.com/doc/DSG1jdUJtQ3FYR1V1 react学习02: https://docs.qq.com/doc/DSGhGZk9PUm1KVldv React简介 框架定…

图片对象列表查询与展示(vue+springboot+elementUI)

本文描述场景为 展示&#xff1a;后端从数据库中查询图片对象列表&#xff0c;返回前端展示 多图片展示 先看一下后端表实体 import com.zpmc.common.domain.BaseEntity; import io.swagger.annotations.ApiModel; import lombok.*;import javax.persistence.*; import java.…

three.js地图可视化项目-广州模型

概述 如有不明白的可以加QQ&#xff1a;2354528292&#xff1b;wx: aichitudousien 更多教学视频请访问&#xff1a;https://space.bilibili.com/236087412 详细教学请到上方视频链接访问&#xff0c;总共3个多小时的教学~ three.js地图可视化项目-广州模型 搭建开发环境 使用…

RAC 到单实例恢复rman

1.备份源库并copy到目标环境中 2.恢复控制文件。 将数据库启动至nomount状态 restore controlfile from 控制文件备份集; 3. 注册备份集 RMAN下&#xff1a;catalog start with 备份集所在目录; 4. 还原数据库 获取datafile select set newname for …

铁路应答器传输系统介绍

应答器传输系统 应答器传输系统是安全点式信息传输系统&#xff0c;通过应答器实现地面设备向车载设备传输信息。 应答器可根据应用需求向车载设备传输固定的&#xff08;通过无源应答器&#xff09;或可变的&#xff08;通过有源应答器&#xff09;上行链路数据。 当天线单…

前端性能优化的技巧和方法

作为前端开发工程师&#xff0c;优化网站性能是每个人的必修课程。在这篇文章中&#xff0c;我将分享前端性能优化的技巧和方法。 代码压缩和合并 代码压缩和合并是一种有效的优化网站性能的方法。所有在开发过程中编写的 JavaScript 和 CSS 文件都需要进行压缩和合并。在压缩…