Android修行手册-卡顿优化布局篇【建议收藏】

简介: 众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!

👉关于作者

众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!

专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)

👉即将学会

就看能学会多少了!

👉背景

在当下移动互联网后半场,手机已经是人手必备的设备。App是离用户最近的应用,界面又是最直观影响用户体验的关键部分,其流畅度直接影响用户对产品的评价和留存。

技术是服务于人的,如果技术无法给你带来良好的体验,那技术本身的存在就具有争议。

所以界面性能是至关重要的,不可忽视。

👉实践过程

布局代码是最基础的,但也是最重要的。

首先我们看个简单小案例

网络异常,图片无法展示
|

不同深浅的颜色来表示过度绘制:

没颜色:没有过度绘制,即一个像素点绘制了 1 次,显示应用本来的颜色;

蓝色:1倍过度绘制,即一个像素点绘制了 2 次;

绿色:2倍过度绘制,即一个像素点绘制了 3 次;

浅红色:3倍过度绘制,即一个像素点绘制了 4 次;

深红色:4倍过度绘制及以上,即一个像素点绘制了 5 次及以上;

😜如何渲染界面

CPU(中央处理器) :我们经常听到,是计算机的核心器件,多缓存多分支,适用于复杂的逻辑运算,主要负责Measure,Layout,Record,Execute的计算操作

GPU(图像处理器):我们通常说的显卡核心就是它了。用于结构单一的数据处理(擅长图形计算),主要负责Rasterization(栅格化)操作

谷歌官方对于流畅度的优化也是高度重视的,有界面渲染三核心Vsync、Triple Buffer和Choreographer。

为何是16ms/为何每秒60帧

android系统每隔16ms绘制一帧UI且要在16ms内完成,( 1秒 / 0.016帧每秒 = 62.5帧/秒 )差不多每秒更新60次。这是因为我们大脑和眼睛一般看24Fps的画面就已经是连续的运动了,看60Fps的画面更看不出端倪,但是60帧可以表达出更加绚丽多彩的内容。

一旦没及时绘制,就会出现掉帧问题,也就是常说的卡顿。这是因为绘制的东西太多的话,CPU、GPU处理不及时。

当然了,设备性能越好,处理能力越强,卡顿会越少,玩游戏的电脑配置高也是出于这方面考虑。

那么Android是如何把图像绘制到界面上的呢?

这就用到了上面的CPU/GPU。

GPU负责栅格化操作(Resterization),栅格化是绘制那些Button,Shape,Path,String,Bitmap等组件最基础的操作。它把那些组件拆分到不同的像素上进行显示。这是一个很“费时”的操作(相比人类时间只是眨眼的功夫),GPU的引入就是为了加快栅格化的操作。

CPU负责把UI组件计算成Polygons,Texture纹理,然后交给GPU进行栅格化渲染。流程如下:

网络异常,图片无法展示
|

为了能够使得App流畅,我们需要在每一帧16ms以内处理完所有的CPU与GPU计算,绘制,渲染等等操作。

有兴趣更深层学习的,可以去看看界面渲染容器DisplayList

😜什么是过度绘制

Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了N次。但是我们只能看到最上层的UI,这就会导致多层次的UI界面除最上层外对用户都是不可见的,这样就会浪费大量的CPU以及GPU资源,浪费可耻。

这就像我们在纸上固定区域不断图画,但是有最上层最接近你,其他层有个鬼用?

😜如何查看绘制维度

开发工具有Hierarchy View、Systrace、Track等

真机在开发者选项中有:调试GPU绘制、硬件层更新、GPU视图更新等等

😜界面优化

在编写Android布局时总会遇到这样或者那样的痛点,比如:

  • 1.有些布局的在很多页面都用到了,而且样式都一样,每次用到都要复制粘贴一大段,有没有办法可以复用呢?
  • 2.解决了1中的问题之后,发现复用的布局外面总要额外套上一层布局,要知道布局嵌套是会影响性能的呐;
  • 3.有些布局只有用到时才会显示,但是必须提前写好,虽然设置了为invisible或gone,还是多多少少会占用内存的。

首先第一点也是最重要的一点,在刚开始写布局的时候一定要提前想好和规划好,尽可能的减少层级的嵌套。往往越复杂的布局越臃肿,越容易被忽视进而出现性能问题,所以我们写布局就要知道一些技巧来展示布局

  • 1. 如果图片和文字在一起且文字不动态变的话,可以直接使用带文字的图片。
  • 2. 移除没用的布局和控件,假设添加个背景,尽可能在已经布局上放,减少只有背景功能的控件。
  • 3. 减少透明度的使用,假设:#55FFFFFF 和 #888888 颜色类似,建议使用后者,因为前者有Alpha,view需要至少绘制两次。
  • 4. 去掉多余的不可见颜色背景、图片等,只保留最上层用户可见即可
  • 5. 减少布局层次结构,避免多层嵌套推荐使用RelativeLayout、ConstraintLayout等父类布局
  • 6. 基本控件LinearLayout 性能比RelativeLayout高一些,要提前根据UI想好哪个布局更合适,要有的方式,对症下药。
  • 7. 自定义View尽可能只更新渲染局部区域,杜绝不断全部重绘。
  • 8. 推荐使用IDE自带的Lint或者阿里代码检查插件,对于标黄警告等提示重视起来,能改的就改。

除了以上,我们就要解决过度绘制,我们还可以使用抽象布局,它们分别是include、merge和ViewStub三个标签,现在我们就来认识认识它们吧。

Include应该是最常用的了,其翻译是“包含”、“包括”,最佳使用就是把相同代码抽离出来成一个独立的xml文件,当你在某个布局需要使用的时候直接include进来,这样一搞,很好地起到复用布局的效果。不仅可以极大地减少代码量,想要修改的话直接改这一个xml就行了。

它的两个主要属性:layout:必填属性, id属性;

我们还可以重写宽高、边距和可见性(visibility)这些布局属性。但是一定要注意,单单重写android:layout_height或者android:layout_width是不行,必须两个同时重写才起作用。

这些也能玩不不少花样。

Merge介绍

凡事都有利有弊include标签除了上面的优点,也有个问题就是布局嵌套。他必须有一个根布局,这也导致了最终布局嵌套层级可能多一层。

这时候又引出个新的标签标签,这次先说他的局限性:就是你需要提前明确要放到什么父布局中,然后提前设置好merge里面的控件位置。

优点也明显:他是消除多余层级的,标签必须作为根节点出现。不占用空间,他只是将子view“搬运”到你想嵌套的位置。

ViewStub

写布局的时候我们经常会遇到有些效果不必一直显示,需要动态的来设置invisible或gone,这无形中影响了页面加载速度。

Android提供的方案就是ViewStub,他是一个不可见的大小为0的视图,具有懒加载功能,存在于视图中,但只有设置setVisibility()和inflate()方法调用后才会渲染填充视图,能为初始化加载xml布局分散压力,就像负载均衡。

使用案例:进度条,加载网络失败,显示错误消息等等

它有以下三个重要属性:

android:layout:ViewStub需要填充的视图名称,为“R.layout.xx”的形式;

android:inflateId:重写被填充的视图的父布局id。

与include标签不同,ViewStub的android:id属性是设置ViewStub本身id的,而不是重写布局id,这一点可不要搞错了。另外,ViewStub还提供了OnInflateListener接口,用于监听布局是否已经加载了。

但是注意 viewStub.inflate();方法不能多次调用,否则抛出异常:

java.lang.IllegalStateException: ViewStubmusthaveanon-nullViewGroupviewParent

原因是ViewStub源码调用了removeViewInLayout()方法把自己从布局移除了。到这里我们就明白了,ViewStub在填充布局成功之后就会自我销毁,再次调用inflate()方法就会抛出IllegalStateException异常了。此时如果想要再次显示布局,可以调用setVisibility()方法。

还有一个大坑:viewStub.getVisibility()的值一直为0,所以用他来判断是否显示没作用。不要急,其实是setVisibility()方法实际上在设置内部视图的可见性,而不是ViewStub本身。

😜硬件加速原理

网络异常,图片无法展示
|

相信经常看到有的文章说开启硬件加速解决卡的问题,但硬件加速是什么呢?

硬件加速的主要原理是通多底层逻辑,将CPU不擅长的图形计算转换成GPU专用指令,让更擅长图形计算的GPU来完成渲染。

硬件加速过程中包含两个步骤 :

构建阶段 : 遍历所有视图,将需要绘制的操作缓存下来,交给单独的Render线程使用GPU进行硬件加速渲染。(这一阶段在主线程中使用CPU构建)

绘制阶段 : 调用OpenGL(即使用GPU)对构建好的视图进行绘制渲染,绘制的内容保存在Graphic Buffer 并交由 SurfaceFlinger 显示。(Android 5.0+ 使用Render Thread线程,专门负责 UI 渲染和动画显示。)

以上证得硬件加速具有不错的优点,但它不是万能的。

我们平时用的时候可能是直接在Application中用,一锅端,这并不严谨,因为硬件加速还没法做到支持所有的绘制操作(比如复杂的自定义View),这样的话就会造成一定的影响:

1. 像素错位等视觉问题

2. 不同设备版本API兼容问题

解决这些问题官方给了解决方案:使用四种级别控制是否硬件加速。

1. Application

网络异常,图片无法展示
|

2. Activity-为单独页面设置

网络异常,图片无法展示
|

3. Window级别

网络异常,图片无法展示
|

4. 单独的view级别关闭加速(View目前不支持动态启动硬件加速)

网络异常,图片无法展示
|


👉其他

📢作者:小空和小芝中的小空

📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
相关文章
|
27天前
|
缓存 监控 Java
构建高效Android应用:从优化用户体验到提升性能
在竞争激烈的移动应用市场中,为用户提供流畅和高效的体验是至关重要的。本文深入探讨了如何通过多种技术手段来优化Android应用的性能,包括UI响应性、内存管理和多线程处理。同时,我们还将讨论如何利用最新的Android框架和工具来诊断和解决性能瓶颈。通过实例分析和最佳实践,读者将能够理解并实施必要的优化策略,以确保他们的应用在保持响应迅速的同时,还能够有效地利用系统资源。
|
1月前
|
调度 数据库 Android开发
构建高效Android应用:Kotlin协程的实践与优化
在Android开发领域,Kotlin以其简洁的语法和平台友好性成为了开发的首选语言。其中,Kotlin协程作为处理异步任务的强大工具,它通过提供轻量级的线程管理机制,使得开发者能够在不阻塞主线程的情况下执行后台任务,从而提升应用性能和用户体验。本文将深入探讨Kotlin协程的核心概念,并通过实例演示如何在实际的Android应用中有效地使用协程进行网络请求、数据库操作以及UI的流畅更新。同时,我们还将讨论协程的调试技巧和常见问题的解决方法,以帮助开发者避免常见的陷阱,构建更加健壮和高效的Android应用。
36 4
|
1月前
|
数据库 Android开发 开发者
构建高效Android应用:采用Kotlin协程优化网络请求处理
【2月更文挑战第30天】 在移动应用开发领域,网络请求的处理是影响用户体验的关键环节。针对Android平台,利用Kotlin协程能够极大提升异步任务处理的效率和简洁性。本文将探讨如何通过Kotlin协程优化Android应用中的网络请求处理流程,包括协程的基本概念、网络请求的异步执行以及错误处理等方面,旨在帮助开发者构建更加流畅和响应迅速的Android应用。
|
25天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
3天前
|
移动开发 Java Android开发
构建高效Android应用:采用Kotlin协程优化网络请求
【4月更文挑战第24天】 在移动开发领域,尤其是对于Android平台而言,网络请求是一个不可或缺的功能。然而,随着用户对应用响应速度和稳定性要求的不断提高,传统的异步处理方式如回调地狱和RxJava已逐渐显示出局限性。本文将探讨如何利用Kotlin协程来简化异步代码,提升网络请求的效率和可读性。我们将深入分析协程的原理,并通过一个实际案例展示如何在Android应用中集成和优化网络请求。
|
9天前
|
缓存 移动开发 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【4月更文挑战第18天】 在移动开发的世界中,打造一个既快速又流畅的Android应用并非易事。本文深入探讨了如何通过一系列创新的技术策略来提升应用性能和用户体验。我们将从用户界面(UI)设计的简约性原则出发,探索响应式布局和Material Design的实践,再深入剖析后台任务处理、内存管理和电池寿命优化的技巧。此外,文中还将讨论最新的Android Jetpack组件如何帮助开发者更高效地构建高质量的应用。此内容不仅适合经验丰富的开发者深化理解,也适合初学者构建起对Android高效开发的基础认识。
10 0
|
15天前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。
|
19天前
|
XML 开发工具 Android开发
构建高效的安卓应用:使用Jetpack Compose优化UI开发
【4月更文挑战第7天】 随着Android开发不断进化,开发者面临着提高应用性能与简化UI构建流程的双重挑战。本文将探讨如何使用Jetpack Compose这一现代UI工具包来优化安卓应用的开发流程,并提升用户界面的流畅性与一致性。通过介绍Jetpack Compose的核心概念、与传统方法的区别以及实际集成步骤,我们旨在提供一种高效且可靠的解决方案,以帮助开发者构建响应迅速且用户体验优良的安卓应用。
|
1月前
|
缓存 前端开发 Android开发
构建高效Android应用:从设计原则到性能优化
随着移动设备成为我们日常生活不可或缺的一部分,开发一个流畅且响应迅速的Android应用变得至关重要。本文将探讨如何通过遵循Android设计原则和实施细致的性能优化策略来构建高效的Android应用程序。我们将深入分析应用架构的选择、内存管理的要点以及UI设计的优化,旨在为开发人员提供一套实用的指导方针,帮助他们提升应用的整体性能和用户体验。
|
1月前
|
监控 Java Android开发
构建高效Android应用:从内存管理到性能优化
【2月更文挑战第30天】 在移动开发领域,打造一个流畅且响应迅速的Android应用是每个开发者追求的目标。本文将深入探讨如何通过有效的内存管理和细致的性能调优来提升应用效率。我们将从分析内存泄露的根本原因出发,讨论垃圾回收机制,并探索多种内存优化策略。接着,文中将介绍多线程编程的最佳实践和UI渲染的关键技巧。最后,我们将通过一系列实用的性能测试工具和方法,帮助开发者监控、定位并解决性能瓶颈。这些技术的综合运用,将指导读者构建出更快速、更稳定、用户体验更佳的Android应用。