如何重新创建或重置缓存的 Observable,与 Retrofit 一起使用以获取新数据?
How to recreate or reset cached Observable, used with Retrofit to get new data?
我有:
API,即returns数据列表在JSON
.
我的目标:
通过Retrofit
+RxJava
获取此数据。
我的问题:
我只需要一个网络请求,如果屏幕在完成之前旋转,我不想开始新的请求。我还需要能够从 API.
刷新数据
我是怎么解决的:
首先通过 Singlton 解决并在 Observable
中使用 cache()
缓存数据。
其次 - 完全重新创建 Retrofit
对象 (1)、改造接口实例 (2) 和 Observable
(3) 本身。我尝试只做 3 次,但失败了 - Observable
未重置并发出旧的缓存数据。
问题:
我重新创建 Observable
的工作方式看起来很糟糕。重新创建缓存 Observable
的 proper/better 方法是什么?
有我的辛格顿get/recreate Observalbe
:
public class SingltonRetrofit
{
private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());
private static Gson gson = new GsonBuilder().create();
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxAdapter)
.build();
private static GetModels apiService = retrofit.create(GetModels.class);
private static Observable<ArrayList<Model>> observableModelsList;
public static void reset()
{
retrofit = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxAdapter)
.build();
apiService = retrofit.create(GetModels.class);
observableModelsList = null;
}
public static Observable<ArrayList<Model>> getModelsObservable()
{
if (observableModelsList == null)
{
observableModelsList = apiService.getModelsList().cache();
}
return observableModelsList;
}
}
P.S.
同样的俄语问题:Как правильно пересоздать закэшированный Observable используемый вместе с Retrofit?
最后我是这样解决的:
我在 singlton 中创建 BehaviorSubject
。它从 Retrofit
创建的 Observable
接收 onError
或 onNext
。片段订阅 BehaviorSubject
并接收其最后一个带有数据或错误的事件。当我需要刷新数据时,我重新创建BehaviorSubject
,重新订阅Retrofit
的Observable
来接收数据或singlton中的错误并重新订阅BehaviorSubject
在片段中.
public class SingltonRetrofitNew
{
private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());
private static Gson gson = new GsonBuilder().create();
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxAdapter)
.build();
private static GetModels apiService = retrofit.create(GetModels.class);
private static BehaviorSubject<ArrayList<Model>> observableModelsList;
private static Observable<ArrayList<Model>> observable = apiService.getModelsList();
private static Subscription subscription;
private SingltonRetrofitNew()
{
}
public static void resetObservable()
{
observableModelsList = BehaviorSubject.create();
if (subscription != null && !subscription.isUnsubscribed())
{
subscription.unsubscribe();
}
subscription = observable.subscribe(new Subscriber<ArrayList<Model>>()
{
@Override
public void onCompleted()
{
//do nothing
}
@Override
public void onError(Throwable e)
{
observableModelsList.onError(e);
}
@Override
public void onNext(ArrayList<Model> hotels)
{
observableModelsList.onNext(hotels);
}
});
}
public static Observable<ArrayList<Model>> getModelsObservable()
{
if (observableModelsList == null)
{
resetObservable();
}
return observableModelsList;
}
}
片段:
public class FragmentsList extends Fragment
{
private static final String TAG = FragmentList.class.getSimpleName();
private Subscription subscription;
private RecyclerView recyclerView;
private ArrayList<Hotel> models = new ArrayList<>();
private boolean isLoading;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.fragment, container, false);
//init views
recyclerView = (RecyclerView) v.findViewById(R.id.recycler);
if (savedInstanceState != null)
{
models = savedInstanceState.getParcelableArrayList(Const.KEY_MODELS);
isLoading = savedInstanceState.getBoolean(Const.KEY_IS_LOADING);
}
if (models.size() == 0 || isLoading)
{
getModelsList();
}
//TODO show saved data if is
return v;
}
@Override
public void onDestroy()
{
super.onDestroy();
if (subscription != null && !subscription.isUnsubscribed())
{
subscription.unsubscribe();
}
}
private void getModelsList()
{
if (subscription != null && !subscription.isUnsubscribed())
{
subscription.unsubscribe();
}
subscription = SingltonRetrofitNew.getModelsObservable().
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Subscriber<ArrayList<Hotel>>()
{
@Override
public void onCompleted()
{
Log.d(TAG, "onCompleted");
}
@Override
public void onError(Throwable e)
{
Log.d(TAG, "onError", e);
Snackbar.make(recyclerView, R.string.connection_error, Snackbar.LENGTH_SHORT)
.setAction(R.string.try_again, new View.OnClickListener()
{
@Override
public void onClick(View v)
{
SingltonRetrofitNew.reset();
getModelsList();
}
})
.show();
}
@Override
public void onNext(ArrayList<Hotel> newModels)
{
models.clear();
models.addAll(newModels);
//TODO show data
}
});
}
@Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(Const.KEY_MODELS, models);
outState.putBoolean(Const.KEY_IS_LOADING, isLoading);
}
}
我有:
API,即returns数据列表在JSON
.
我的目标:
通过Retrofit
+RxJava
获取此数据。
我的问题:
我只需要一个网络请求,如果屏幕在完成之前旋转,我不想开始新的请求。我还需要能够从 API.
刷新数据我是怎么解决的:
首先通过 Singlton 解决并在 Observable
中使用 cache()
缓存数据。
其次 - 完全重新创建 Retrofit
对象 (1)、改造接口实例 (2) 和 Observable
(3) 本身。我尝试只做 3 次,但失败了 - Observable
未重置并发出旧的缓存数据。
问题:
我重新创建 Observable
的工作方式看起来很糟糕。重新创建缓存 Observable
的 proper/better 方法是什么?
有我的辛格顿get/recreate Observalbe
:
public class SingltonRetrofit
{
private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());
private static Gson gson = new GsonBuilder().create();
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxAdapter)
.build();
private static GetModels apiService = retrofit.create(GetModels.class);
private static Observable<ArrayList<Model>> observableModelsList;
public static void reset()
{
retrofit = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxAdapter)
.build();
apiService = retrofit.create(GetModels.class);
observableModelsList = null;
}
public static Observable<ArrayList<Model>> getModelsObservable()
{
if (observableModelsList == null)
{
observableModelsList = apiService.getModelsList().cache();
}
return observableModelsList;
}
}
P.S.
同样的俄语问题:Как правильно пересоздать закэшированный Observable используемый вместе с Retrofit?
最后我是这样解决的:
我在 singlton 中创建 BehaviorSubject
。它从 Retrofit
创建的 Observable
接收 onError
或 onNext
。片段订阅 BehaviorSubject
并接收其最后一个带有数据或错误的事件。当我需要刷新数据时,我重新创建BehaviorSubject
,重新订阅Retrofit
的Observable
来接收数据或singlton中的错误并重新订阅BehaviorSubject
在片段中.
public class SingltonRetrofitNew
{
private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());
private static Gson gson = new GsonBuilder().create();
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxAdapter)
.build();
private static GetModels apiService = retrofit.create(GetModels.class);
private static BehaviorSubject<ArrayList<Model>> observableModelsList;
private static Observable<ArrayList<Model>> observable = apiService.getModelsList();
private static Subscription subscription;
private SingltonRetrofitNew()
{
}
public static void resetObservable()
{
observableModelsList = BehaviorSubject.create();
if (subscription != null && !subscription.isUnsubscribed())
{
subscription.unsubscribe();
}
subscription = observable.subscribe(new Subscriber<ArrayList<Model>>()
{
@Override
public void onCompleted()
{
//do nothing
}
@Override
public void onError(Throwable e)
{
observableModelsList.onError(e);
}
@Override
public void onNext(ArrayList<Model> hotels)
{
observableModelsList.onNext(hotels);
}
});
}
public static Observable<ArrayList<Model>> getModelsObservable()
{
if (observableModelsList == null)
{
resetObservable();
}
return observableModelsList;
}
}
片段:
public class FragmentsList extends Fragment
{
private static final String TAG = FragmentList.class.getSimpleName();
private Subscription subscription;
private RecyclerView recyclerView;
private ArrayList<Hotel> models = new ArrayList<>();
private boolean isLoading;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.fragment, container, false);
//init views
recyclerView = (RecyclerView) v.findViewById(R.id.recycler);
if (savedInstanceState != null)
{
models = savedInstanceState.getParcelableArrayList(Const.KEY_MODELS);
isLoading = savedInstanceState.getBoolean(Const.KEY_IS_LOADING);
}
if (models.size() == 0 || isLoading)
{
getModelsList();
}
//TODO show saved data if is
return v;
}
@Override
public void onDestroy()
{
super.onDestroy();
if (subscription != null && !subscription.isUnsubscribed())
{
subscription.unsubscribe();
}
}
private void getModelsList()
{
if (subscription != null && !subscription.isUnsubscribed())
{
subscription.unsubscribe();
}
subscription = SingltonRetrofitNew.getModelsObservable().
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Subscriber<ArrayList<Hotel>>()
{
@Override
public void onCompleted()
{
Log.d(TAG, "onCompleted");
}
@Override
public void onError(Throwable e)
{
Log.d(TAG, "onError", e);
Snackbar.make(recyclerView, R.string.connection_error, Snackbar.LENGTH_SHORT)
.setAction(R.string.try_again, new View.OnClickListener()
{
@Override
public void onClick(View v)
{
SingltonRetrofitNew.reset();
getModelsList();
}
})
.show();
}
@Override
public void onNext(ArrayList<Hotel> newModels)
{
models.clear();
models.addAll(newModels);
//TODO show data
}
});
}
@Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(Const.KEY_MODELS, models);
outState.putBoolean(Const.KEY_IS_LOADING, isLoading);
}
}