Android在旋转设备上管理多个请求rxJava

时间:2017-03-19 14:47:14

标签: android rx-java rx-android

我在Android应用程序上使用MVVM,我想在设备轮换时管理请求和rxJava,如何在旋转设备后禁用请求并从上次请求中计数?

这是我的简单代码,知道我该怎么做,但我找不到任何关于它的文档和示例代码

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = DataBindingUtil.setContentView(this, R.layout.activity_register);
    ...
    Observer<String> myObserver = new Observer<String>() {
        @Override
        public void onError(Throwable e) {
            // Called when the observable encounters an error
        }

        @Override
        public void onComplete() {

        }

        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(String s) {
            // Called each time the observable emits data
            Log.e("MY OBSERVER", s);
        }
    };

    Observable.just("Hello").subscribe(myObserver);
}

我使用的是最新版本的rxJava

5 个答案:

答案 0 :(得分:2)

在Android中处理轮换是一个很酷的挑战。有几种方法可以做到这一点。

1-服务:您可以使用服务并处理网络请求或其他后台服务。通过服务,您可以从ui中分离您的业务逻辑。

2-工作人员片段:工作人员片段是没有布局的片段实例。您应该将工作人员片段的retainInstanceState设置为true。因此,您可以根据方向更改保存您的片段,并且不会丢失您的后台操作。

为什么工人碎片?如果将retainInstanceState设置为带有布局的片段,则会泄漏视图。

如果您正在使用MVVM,则可以将ViewModel实现为工作人员片段,其中setRetainInstanceState = true

3-全局单例数据源:您可以创建一个全局单例数据源类,用于处理应用程序中活动/片段生命周期的独立范围内的操作。

4-加载程序:加载程序可以从方向更改中恢复状态。您使用加载器处理操作,但它们旨在从磁盘加载数据,不适合长时间运行的网络请求。

额外:您可以使用Path's Priority Job Queue来保留您的工作: https://github.com/path/android-priority-jobqueue

修改:您可以在不使用Google的新架构组件的情况下检查我的仓库以处理设备轮换。 (作为我在答案中指出的Worker Fragment的一个例子。) https://github.com/savepopulation/bulk-action

答案 1 :(得分:1)

您有以下选择:

  • 使用一些全局Singleton或您的Application类来保存您的逻辑,而不是在Activity的生命周期内
  • 使用在您的活动/应用程序旁边运行的服务
  • 使用装载机

全局状态通常很糟糕,使您的代码难以测试/调试。服务往往过度。

对于您使用设备轮换的情况,并继续使用,您通常会使用a Loader,它一直在轮换中运行,只有在您离开活动后才会被销毁。

我最近还撰写了一篇文章,介绍use Loaders together with RxJava在方向更改期间保持状态的一种可能解决方案。

答案 2 :(得分:0)

您可以利用Fragment #setRetainInstance(true)。设置该标志后,片段在设备旋转后不会被销毁,并且可以用作对象容器。请查看此示例,该示例还存储了Observable - https://github.com/krpiotrek/RetainFragmentSample

答案 3 :(得分:0)

你需要覆盖

@Override
public void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
}

当设备被旋转时,将数据存储在bundle中,然后在create check

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if(savedInstanceState == null){
   //saved instance is null
}else{
    //get your stored values here
    counter = savedInstanceState.getInt("value",0); //here zero is the default value
 }
}

答案 4 :(得分:0)

我这样做是为了拥有一个单例类(或者之前的 savepopulation 所解释的任何长生命对象,但是 - 诀窍是将加载的数据存储在BehaviorSubject中,并在活动中订阅该主题,而不是原始网络请求。

这样:

public class MyNetworkSingleton {
  // This static service survives orientation changes
  public static MyNetworkSingleton INSTANCE = new MyNetworkSingleton();

  private final BehaviorSubject<String> dataSubject = BehaviorSubject.create();

  public Observable<String> getData() {
     if (!dataSubject.hasValue()) {
        refreshData(); // No data is loaded yet, load initial data from network
     }

     return dataSubject;
  }

  public void refreshData() {
     someDataSourceCall().subscribe(new Observer<String>() {
       @Override
       public void onError(Throwable e) {
           // Remember, this point also needs error handling of some form,
           // e.g. propagating the error to the UI as a Toast
       }

       @Override
       public void onComplete() {

       }

       @Override
       public void onSubscribe(Disposable d) {

       }

       @Override
       public void onNext(String data) {
          dataSubject.onNext(data); // this refreshes the internally stored data
       }
     });
  }

  private Observable<String> someDataSourceCall() {
     return // some network request here etc. where you get your data from
  }
}

然后:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    Observer<String> myObserver = new Observer<String>() {
        @Override
        public void onError(Throwable e) {
            // Called when the observable encounters an error
        }

        @Override
        public void onComplete() {

        }

        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(String s) {
            // Called each time the observable emits data
            Log.e("MY OBSERVER", s);
        }
    };

    MyNetworkSingleton.INSTANCE.getData().subscribe(myObserver);

    myRefreshButton.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {
            // refresh data from network only when button is pressed
            MyNetworkSingleton.INSTANCE.refreshData();
        }
    });
}

这种方式只有在您第一次需要来自网络的数据时才会加载,或者当用户点击刷新按钮(myRefreshButton)时。