Android - RxJava vs AsyncTask防止getActivity()内存泄漏

j2e*_*nue 6 android memory-leaks android-asynctask rx-java

如何在Android中使用RxJava(或RxAndroid等)代替AsyncTask有助于防止上下文泄漏?在AsyncTask中,如果您执行它并且用户离开应用程序,那么活动上下文可以为null并且应用程序可能会崩溃.我听说RxJava可以在进行线程时帮助防止这种类型的崩溃.我还听说它可以做更好的错误处理,然后是AsyncTask的doInBackground方法(它会严重处理错误).大多数时候我只是在doInBackground中返回null(例如),如果有任何失败,但我已经读过RxJava可以返回确切的错误而不是泄漏.谁能举个例子?

这是一个AsyncTask崩溃的小演示,如果用户在尝试向UI报告结果时离开应用程序:

     @SuppressWarnings("unused")
private class GetTask extends AsyncTask<Void, Void, Void> {         

    @Override
    protected void onPostExecute(String result) {         
        pd = new ProgressDialog(getActivity().getApplicationContext());//can crash right here
        pd.setTitle("Grabbing Track!");
        pd.setMessage("Please wait...");
        pd.setCancelable(false);
        pd.setIndeterminate(true);
        pd.show();
    }}
Run Code Online (Sandbox Code Playgroud)

这是一个doInBackground方法调用,它不会发出有用的错误:

@Override 
protected String doInBackground(String... params) {
    String myIntAsString = 1/0 + ""; //this should give an error (how do we report it to the caller??
                                  //or if we are parsing json and it fails, how do we report it to the caller cleanly. Can RxJava help?
}
Run Code Online (Sandbox Code Playgroud)

j2e*_*nue 9

我认为关于RxJava的好处是,如果你有一堆任务,你可以将它们按顺序排列,这样你就知道什么时候完成而下一个即将开始.在AsyncTask中如果你有多个运行,你不能保证哪个任务将首先完成,然后你必须做很多错误检查,如果你关心订单.所以RxJava允许你对调用进行排序.

关于内存泄漏,我们可以将AsyncTask作为活动的内部类.现在,因为当活动被破坏时它与活动相关联,上下文仍然悬而未开,并且不会被垃圾收集,这就是内存泄漏部分.

这是RxJava可以提供帮助的地方.如果发生任何错误,那么我们可以调用订阅者onError方法.订阅者可能如下所示:

    public Observable<JsonObject> get_A_NetworkCall() {
    // Do your network call...but return an observable when done
}

Subscription subscription = get_A_NetworkCall()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<jsonResponse>() {

        @Override
        public void onCompleted() {
             // Update UI
        }

        @Override
        public void onError() {
             // show error on UI
        }

        @Override
        public void onNext(JsonObject response) {
             // Handle result of jsonResponse 
        }
});
Run Code Online (Sandbox Code Playgroud)

或类似的东西 - 这是伪造的.关键是你可以更干净地报告错误并在一行中切换线程.在这里,我们报告了机器人主线程,但是在新线程上工作.在我们的活动onDestroy方法完成之后,我们可以简单地取消订阅observable并将其杀死并防止我们遇到的任何内存泄漏与AsyncTask.这对我来说应该是任何asyncTasks的替代品.


lop*_*par 5

我使用了两件事的组合.首先,RxAndroid真的很有帮助:https: //github.com/ReactiveX/RxAndroid

您可以使用AppObservable.bindActivity它来绑定一个observable,以便在主线程上观察其输出,如果活动被安排销毁,则不会转发消息.您仍然需要管理暂停/恢复生命周期.为此,我使用这样的复合订阅(pseudojava即将发布):

public class MyActivity extends Activity {
  private final CompositeSubscription subscriptions = new CompositeSubscription();

  @Override
  public void onResume() {
    super.onResume();
    subscriptions.add(AppObservable.bindActivity(this, myObservable)
        .subscribe());
    subscriptions.add(AppObservable.bindActivity(this, myOtherObservable)
        .subscribe());
  }

  @Override
  public void onPause() {
    subscriptions.clear();
    super.onPause();
  }

}
Run Code Online (Sandbox Code Playgroud)

显然,subscribe如果你想对数据做些什么,你会想做更多的事情,但重要的是收集返回的Subscription实例并将它们添加到CompositeSubscription.当它清除它们时,它也会取消订阅它们.

使用这些"两个奇怪的技巧"应该防止事件在不活动状态时回到活动状态.