非静态内部类: 成员内部类, 局部内部类、 匿名内部类。 会有对外部类的引用。这样内部类中耗时操作在用户频繁退出重启APP相关Activity时很容易导致内存泄漏。
一、匿名内部类:Runnable
1、泄漏版
new Thread(new Runnable() { @Override public void run() { try { //模拟耗时操作 Thread.sleep(15000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start();
连续多次退出重启后发现:
2、优化版:
将 非静态内部类 改为 静态非匿名内部类
new Thread(new MyRunnable()).start(); private static class MyRunnable implements Runnable { @Override public void run() { try { Thread.sleep(15000); } catch (InterruptedException e) { e.printStackTrace(); } } }
二、成员内部类:Handler
1、泄漏版:
private final static int MESSAGECODE = 1; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.d("mmmmmmmm", "handler " + msg.what); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { handler.sendEmptyMessage(MESSAGECODE); try { Thread.sleep(8000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(MESSAGECODE); } }).start(); }
连续多次退出重启后发现:
2、优化版:
2.1、使用静态内部类
2.2、使用弱引用
2.3、在onDestroy() 里面取消异步任务。(注意:单纯的取消还是会内存泄漏)
private final static int MESSAGECODE = 1; private static Handler handler;//静态 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建Handler handler = new MyHandler(this); //创建线程并且启动线程 new Thread(new MyRunnable()).start(); } //1、避免Handler引用activity造成的内存泄漏:使用静态内部类+ 使用弱引用 private static class MyHandler extends Handler { WeakReference<HandlerActivity> weakReference; public MyHandler(HandlerActivity activity) { weakReference = new WeakReference<HandlerActivity>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (weakReference.get() != null) { // update android ui Log.d("mmmmmmmm", "handler " + msg.what); } } } //2、避免非静态Runnable内部类引用activity造成的内存泄漏 private static class MyRunnable implements Runnable { @Override public void run() { handler.sendEmptyMessage(MESSAGECODE); try { Thread.sleep(8000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(MESSAGECODE); } } @Override protected void onDestroy() { super.onDestroy(); //3、如果参数为null的话,会将所有的Callbacks和Messages全部清除掉。 handler.removeCallbacksAndMessages(null); }
三、匿名内部类:TimerTask
1、泄漏版:
new Timer().schedule(new TimerTask() { @Override public void run() { while (true) ; } }, 1000); // 1秒后启动一个任务
连续多次退出重启后发现:
2、优化版:
1、在适当的时机进行Cancel。
2、TimerTask用静态内部类
private TimerTask timerTask ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); timerTask = new MyTimerTask() ; new Timer().schedule( timerTask ,1000 ); // 1秒后启动一个任务 } private static class MyTimerTask extends TimerTask { @Override public void run() { while(true){ Log.d( "ttttttttt" , "timerTask" ) ; } } } @Override protected void onDestroy() { super.onDestroy(); //取消定时任务 if ( timerTask != null ){ timerTask.cancel() ; } }
四、匿名内部类:AsyncTask
1、泄露版:
new AsyncTask<String,Integer,String>(){ @Override protected String doInBackground(String... params) { try { Thread.sleep( 6000 ); } catch (InterruptedException e) { } return "ssss"; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); Log.d( "mmmmmm activity2 " , "" + s ) ; } }.execute();
连续多次退出重启后发现:
2、优化版
1、自定义静态AsyncTask类
2、AsyncTask的周期和Activity周期应该保持一致。也就是在Activity生命周期结束时要将AsyncTask cancel掉。
private static MyTask myTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myTask = new MyTask(); myTask.execute(); } //1、创建静态内部类 private static class MyTask extends AsyncTask { @Override protected Object doInBackground(Object[] params) { try { //模拟耗时操作 Thread.sleep(15000); } catch (InterruptedException e) { e.printStackTrace(); } return ""; } } @Override protected void onDestroy() { super.onDestroy(); //2、取消异步任务 if (myTask != null) { myTask.cancel(true); } }