Android性能优化方案
布局优化
尽量减少layout层级,减少界面绘制的工作量。
采用,标签
自定义View的绘制
onDraw中不要创建大量的局部对象。因为onDraw方法会被频繁调用,这样就会在一瞬间产生大量的临时对象,不仅会占用过多内存还会导致系统频繁GC,降低程序执行效率。
onDraw中不要做太多耗时才操作。
内存优化
静态变量导致的内存泄露
示例:一个外部的静态Context变量引用了当前的Activity实例,当Activity销毁的时候无法被销毁。或者一个Activity的一个静态Context变量,引用了当前Activity,销毁之前没有释放,导致Activity无法被销毁。
解决方法:不要将Activty作为Context传给外部Context变量。如果外部需要传入Context,可以使用Application Context,因为Application Context的生命周期与APP的生命周期一致。如果Activity内部有静态Context变量持有当前Activity实例,在onDestroy的时候要将该变量持有Activity释放。单例模式导致的内存泄露
示例:单例模式内部的Context变量持有外部存入的Activity实例,在Activity销毁之前没有释放操作,导致Activity无法被销毁,内存无法回收。
解决办法:如果单例模式需要Context的时候,可以通过调用Context.getApplicationContext()方法或者Activity.getApplication()方法来传入Application对象。或者直接在Application 创建的时候,即onCreate的时候传入Application Context。属性动画导致的内存泄露
示例:属性动画中有一类无限循环的动画,如果在Activity播放了此类动画并且没有在onDestroy中去停止动画,那么动画会一直播放下去,并且这个时候Activity的View会被动画持有,而View又持有了Activity,最终导致Activity无法释放。
解决办法:在Activity的onDrstroy中调用animator.cancel()来停止动画。自定义Handler导致的内存泄露
示例:如果我们在Activity中定义一个非静态的Handler内部类,这样这个内部类就默认持有了当前Activity实例的引用。Handler常常伴随着一个执行耗时操作的异步线程(如下载多张图片),如果在完成耗时操作之前,Activity退出,异步线程持有handler的引用,handler持有Activity的引用,Activity的实例无法被销毁,从而导致内存泄漏
解决办法:用一个静态的内部类的来代替,同时Weakference的方式传入外部Activity的引用。同时在Activity的onDestroy方法里面调用mHandler.removeCallbacksAndMessages(null);移除该Handler相关的消息队列中所有消息和所有的Runnable。
代码示例:
private MyHandler mHandler = new MyHandler(this);
private static class MyHandler extends Handler {
WeakReference<MainActivity> weakReference;
public MyHandler(MainActivity activity) {
weakReference = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
- AsyncTask导致的内存泄露
原因和Handler内存泄露原因相似,解决办法也一样,采用静态内部类的方式。
事例:
private MyAsyncTask asyncTask;
private static class MyAsyncTask extends AsyncTask<Void, Integer, String>{
public final WeakReference<MyActivity> weakReference;
public MyAsyncTask(MyActivity activity){
weakReference = new WeakReference<MyActivity>(activity);
}
@Override
protected String doInBackground(Void... params) {
//该方法中最好不要做一些不可中断的操作,否则的话。AsyncTask在cancel的时候是无法被停掉的。
//例如,BitmapFactory.decodeFile(...)等
return null;
}
@SuppressLint("NewApi")
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
MyActivity myActivity = weakReference.get();
if (myActivity.isFinishing() || myActivity.isDestroyed()) {
//满足条件说明Activity正在销毁,此时不应该和UI进行交互。因为此时的Activity正在被销毁
return;
}else{
//通过软应该拿到的外部activity的引用和UI交互
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//在onDestroy做如下判断,如果activity正在被销毁,则取消asynctask
if (asyncTask!=null && !asyncTask.isCancelled()) {
asyncTask.cancel(true);
}
}
- 4.其他
Bitmap对象使用完后,忘记了调用recycle()方法销毁;