Android垃圾回收机制解决内存泄露问题

2019-12-10 19:11:05丽君

2、使用匿名内部类的时候经常出现的错误

错误方式:

 public class FooActivity extends Activity{

   private TextView textView;   



   private Handler handler = new Handler(){

    @override

    public void handlerMessage(Message msg){

     

    }

   };

   @override

   public void onCreate(Bundle bundle){

    super.onCreate(bundle);

    setContextView(R.layout.activity_foo_layout);

    

    textView = (TextView)findViewById(R.id.textView);

    

    handler.postDelayed(new Runnable(){

     @override

     public void run(){

       textView.setText(“ok”);

     };

    },1000 * 60 * 10);

   }

  }



错误原因:

     当我们执行了FooActivity的finish方法,被延迟的消息会在被处理之前存在于主线程消息队列中10分钟,而这个消息中又包含了Handler的引用,而Handler是一个匿名内部类的实例,其持有外面的FooActivity的引用,所以这导致了FooActivity无法回收,进而导致FooActivity持有的很多资源都无法回收,所以产生了内存泄露。

     注意上面的new Runnable这里也是匿名内部类实现的,同样也会持有FooActivity的引用,也会阻止FooActivity被回收。

     一个静态的匿名内部类实例不会持有外部类的引用。

正确方式:    

 public class FooActivity extends Activity{

   private TextView textView;

   

   private static class MyHandler extends Handler {

   private final WeakReference<FooActivity> mActivity;

   public MyHandler(FooActivity activity) {

    mActivity = new WeakReference<FooActivity>(activity);

   }

   @Override

   public void handleMessage(Message msg) {

    FooActivity activity = mActivity.get();

     if (activity != null) {

       // ...

     }

    }

   }

   private final MyHandler handler = new MyHandler(this);



   @override

   public void onCreate(Bundle bundle){

    super.onCreate(bundle);

    setContextView(R.layout.activity_foo_layout);

    

    textView = (TextView)findViewById(R.id.textView);

    

    handler.postDelayed(new MyRunnable(textView),1000 * 60 * 10);

   }



   private static class MyRunnable implements Runnable{

    private WeakReference<TextView> textViewWeakReference;

    

    public MyRunnable(TextView textView){

     textViewWeakReference = new WeakReference<TextView>(textView);

    }

     @override

     public void run(){

       final TextView textView = textViewWeakReference.get();

       if(textView != null){

        textView.setText("OK");

       }

     };

   }

  }