Android性能优化之中的一个 布局优化
本文为Android性能优化——布局优化,主要介绍使用抽象布局标签(include, viewstub, merge)、去除不必要的嵌套和View节点、降低不必要的infalte及其它Layout方面可调长处,顺带提及布局调优相关工具(hierarchy viewer和lint)。
一、布局复杂度的优化
关于布局的优化,主要分两个慷慨向
- 实现同样界面效果而且层级结构同样时,选用何种Layout最好
在Android中单独的布局性能:
FrameLayout>LinearLayout>RelativeLayout
总结:
RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure;
RelativeLayout的子View假设高度和RelativeLayout不同。则会引发效率问题。当子View非常复杂时。这个问题会更加严重。假设能够。尽量使用padding取代margin;
在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout;
使用组合控件性能要好于两个独立控件,比方一个文本旁边有一个图片,这中情况最好要用DrawableLeft的这样的属性设置图片;
- 降低布局的层级结构
HierarchyViewer—可查看布局层次结构,View绘制时耗时。
无线UIViewer—强烈推荐App工具。可在手机端直接实现HierarchyViewer的功能。查看随意界面的UI布局。
总结:
一些复用性非常高的布局文件,比方一个App的标题栏,建议使用布局重用include标签。方便引入和共同管理。
观察上图第三个层级和第四个层级,不管是Layout类型。还是所覆盖的坐标点。都是重合的。由于父FrameLayout作为一个Container。子FrameLayout作为一个子View的跟布局,这样的情况。可使用merge标签进行布局层级的优化。
有些在特定情况下才会出现的界面,比方联网之后,或者未必百分之百出现的界面。可用ViewStub标签进行懒载入,性能明显要优于载入出这个界面然后gone掉。
(1) 标签
include标签经常使用于将布局中的公共部分提取出来供其它layout共用。以实现布局模块化,这在布局编写方便提供了大大的便利。
以下以在一个布局main.xml中用include引入还有一个布局foot.xml为例。main.mxl代码例如以下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@+id/simple_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/dp_80" />
<include layout="@layout/foot.xml" />
</RelativeLayout>
当中include引入的foot.xml为公用的页面底部,代码例如以下:
<?
xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_above="@+id/text"/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_alignParentBottom="true"
android:text="@string/app_name" />
</RelativeLayout>
标签唯一须要的属性是layout属性,指定须要包括的布局文件。能够定义android:id和android:layout_*属性来覆盖被引入布局根节点的相应属性值。
注意又一次定义android:id后。子布局的顶结点i就变化了。
(2) 标签
viewstub标签同include标签一样能够用来引入一个外部布局,不同的是。viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置。从而在解析layout时节省cpu和内存。
viewstub经常使用来引入那些默认不会显示。仅仅在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。
以下以在一个布局main.xml中添加网络错误时的提示页面network_error.xml为例。
main.mxl代码例如以下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ViewStub
android:id="@+id/network_error_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/network_error" />
</RelativeLayout>
当中network_error.xml为仅仅有在网络错误时才须要显示的布局。默认不会被解析,演示样例代码例如以下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/network_setting"
android:layout_width="@dimen/dp_160"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="@string/network_setting" />
<Button
android:id="@+id/network_refresh"
android:layout_width="@dimen/dp_160"
android:layout_height="wrap_content"
android:layout_below="@+id/network_setting"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/dp_10"
android:text="@string/network_refresh" />
</RelativeLayout>
在java中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View。例如以下:
private View networkErrorView;
private void showNetError() {
// not repeated infalte
if (networkErrorView != null) {
networkErrorView.setVisibility(View.VISIBLE);
return;
}
ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
networkErrorView = stub.inflate();
Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);
Button refresh = (Button)findViewById(R.id.network_refresh);
}
private void showNormal() {
if (networkErrorView != null) {
networkErrorView.setVisibility(View.GONE);
}
}
在上面showNetError()中展开了ViewStub。同一时候我们对networkErrorView进行了保存,这样下次不用继续inflate。
这就是后面第三部分提到的降低不必要的infalte。
viewstub标签大部分属性同include标签相似。
上面展开ViewStub部分代码
Java
ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
networkErrorView = stub.inflate();
也能够写成以下的形式
View viewStub = findViewById(R.id.network_error_layout);
viewStub.setVisibility(View.VISIBLE); // ViewStub被展开后的布局所替换
networkErrorView = findViewById(R.id.network_error_layout); // 获取展开后的布局
效果一致,仅仅是不用显示的转换为ViewStub。
通过viewstub的原理我们能够知道将一个view设置为GONE不会被解析,从而提高layout解析速度。而VISIBLE和INVISIBLE这两个可见性属性会被正常解析。
(3) 标签
在使用了include后可能导致布局嵌套过多,多余不必要的layout节点,从而导致解析变慢。不必要的节点和嵌套可通过hierarchy viewer(以下布局调优工具中有详细介绍)或设置->开发人员选项->显示布局边界查看。
merge标签可用于两种典型情况:
a. 布局顶结点是FrameLayout且不须要设置background或padding等属性。能够用merge取代。由于Activity内容试图的parent view就是个FrameLayout。所以能够用merge消除仅仅剩一个。
b. 某布局作为子布局被其它布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自己主动被忽略。而将其子节点所有合并到主布局中。
以(1) 标签的演示样例为例,用hierarchy viewer查看main.xml布局例如以下图:
android include
能够发现多了一层不是必需的RelativeLayout,将foot.xml中RelativeLayout改为merge,例如以下:
Java
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_above="@+id/text"/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_alignParentBottom="true"
android:text="@string/app_name" />
</merge>
执行后再次用hierarchy viewer查看main.xml布局例如以下图:
android include2
这样就不会有多余的RelativeLayout节点了。
2、去除不必要的嵌套和View节点
(1) 首次不须要使用的节点设置为GONE或使用viewstub
(2) 使用RelativeLayout取代LinearLayout
大约在Android4.0之前。新建project的默认main.xml中顶节点是LinearLayout,而在之后已经改为RelativeLayout。由于RelativeLayout性能更优。且能够简单实现LinearLayout嵌套才干实现的布局。
4.0及以上Android版本号可通过设置->开发人员选项->显示布局边界打开页面布局显示,看看是否有不必要的节点和嵌套。
4.0以下版本号可通过hierarchy viewer查看。
3、降低不必要的infalte
(1) 对于inflate的布局能够直接缓存,用所有变量取代局部变量,避免下次需再次inflate
如上面ViewStub演示样例中的
Java
if (networkErrorView != null) {
networkErrorView.setVisibility(View.VISIBLE);
return;
}
(2) ListView提供了item缓存,adapter getView的标准写法,例如以下:
Java
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
……
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
}
/**
* ViewHolder
*
* @author trinea@trinea.cn 2013-08-01
*/
private static class ViewHolder {
ImageView appIcon;
TextView appName;
TextView appInfo;
}
关于ListView缓存原理可见Android ListView缓存机制。
4、其它点
(1) 用SurfaceView或TextureView取代普通View
SurfaceView或TextureView能够通过将画图操作移动到还有一个单独线程上提高性能。
普通View的绘制过程都是在主线程(UI线程)中完毕。假设某些画图操作影响性能就不好优化了,这时我们能够考虑使用SurfaceView和TextureView。他们的画图操作发生在UI线程之外的还有一个线程上。
由于SurfaceView在常规视图系统之外,所以无法像常规试图一样移动、缩放或旋转一个SurfaceView。
TextureView是Android4.0引入的,除了与SurfaceView一样在单独线程绘制外。还能够像常规视图一样被改变。
(2) 使用RenderJavascript
RenderScript是Adnroid3.0引进的用来在Android上写高性能代码的一种语言,语法给予C语言的C99标准。他的结构是独立的,所以不须要为不同的CPU或者GPU定制代码代码。
(3) 使用OpenGL画图
Android支持使用OpenGL API的高性能画图。这是Android可用的最高级的画图机制,在游戏类对性能要求较高的应用中得到广泛使用。
Android 4.3最大的改变,就是支持OpenGL ES 3.0。
相比2.0,3.0有很多其它的缓冲区对象、添加了新的着色语言、添加多纹理支持等等,将为Android游戏带来更出色的视觉体验。
(4) 尽量为所有分辨率创建资源
降低不必要的硬件缩放。这会降低UI的绘制速度,可借助Android asset studio
5、布局调优工具
(1) hierarchy viewer
hierarchy viewer能够方便的查看Activity的布局,各个View的属性、measure、layout、draw的时间,假设耗时较多会用红色标记,否则显示绿色。
hierarchy viewer.bat位于/tools/文件夹下。使用可见:Using Hierarchy Viewer , 演示样例图例如以下:
android hierarechy viewer
(2) layoutopt
layoutopt是一个能够提供layout及其层级优化提示的命令行,在sdk16以后已经被lint取代,在Windows->Show View->Other->Android->Lint Warnings查看lint优化提示,lint详细介绍可见Improving Your Code with lint。
Android性能优化之中的一个 布局优化的更多相关文章
- Android多线程分析之中的一个:使用Thread异步下载图像
Android多线程分析之中的一个:使用Thread异步下载图像 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可.转载请注明出处 打算整理一下对 Android Fr ...
- Android绘制优化(二)布局优化
前言 我们知道一个界面的测量和绘制是通过递归来完成的,减少布局的层数就会减少测量和绘制的时间,从而性能就会得到提升.当然这只是布局优化的一方面,那么如何来进行布局的分析和优化呢?本篇文章会给你一个满意 ...
- Android动画三部曲之中的一个 View Animation & LayoutAnimation
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/50612827 本篇文章对android的Tween动画和帧动画以及布局动画进行总结. ...
- Android性能优化之布局优化
最新最准确内容建议直接访问原文:Android性能优化之布局优化 本文为Android性能优化的第二篇——布局优化,主要介绍使用抽象布局标签(include, viewstub, merge).去除不 ...
- Android Studido下的应用性能优化总结--布局优化
前言:一个应用的成功=产品设计*性能 ,再此我们不讨论一个应用的设计,那交给我们可爱又可恨的产品经理和UI设计师来决定!所以这里分步骤讨论如何提升一个应用的性能,这里先探讨布局优化问题. 布局优化 避 ...
- Android的布局优化之include、merge 、viewstub
以前在写布局的时候总是喜欢用自己熟悉的方式去写,从来也没有想过优化怎么的,后来又一次在上班的时候老大拿着我写的一个页面说我这个不行.我说这不是和设计图上的一模一样的么?怎么就不行了?然后他就跟我说了一 ...
- Android最佳性能实践(四)——布局优化技巧
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43376527 在前面几篇文章其中.我们学习了怎样通过合理管理内存,以及高性能编码技 ...
- Android 性能优化总结
App 流畅运行,是用户体验的第一步.App 流程运行,涉及到性能优化,主要涉及到布局优化, 绘制优化,内存泄漏优化,响应速度优化,列表展示优化,Bitmap 优化,线程优化,包大小优化. 布局优化 ...
- Andorid之页面布局优化
文章大纲 一.为什么要进行页面布局优化二.页面布局优化实操三.项目源码下载四.参考文章 一.为什么要进行页面布局优化 在开发Android时,会遇到某些是通用的布局,我们常将一些通用的视图提取到一 ...
随机推荐
- BZOJ 4820 [Sdoi2017]硬币游戏 ——期望DP 高斯消元
做法太神了,理解不了. 自己想到的是建出AC自动机然后建出矩阵然后求逆计算,感觉可以过$40%$ 用一个状态$N$表示任意一个位置没有匹配成功的概率和. 每种匹配不成功的情况都是等价的. 然后我们强制 ...
- [图论训练]BZOJ 2118: 墨墨的等式 【最短路】
Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在 ...
- input和textarea区别
1. input是单行文本,textarea是多行文本,可以带滚动条2. input的value放在标签里面 <input type="text" value="b ...
- 刷题总结——棘手的操作(bzoj2333)
题目: 题目背景 SCOI2011 DAY2 T1 题目描述 有 N 个节点,标号从 1 到 N ,这 N 个节点一开始相互不连通.第i个节点的初始权值为 a[i] ,接下来有如下一些操作:U x y ...
- linux监控平台搭建-内存
linux监控平台搭建-内存 上一篇文章说的硬盘.就写一下.更加重要的东西.在手机上面是RAM.机器是memory.内存是按照字节编址.每个地址的存储单元可以存放8bit的数据.cpu 通过内存地址获 ...
- COGS728. [网络流24题] 最小路径覆盖问题
算法实现题8-3 最小路径覆盖问题(习题8-13) ´问题描述: 给定有向图G=(V,E).设P是G的一个简单路(顶点不相交)的集合.如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖.P中 ...
- BZOJ 4077 Messenger
Messenger [问题描述] alice和bob各自在两条折线上行进,一个邮递员要从alice那拿一个包裹,并以直线移动到bob处,alice和bob.邮递员的速度均为1单位/s,问邮递员最少要走 ...
- 變更 cut-off,termination current,截止電流 對 battery capacity 的影響
依之前的經驗 2700mAh 電池 cut-off 由 128 降至 64 mA,充電時間延長 20 分鐘, (128 + 64)/2 = 96 取平均充電流, 96 * (20/60) = 32 m ...
- HRBUST 2078:糖果(模拟,贪心)
题不难,但作为一道恶心到了我的题,我还是记录一下的好. 题意:n个人围一圈,要求:相邻两人,分数高的要比分数低的得到更多的糖果,若分数相同则必须得到相同数量的糖果.问满足要求的最少需要分配的糖果数.( ...
- mysql 新增用户并授权
grant all privileges on *.* to 'root'@‘%’ identified by '123456'; *.* 表示所有资源. 刷新权限 flush privileges;