Handler或Runnable作为非静态内部类,引发的内存泄露问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36707431/article/details/78616900

       一、Handler 和 Runnable 都有定时器的功能,当它们作为非静态内部类的时候,同样会持有外部类的引用,如果它们的内部有延迟操作,在延迟操作还没有发生的时候,销毁了外部类,那么外部类对象无法回收,从而造成内存泄漏。

     假设MianActivity里面有个Handler的10秒延时操作:

     Handler 和 Runnable 作为匿名内部类,都会持有 MainActivity 的引用,而它们内部有一个 10 秒钟的定时器,如果在打开 MainActivity 的 10 秒内关闭了 MainActivity,那么由于 Handler 和 Runnable 的生命周期比 MainActivity 长,会导致 MainActivity 无法被回收,从而造成内存泄漏。

     二、应该如何避免内存泄漏呢?

     一般套路就是把 Handler 和 Runnable 定义为静态内部类,这样它们就不再持有 MainActivity 的引用了,从而避免了内存泄漏:

public class MainActivity extends AppCompatActivity {  
    private static final String TAG = "MainActivity";  
private Handler handler; private Runnable runnable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handler = new TestHandler(); runnable = new TestRunnable(); handler.postDelayed(runnable, 10 * 1000); } private static class TestHandler extends Handler { } private static class TestRunnable implements Runnable { @Override public void run() { Log.d(TAG, "run: "); } } }
 
 
@Override  
protected void onDestroy() {  
    super.onDestroy();  
    handler.removeCallbacks(runnable);  
}
       还有一种特殊情况,如果 Handler 或者 Runnable 中持有 Context 对象,那么即使使用静态内部类,还是会发生内存泄漏,这种情况可以使用弱引用的方式来引用 Context 来避免内存泄漏

public class MainActivity extends AppCompatActivity { 
    private static final String TAG = "MainActivity"; 
    private Handler handler; 
    private Runnable runnable; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 

        handler = new TestHandler(new WeakReference<Context>(this)); 
        runnable = new TestRunnable(); 
        handler.postDelayed(runnable, 10 * 1000); 
    } 

    private static class TestHandler extends Handler { 
        private Context context; 
        private TestHandler(WeakReference<Context> weakContext) { 
            context = weakContext.get(); 
        } 
    } 

    private static class TestRunnable implements Runnable { 
        @Override 
        public void run() { 
            Log.d(TAG, "run: "); 
        } 
    } 

   
} 





猜你喜欢

转载自blog.csdn.net/qq_36707431/article/details/78616900
今日推荐