一、布局优化
布局优化就是删除布局中无用的控件和层级,可以用Hierarchy Viewer工具来检测,其次有选择地使用性能较低的ViewGroup。
- include标签
include标签只支持以android:layout开头的属性,比如android:layout_width;android:layout_height等,其他属性不支持,比如android:background.当然属性id还是支持的,如果include制定了这个id属性,同时被包含的布局文件也指定了id属性,那么以<include>指定的id属性为准,需要注意的是,如果include指定了android:layout_*这种属性,那么width,height必须存在,否则其他的android:layout形式的属性无法生效。
- merge标签
merge标签一般和include标签一起使用从而减少布局的层级,由于当前布局是一个竖直方向的Linearlayout,被包含的布局文件中的根布局也是Linearlayout,显然这个Linearlayout是多余的,通过merge标签就可以去掉多余的这一层。
- ViewStub
ViewStub继承了View,它非常轻量级且宽/高都是0,因此它本身不参与任何的布局和绘制过程。ViewStub的意义在于按需加载所需的布局文件,在使用的时候再加载,提高了程序初始化时的性能。例子如下:
<ViewStub
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
//用法一
((ViewStub)findViewById(R.id.tv)).setVisibility(View.VISIBLE);
//用法二
View view=((ViewStub)findViewById(R.id.tv)).inflate();
二、卡顿优化
1、绘制优化 onDraw
(1)首先,onDraw中不要创建新的局部对象,这是因为onDraw方法可能会被频繁调用,这样一瞬间产生大量的临时对象,不仅占用过多的内存而且还频繁GC,降低了程序的执行效率。
(2)在onDraw中不要做耗时的操作,也不能执行成千上万的循环操作。View的绘制帧率保证60fps是最佳的,这就要求每帧的绘制时间不超过16ms(16ms=1000/60)。
2、过度绘制 使用手机开发者模式GPU
3、事件冲突
4、处理数据,内存抖动
三、内存泄漏优化
- 1、静态变量导致的内存泄漏
public class MainActivity extends Activity{
private static Context sContext;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sContext=this;
}
}
- 单利模式导致的内存泄漏
(1)如果参数是context,不要用某个activity的context,使用application的context。
- 观察者模式类型的
只注册,未反注册
private List<DataListener> list=new ArrayList<>();
public void registerListener(DataListener listener){
list.add(listener);
}
public void unRegisterListner(DataListener listener){
list.remove(listener);
}
- 属性动画导致的内存泄漏
属性动画中的无线循环动画,如果没有在activity的ondestory()方法中去停止动画,尽管看不到动画效果,但是动画会一直播放下去,这时候动画持有了view,view只有了activity,最终activity无法释放,调用animator.cancel()来停止动画。
ObjectAnimatior animatior=ObjectAnimatior.ofFloat(mButton,"rotation",0,360).setDuration(2000);
animator.cancel();
- 数据库导致的内存泄漏
- 自定义view中获取自定义属性,没有释放recycle
- 非静态内部类导致的内存泄漏(handler)
- Bitmap未释放
- 强引用,弱引用,软应用,虚引用类型
- 点9图片
- webview
四、响应速度优化
响应速度优化的核心思想是避免在主线程中做耗时操作,如果在主线程中做耗时操作,activity启动时出现黑屏现象,甚至出现ANR,所以耗时操作在工作线程中完成。
(1)数据传递 序列化
(2)ANR Application Not Responding应用程序无响应
以下四个条件都可以造成ANR:
- InputDispatching Timeout 5s没无法响应屏幕触摸事件或键盘输入事件
- BroadcastQueue Timeout 在执行前台广播(BroadcastRrceiver)的onReceive()函数时10s没有处理完成,后台为60s
- Service Timeout 前台服务20s内,后台服务在200s内没有执行完毕
- ContentProvicer Timeout ContentProvider的publish在10s内没进行完
四、启动优化
1、分类
- 冷启动
现象: 点击app的icon,显示白屏或者黑屏
冷启动流程: 加载启动app-->app启动之后展示一个空白的window-->创建app进程-->创建app对象-->启动MainThread-->创建启动的activity对象-->加载view
解决办法:1、设置默认启动activity的主题里面windowback属性为透明
<style name="SplashTheme" parent="AppTheme">
<item name="android:windowBackground">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowDisablePreview">@null</item>
</style>
2、设置默认启动activity的主题里面windowback属性为默认图片
<style name="SplashTheme" parent="AppTheme">
<item name="android:windowBackground">@drawable/abc_vector_test</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowDisablePreview">@null</item>
</style>
3、上面的1,2方法只是治标,辅以下面方法
applicaiton的oncreate方法初始化各种sdk判断是否在当前进程
applicaiton的onCreate方法不做耗时操作
sdk的初始化如果可以最好延迟加载
- 热启动
最快,从后台到前台
- 温启动
2、启动时间测量方式
- adb命令(不严谨,线下使用方便,不能线上使用)
ThisTime:最后一个activity启动耗时
TotalTime:所有Activity启动耗时
WaitTime:AMS启动Activity的总耗时
- 手动打点(精确,可带到线上,进行统计)
public class SingleApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
//记录开始时间
}
//在activity中加载完xml,记录结束时间
(3)启动优化工具
两种工具互补
traceview
图形的形式展示执行时间,调用栈等,信息全面,包含所有线程
使用方式:
Debug.startMethodTracing("文件名")
Debug.stopMetodTracing();
生成文件在sd卡:Android/data/packagename/files/名字.trace
五、耗电优化
六、安装包大小优化
- res图片一套,删除无用的文件
- 代码混淆
七、线程优化
使用线程池