Android/RxJava,防止同类多个订阅

Android/RxJava, prevent multiple subscriptions of the same kind

早上好,我最近忙于研究 RxJava,遇到了一个问题。

我在 ViewPager 中有一个 Fragment,它在 onViewCreated() 上启动一个 HTTP 请求(由 Retrofit 和 RxJava 处理)以检索字符串列表。 它的方法是 创建订阅 并将其添加到 CompositeSubscription 对象

这是代码

final Subscription subscription = MyManager.getService().getListStringsFromWeb()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<List<String>() {
                @Override
                public void onCompleted() {
                    // DO NOTHING
                }

                @Override
                public void onError(Throwable e) {
                    // DO SOMETHING
                }

                @Override
                public void onNext(List<String> result) {
                    returnResultToView(result);
                }
            });
addSubscription(subscription);

在 onViewCreated() 的片段中,我检查是否有结果,如果没有我们调用上面的方法,如果有我们很高兴。

问题 是当我旋转设备时 "first" 订阅尚未 return,因此片段不记得数据并且它会启动另一个搜索,如果我继续轮换,我会继续添加订阅

我想知道是否有办法保留第一个订阅,当它的结果到达时,只需将它返回给片段并忽略所有其他订阅

逐步实现所需的行为:

非常感谢

关于 Fragments 和 RxJava 的不幸的事情是你必须以某种方式保持 observable。一种方法是让它们在 Fragment 中静态化,这样你只创建一次,然后在 onStart()/onStop() 中创建它们 subscribe/unsubscribe 或者你决定。

如果您不喜欢制作静态变量,另一种方法是使用处理数据的保留片段。然后,数据的视图 Fragment 可以 "bind" 本身到数据片段。这种方法的优点是数据很容易被Activity的所有组件使用,它从视图中抽象出数据以便于测试,并且比生命周期组件长。

因此,对于保留的片段,您可以这样做:

public class DataFragment extends Fragment {

   private Observable<List<String> stringObs;

   @Override
   public void onAttach(Context ctx) {
      super.onAttach(ctx);
      setRetainInstance(true);
   }

   @Override
   public void onCreateView(LayoutInflater inflater, ViewGroup group, Bundle savedInsatnceState) {
      return null; // no view, no problem.
   }

   public Observable<List<String>> getStrings() {
     if (stringsObs == null) {
         stringsObs = MyManager.getService()
            .getListStringsFromWeb()
            .cache()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread());
     }
     return stringsObs;
   }
}

像这样将 DataFragment 添加到 FragmentManager 中:

FragmentManager fm = getFragmentManager();
DataFragment df = fm.findFragmentByTag("DataFragment");
if (df == null) {
   // Only add the retained fragment if it doesn't exist.  Otherwise, use the old one.
   fm.beginTransaction()
   .add(new DataFragment(), "DataFragment")
   .commit();
}

然后在 ViewFragment 上你可以像这样订阅它:

public class ViewFragment extends Fragment {

   private Subscription s;

   @Override
   public void onStart() {
     super.onStart();
     DataFragment dataFragment = (DataFragment) getFragmentManager().findFragmentByTag("DataFragment");
     s = dataFragment.getStrings()
            .subscribe(new Observer<List<String>() {
              // Do things
            });
   }

   @Override
   public void onStop() {
      super.onStop();
      s.unsubscribe();
   }
}

现在,您的 ViewFragment 可以随心所欲地消失和重新出现,而不会妨碍下载。以您需要的方式操作 Observables 也更容易。