Android 弱引用使用示例

 结合静态内部类和WeakReference来解决Activity中可能存在的Handler内存泄露问题。

Activity中我们需要新建一个线程获取数据,使用handler - sendMessage方式。下面是这一过程的一般性代码:

 public class MainActivity extends Activity {

     //...
     private int page;
     private Handler handler = new Handler() {

         @Override
         public void handleMessage(Message msg) {
             if (msg.what == 1) {

                 //...

                 page++;
             } else {

                 //...

             }

         };
     };

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

         //...

         new Thread(new Runnable() {
             @Override
             public void run() {
                 //.. 
                 Message msg = Message.obtain();
                 msg.what = 1;
                 //msg.obj = xx;
                 handler.sendMessage(msg);
             }
         }).start();

         //...

     }

 }

在Eclispe中Run Link,将会看到警示信息:This Handler class should be static or leaks might occur …点击查看此信息,其详情中对问题进行了说明并给出了建议性的解决方案。

Issue: Ensures that Handler classes do not hold on to a reference to an outer class
Id: HandlerLeak

Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class;In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object.

大致的意思是建议将Handler定义成内部静态类,并在此静态内部类中定义一个WeakReference的引用,由于指示外部的Activity对象。

问题分析:

Activity具有自身的生命周期,Activity中新开启的线程运行过程中,可能此时用户按下了Back键,或系统内存不足等希望回收此Activity,由于Activity中新起的线程并不会遵循Activity本身的什么周期,也就是说,当Activity执行了onDestroy,由于线程以及Handler 的HandleMessage的存在,使得系统本希望进行此Activity内存回收不能实现,因为非静态内部类中隐性的持有对外部类的引用,导致可能存在的内存泄露问题。

因此,在Activity中使用Handler时,一方面需要将其定义为静态内部类形式,这样可以使其与外部类(Activity)解耦,不再持有外部类的引用,同时由于Handler中的handlerMessage一般都会多少需要访问或修改Activity的属性,此时,需要在Handler内部定义指向此Activity的WeakReference,使其不会影响到Activity的内存回收同时,可以在正常情况下访问到Activity的属性。

Google官方给出的建议写法为:



 public class MainActivity extends Activity {

     //...
     private int page;
     private MyHandler mMyHandler = new MyHandler(this);

     private static class MyHandler extends Handler {

         private WeakReference wrActivity;

         public MyHandler(MainActivity activity) {
             this.wrActivity = new WeakReference(activity);
         }

         @Override
         public void handleMessage(Message msg) {
             if (wrActivity.get() == null) {
                 return;
             }
             MainActivity mActivity = wrActivity.get();
             if (msg.what == 1) {

                 //...
                 mActivity.page++;

             } else {

                 //...

             }
         }

     }

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

         //...

         new Thread(new Runnable() {
             @Override
             public void run() {
                 //.. 
                 Message msg = Message.obtain();
                 msg.what = 1;
                 //msg.obj = xx;
                 mMyHandler.sendMessage(msg);
             }
         }).start();

         //...

     }

 }



 

你可能感兴趣的:(Android 弱引用使用示例)