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

时间:2016-12-21 16:05:30

标签: android rx-java observable rx-android subscriptions

早上好,我最近在和RxJava一起玩,我遇到了一个问题。

我在 ViewPager 中有一个片段,它在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()的片段中,我检查结果是否在那里,如果没有我们调用上面的方法,如果有我们很高兴作为一个蛤蜊​​。

问题是指当我旋转设备时,第一个&#34;订阅尚未返回,因此片段不会记住数据,它会启动另一个搜索,如果我继续旋转,我会继续添加订阅

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

逐步期望的行为:

  • 启动片段并请求
  • 屏幕显示正在启动订阅/请求的加载图片和背景
  • 自第一个请求仍未决时,多个屏幕旋转保持加载图像
  • 第一次调用的结果返回后,将其返回到片段,从而隐藏加载图像并显示结果

非常感谢

1 个答案:

答案 0 :(得分:2)

关于Fragments和RxJava的不幸之处在于你必须以某种方式保持可观察性。一种方法是将它们设置为Fragment的静态,以便您只创建一次,然后在onStart() / onStop()中订阅/取消订阅,或者您自己决定。

如果您不喜欢制作静态变量,那么另一种方法是使用保留的Fragment来处理数据。然后,数据的Fragment视图可以将自身“绑定”到数据片段。这种方法的优点是,数据可以轻松地用于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可以在不妨碍下载的情况下消失并重新出现。以您需要的方式操纵Observable更容易。