之前看过这样一篇文章对应用性能提示有很大帮助的一篇文章Android应用性能剖析全攻略
总结了几个提升ui流畅度的可优化点
1.远离主线程
主线程进行的很多耗时操作,过多的循环遍历,甚至轻微的逻辑,常见的像读缓存、sharedpreferences都会造成轻微的卡顿,严重的甚至ANR,sharedpreferences还是建议存放一些小数据的东西
2.布局过于复杂view的层次过多
布局的层次越多,渲染的速度越慢,能用一个控件可以搞定的千万不要用多个控件,少用LinearLayout,多用RelativeLayout,他能够多个方向进行排版,
常见的优化像Adapter,结构简单的话只需要一个控件就可以了,不需要外层再嵌套个layout
3.敏感方法里少做不相关的操作
比如onDraw, onMeasure, onLayout里面只做绘制方面的事情,如果要做需要handler发送消息去执行
4.避免频繁的addView和removeView
一般出现在实现动画的常见,使用这种方式来实现,这都会不断的触发measure/onMeasure,layout/onLayout和View的重绘。
View的层次越少,数量越少渲染越快,布局层面上的优化:
删除没有用的View
除去无必要的嵌套,比如当内部仅有一个View时,外面就没有必要再加一个ViewGroup了
多使用RelativeLayout。它能够随意的排版View,三维上的方位都可以搞定,所以对象像列表的Cell之类的,一个RelativeLayout基本上就可以搞定。
用TextView的drawable属性来组合图片+文字
用merge来减少层次
对于某些情况才用到的View,就使用ViewStub,然后在需要显示的时候再inflate。也就是所谓的延时和按需渲染
尽量不要用背景图片,特别整个Activity大小的背景,费内存,占资源
尽可能用矢量图形,比如颜色,drawable,shape,icon font等等
对于列表(List和Grid)优化除了上面提到的,还要注意使用组件传回来的convertView以及ViewHolder。convertView可以复用View对象,避免inflate过多的View。ViewHolder模式主要是减少findViewById的调用。
用StrictMode来检测主线程中所执行的耗时操作,这也是一大优化项,如下,可以在Activity入口加入,检测到并打印log,包含方法的耗时时间
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
// .penaltyDialog()//弹出违规提示对话框
// 这里可以替换为detectAll()就包括了磁盘读写和网络I / O
.penaltyLog()
//打印logcat,当然也可以定位到dropbox,通过文件保存相应的log
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
//探测SQLite数据库操作
.penaltyLog()
//打印logcat
.penaltyDeath()
.build());
布局调试工具hierarchyview
这个工具很明显就是用来调试布局的,它能以可视化的方式展示View的层次结构,顺带显示每一层View的渲染速度。运行方法是找到SDK/tools/运行hierarchyviewer.
注意:默认情况下只有调试的ROM(build with eng)或者用模拟器才能抓到View的层次信息(否则,应用的页面就很容易被破解了),对于可控制源码的可以用开源库来解决这个问题。
关于ViewServer,官方提供了一个ViewServer.java,需要接入到自己的应用中去,才能使用hierarchyview,使用的正确姿势:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (getIntent().getExtras() != null) mCounter = getIntent().getExtras().getInt("counter");
((TextView) findViewById(R.id.label)).setText("Activity #" + (mCounter + 1));
ViewServer.get(this).addWindow(this);
}
@Override
public void onDestroy() {
super.onDestroy();
ViewServer.get(this).removeWindow(this);
}
@Override
public void onResume() {
super.onResume();
ViewServer.get(this).setFocusedWindow(this);
}
针对这个工具,对自己的应用进行了优化
优化前的版本view的数量:131
优化前的版本view的数量:127
优化后的版本view的数量:105
优化经验:不经常显示的用ViewStub加载,多用merge来减少层次,把整个层次往前提,减少包裹,就能大幅度的提升流畅度和过度绘制