【问题标题】:Android manage multi request rxJava on rotation deviceAndroid 在旋转设备上管理多请求 rxJava
【发布时间】:2017-03-19 14:47:14
【问题描述】:

我在 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

【问题讨论】:

    标签: android rx-java rx-android


    【解决方案1】:

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

    1- 服务:您可以使用服务并在服务中处理您的网络请求或其他后台操作。同样使用服务,您可以将业务逻辑与 ui 分开。

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

    为什么要使用 Worker Fragment?如果您将 retainInstanceState 设置为具有布局的片段,则会泄漏视图。

    如果您使用 MVVM,您可以将 ViewModel 实现为 Worker Fragment,即 setRetainInstanceState = true

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

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

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

    编辑:您可以查看我的存储库以处理设备旋转,而无需使用 Google 的新架构组件。 (作为我在回答中指出的Worker Fragment 的一个例子。) https://github.com/savepopulation/bulk-action

    【讨论】:

    • 从服务器请求而不点击任何按钮发出多个请求,因为在旋转设备上我们没有任何处理,你能帮我从Loaders 的方向变化中恢复状态吗?示例代码知道如何我能做到吗?
    • 我想补充一点,选择第三个选项时,全局单例不是必需的。数据源实例也可以通过依赖注入传递。
    • 这不能回答问题。它明确说明了在旋转设备/再次订阅可观察对象时如何不重新触发请求。
    【解决方案2】:

    您有以下选择:

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

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

    对于您的设备轮换用例并从中断处继续,您通常会使用a Loader,它会继续轮换运行,并且只有在您离开活动时才会被销毁。

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

    【讨论】:

    • 谢谢先生,请让我检查您的帖子并尝试使用加载器
    • 如何在这部分代码Observable.Transformer 上导入Transformer
    【解决方案3】:

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

    【讨论】:

    • 那是活动不是片段
    • 这不会改变任何东西 - 你只是使用片段作为容器。查看示例 - 它适用于 Activity,就像您的案例一样
    • 问题是我没有任何片段先生,我不想使用片段来解决更困难的问题或解决这个问题
    【解决方案4】:

    你需要重写

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

    当设备旋转时,将数据存储在包中,然后在内部创建检查

    @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
     }
    }
    

    【讨论】:

    • 如何从服务器请求并放置状态直到手机轮换得到响应?
    • 你可以添加布尔值到 bundle isLoading 并在 oncreate 中检查
    【解决方案5】:

    我这样做的方法是拥有一个单例类(或任何长期存在的对象,如 savepopulation 前面所述,但是 - 诀窍是将加载的数据存储在 BehaviorSubject 中,然后订阅到 Activity 中的那个主题,而不是原来的网络请求。

    这边:

    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) 时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多