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

       一、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: "); 
        } 
    } 

   
} 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值