我在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
答案 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)
您有以下选择:
全局状态通常很糟糕,使您的代码难以测试/调试。服务往往过度。
对于您使用设备轮换的情况,并继续使用,您通常会使用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
)时。