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。