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)
我认为关于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的替代品.
我使用了两件事的组合.首先,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.当它清除它们时,它也会取消订阅它们.
使用这些"两个奇怪的技巧"应该防止事件在不活动状态时回到活动状态.