Android常见内存泄露优化总结

 

进行android总结,总结了一些自己写的以及常见的android内存泄露的优化,如有错误以及不全的地方请大家帮忙指正,谢谢!!!

1、Activity Fragment用了 static
例如:

public class MainActivity extends ActionBarActivity{
public static MainActivity mainActivity;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mainActivity=this;
  }
}

如此写了之后在其他的地方调用MainActivity.mainActivity...

只要有对象持有了这个mainActivity,MainActivity就不会被回收,里面的所有的数据包括View不会被回收,容易出现内存泄露
不同界面之间的数据传输用intnent等进行传递,该缓存的数据进行缓存,数据库,文件,sp都可以。

2、Activity Fragment用了 别的对象持有了该对象
例如MyManager.getInstance().addListener(this);
能用getApplicationContext()就用getApplicationContext();只能用这个对象的在onDestroy()的时候要清除持有的的该对象

3、Handler
1)、如果handler中new了很多重复的message,会存在内存泄露,可以调用handler.removeMessages(what);
在onDestroy()的时候的时候最好调用handler.removeMessages(what);
2)、

public class MainActivity extends Activity {
  //...
  Handler handler;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //...
    handler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
    }
  }
}


如果调用了handler.postDeslayed,如果delay的时间过长,此时Activity不会被回收,可以onDestroy()的时候handler.removeMessages(what);
还可以用下面的写法

private static class MyHandler extends Handler { 
private final WeakReference<MainActivity> mActivity; 
// ...
public MyHandler(MainActivity activity) {
  mActivity = new WeakReference<MainActivity>(activity);
  //... 
}
@Override
public void handleMessage(Message msg) { 
}
//...
}

 


WeakReference,也就是所谓的弱引用。垃圾回收器在回收的时候,是会忽视掉弱引用的,所以包含它的 Activity 会被正常清理掉

4、线程造成的内存泄露
对于线程造成的内存泄漏,也是平时比较常见的,下面的写法:

new AsyncTask<Void, Void, Void>() {
  @Override
  protected Void doInBackground(Void... params) {
    SystemClock.sleep(10000);
    return null;
  }
}.execute();

上面的异步任务是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成,
那么将导致Activity的内存资源无法回收,造成内存泄漏。正确的做法还是使用静态内部类的方式,如下

static class MyAsyncTask extends AsyncTask<Void, Void, Void> {
    private WeakReference<Context> weakReference;
    public MyAsyncTask(Context context) {
        weakReference = new WeakReference<>(context);
    }
    @Override
    protected Void doInBackground(Void... params) {
        SystemClock.sleep(10000);
        return null;
    }
    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        MainActivity activity = (MainActivity) weakReference.get();
        if (activity != null) {
        //...
        }
    }
}                

5、资源未关闭造成的内存泄漏
对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
BraodcastReceiver动态注册的需要unRegister(..)
Cursor需要close()
Stream也需要close()
Bitmap需要recyle()

6、Adapter每次new View,可以用下面的写法,ListView和GridView可以重复的利用View

public View getView(int position, View convertView, ViewGroup arg2) {

    ViewHolder vh = null;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.item_list, null);
        vh = new ViewHolder();
        vh.tv = (TextView) convertView.findViewById(R.id.tv);
        convertView.setTag(vh);
    } else {
        vh = (ViewHolder) convertView.getTag();
    }
    vh.tv.setText("");
    return convertView;
}

public static class ViewHolder {
    public TextView tv;
}

7、 移除掉所有的静态引用。
考虑用 EventBus 来解耦 Listener,在不需要的时候,解除 Listener 的绑定。
尽量用静态内部类。
做 Code Review。
用类似 MAT,Eclipse Analyzer,LeakCanary 这样的工具分析内存。
在 Callback 输出 Log。

posted @ 2015-12-12 18:10  逊志  阅读(594)  评论(0编辑  收藏  举报