代码之家  ›  专栏  ›  技术社区  ›  mohax

如何重新创建或重置缓存的Observable,与Retrofit一起使用以获取新数据?

  •  4
  • mohax  · 技术社区  · 10 年前

    我有:

    API,它返回中的数据列表 JSON .

    我的目标:

    Retrofit + RxJava .

    我的问题:

    我只需要一个网络请求,若屏幕在完成之前旋转过,我不想启动新的网络请求。我还需要从API刷新数据的能力。

    解决方法:

    第一个问题是通过Singleton和缓存数据来解决的 Observable 具有 cache() .

    改装 可观察的 (3) 本身。我试着只做了3次,但失败了- 可观察的 未重置,并发出旧的缓存数据。

    问题:

    可观察的 看起来很糟糕。重新创建缓存的正确/更好的方法是什么 可观察的 ?


    有我的Singleton要买/再买 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;
        }
    }
    

    附笔。

    俄语中的相同问题: Как правильно пересоздать закэшированный Observable используемый вместе с Retrofit?

    1 回复  |  直到 9 年前
        1
  •  2
  •   mohax    10 年前

    最后我解决了这个问题:

    我创造 BehaviorSubject onError onNext 从…起 Observable ,由创建 Retrofit .片段订阅 行为主体 并接收带有数据或错误的最后一个事件。当我需要刷新数据时,我会重新创建 行为主体 可观察的 接收singleton中的数据或错误并重新订阅 行为主体 碎片中。

    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);
        }
    }