专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
stormzhang  ·  年底扣税变多了 ·  17 小时前  
鸿洋  ·  理解Android ... ·  2 天前  
鸿洋  ·  Android H5页面性能分析策略 ·  4 天前  
51好读  ›  专栏  ›  安卓开发精选

你并不一定要用弱引用来避免内存泄漏

安卓开发精选  · 公众号  · android  · 2016-12-20 21:48

正文

(点击上方公众号,可快速关注)

英文:medium.com

来源:泡在网上的日子    

链接:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/1213/6850.html


原文:You don’t have to use WeakReference to avoid memory leaks



我的一个同事最近提到他们看的一个演讲,其中讲到:


如果你是一个安卓开发者却不使用弱引用,那么你就有麻烦了。


我个人认为这不仅是一种错误观点,而且相当误导人。WeakReference(弱引用)应该是修复内存泄漏的最后手段。


然后今天,我看到了Enrique López Mañas发布在Google Developers Experts专栏的一篇文章。


Finally understanding how references work in Android and Java

A few weeks ago I attended Mobiconf, one of the best conferences for Mobile Developers I had the pleasure to attend in…medium.com


这是一篇总结Java引用的好文章。


这篇文章并没有说必须使用弱引用,但是也没有给出替代的方案。我觉得我必须给出其它的方法来阐明弱引用并不是必须使用。


如果你不使用弱引用并不会真的有什么问题


我认为处处使用弱引用并不是一种最佳实践。使用弱引用来修复内存泄漏的问题往往意味着缺乏合理的架构。


虽然文章中给出的例子修复了潜在的内存泄漏问题,但是也有其它的方法。我可以给出两个耗时后台任务中避免内存泄漏的例子。


避免AsyncTask内存泄漏的简单例子:


Activity:


public class MainActivity extends Activity {

  private MyAsyncTask task;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    task = new MyAsyncTask();

    task.setListener(createListener());

    task.execute();

  }

  @Override

  protected void onDestroy() {

    task.setListener(null);

    super.onDestroy();

  }

  private MyAsyncTask.Listener createListener() {

    return new MyAsyncTask.Listener() {

      @Override

      public void onSuccess(Object object) {

        // adapt contents

      }

    };

  }

}


这里是AsyncTask:


class MyAsyncTask extends AsyncTask {

  private Listener listener;

  @Override

  protected Object doInBackground(Object[] params) {

    return doSomeStuff();

  }

  private Object doSomeStuff() {

    //do something to get result

    return new Object();

  }

  @Override

  protected void onPostExecute(Object object) {

    if (listener != null) {

      listener.onSuccess(object);

    }

  }

  public void setListener(Listener listener) {

    this.listener = listener;

  }

  interface Listener {

    void onSuccess(Object object);

  }

}


当然这个例子非常基础,但是我认为作为另一种解决方案的演示来说足够了。


这里是另一个使用RxJava实现的简单例子,我们仍然没有使用弱引用。


public class MainActivity extends Activity {

  private Subscription subscription;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    subscription = Observable

        .fromCallable(new Callable() {

          @Override

          public Object call() throws Exception {

            return doSomeStuff();

          }

        })

        .subscribeOn(Schedulers.io())

        .observeOn(AndroidSchedulers.mainThread())

        .subscribe(new Action1() {

          @Override

          public void call(Object o) {

            // adapt contents

          }

        });

  }

  private Object doSomeStuff() {

    //do something to get result

    return new Object();

  }

  @Override

  protected void onDestroy() {

    subscription.unsubscribe();

    super.onDestroy();

  }

}


注意如果我们没有unsubscribe Subscription那么仍然可能会出现内存泄漏。


最后我给出两个Novoda的项目,它们是很好的学习资源。你可能猜到了,它们并没有使用任何弱引用:)。


novoda/bonfire-firebase-sample

bonfire-firebase-sample – An app to discuss your favourite emojis. This is a sample app built with Firebase.github.com


novoda/spikes

spikes – Where ideas & concepts are born & incubatedgithub.com


我认为一个很重要的守则是让内部类为静态的。尤其是它们要做耗时的后台任务的时候。或者更好的方法是把这个类移到外面作为单独的类。


用非静态的内部类做耗时的后台任务总是很糟糕的实践,不光是在安卓中。


关注「安卓开发精选
看更多精选安卓技术文章
↓↓↓