使用RXJAVA处理显示ProgresBar的服务器延迟

时间:2018-11-11 15:17:44

标签: android rx-java2 android-progressbar

我想为服务器延迟实现ProgressBar。

我基于:

借助Android中的MVVM,Dagger 2,LiveData和RxJava 2在Retrofit库中使用REST API

https://medium.com/@saquib3705/consuming-rest-api-using-retrofit-library-with-the-help-of-mvvm-dagger-livedata-and-rxjava2-in-67aebefe031d

我做了一些工作,但是有几个问题(底部的LogCat)

我的代码(已编辑-我的ViewModel类中的完整视图)

public class ViewModelApp extends ViewModel {

    //services
    private ServiceItune serviceItune;
    private ServiceLastFm serviceLastFm;

    @Inject
    @Named("apiLastFm")
    Retrofit apiLastFm;

    @Inject
    @Named("apiItune")
    Retrofit apiItune;


    // Rx
    private final CompositeDisposable disposables = new CompositeDisposable();
    Disposable disposable;

    // LifeData
    private MutableLiveData<ApiResponse> responseLiveDataCombinedResult;

    public MutableLiveData<ApiResponse> getResponseLiveDataCombinedResult () {

        if (responseLiveDataCombinedResult == null){
            responseLiveDataCombinedResult = new MutableLiveData<ApiResponse>();
        }
        return responseLiveDataCombinedResult;
    }

    // Constructor
    public ViewModelApp() {

        MainApplication.component.inject(this);
        serviceItune = apiItune.create(ServiceItune.class);
        serviceLastFm = apiLastFm.create(ServiceLastFm.class);
        getAll("");

    }

    public Observable getMergedObservable (String query) {

        Observable<RootiTune> iTuneObservable =serviceItune.getItuneArtistNameRx2NoList(ServiceItune.API_ITUNE_BASE_FULL_URL,query);
        Observable <RootLastFm>  lastFmObservable = serviceLastFm.searchArtistRx(ServiceLastFm.API_LAST_FM_FULL_URL, query, ServiceLastFm.KEY_LAST_FM,"json");

        return iTuneObservable.flatMap((Function<RootiTune, ObservableSource<CombinedResult>>)
                rootiTune -> {
                    return Observable.just(rootiTune).zipWith(lastFmObservable,
                            (rootiTune1, rootLastFm) -> new CombinedResult(rootiTune1, rootLastFm));
                });
    }

    public void getAll (String query){

        disposables.add(getMergedObservable(query)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                //  do something (update the UI) before the task started
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        responseLiveDataCombinedResult.setValue(ApiResponse.loading());
                        Log.v("Disposablevariable ",disposable.toString());
                    }
                })
                .subscribe((Consumer<CombinedResult>) combinedResult -> responseLiveDataCombinedResult.setValue(ApiResponse.success(combinedResult))
                        ,(Consumer<Throwable>)throwable -> responseLiveDataCombinedResult.setValue(ApiResponse.error(throwable))
                )
        );
    }

    @Override
    protected void onCleared() {
        disposables.clear();
    }
}

+

    public class ApiResponse {

        public final Status status;

        @Nullable
        public final CombinedResult combinedResult;

        @Nullable
        public final Throwable error;

        private ApiResponse(Status status, @Nullable CombinedResult combinedResult, @Nullable Throwable error) {
            this.status = status;
            this.combinedResult = combinedResult;
            this.error = error;
        }

        public static ApiResponse loading() {

            return new ApiResponse(LOADING, null, null);
        }

        public static ApiResponse success(@NonNull CombinedResult combinedResult) {
            return new ApiResponse(SUCCESS, combinedResult, null);
        }

        public static ApiResponse error(@NonNull Throwable error) {
            return new ApiResponse(ERROR, null, error);
        }

    }

我的http客户端:

@Provides
@Singleton
public OkHttpClient okHttpClient(HttpLoggingInterceptor loggingInterceptor) {


    return new OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .addInterceptor(chain -> {
                Request original = chain.request();
                Request request = original.newBuilder()
                        .build();
                return chain.proceed(request);
            })
            .connectTimeout(100, TimeUnit.SECONDS)
            .readTimeout(300, TimeUnit.SECONDS)
            .build();
}

最后:

class MainListFragment

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

        viewModel =
                ViewModelProviders
                .of(getActivity())
                .get(ViewModelApp.class);

        observeViewModel(viewModel);
    }

    private void observeViewModel(ViewModelApp viewModelAppe) {

        viewModelAppe.getResponseLiveDataCombinedResult().observe(getActivity(), this::consumeResponse);

    }

    private void consumeResponse(ApiResponse apiResponse) {

        switch (apiResponse.status){

            case LOADING:

                progressDialog.show();
                break;

            case SUCCESS:
                progressDialog.dismiss();
                if (apiResponse.combinedResult.getArtistsWithPhoto() != null){
                    mainAdapter.setProjectList(apiResponse.combinedResult.getArtistsWithPhoto());
                    combinedLocalResult = apiResponse.combinedResult;
                }


            case ERROR:
                if (!Constant.checkInternetConnection(getActivity())) {
                    progressDialog.dismiss();
                    Toast.makeText(getActivity(), getResources().getString(R.string.errorString), Toast.LENGTH_SHORT).show();
                }
            default:

                break;
        }

    }

我的LogCat:

 Attempt to invoke virtual method 'void android.arch.lifecycle.MutableLiveData.setValue(java.lang.Object)' on a null object reference

1 个答案:

答案 0 :(得分:1)

要解决该问题,您需要在responseLiveDataCombinedResult内初始化ViewModelApp变量。你可以那样做

private MutableLiveData<ApiResponse> responseLiveDataCombinedResult = new MutableLiveData<ApiResponse>();

或者如果由于某种原因您不想这样做,则需要通过调用getResponseLiveDataCombinedResult()访问该实时数据变量。

public void getAll (String query){

    disposables.add(getMergedObservable(query)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            //  do something (update the UI) before the task started
            .doOnSubscribe(new Consumer<Disposable>() {
                @Override
                public void accept(Disposable disposable) throws Exception {
                    getResponseLiveDataCombinedResult().setValue(ApiResponse.loading());
                    Log.v("Disposablevariable ",disposable.toString());
                }
            })
            .subscribe((Consumer<CombinedResult>) combinedResult -> getResponseLiveDataCombinedResult().setValue(ApiResponse.success(combinedResult))
                    ,(Consumer<Throwable>)throwable -> getResponseLiveDataCombinedResult().setValue(ApiResponse.error(throwable))
            )
    );
}

两种方法都可以接受。同样,如果您以这种方式重写Rx链,将会更加清楚

getMergedObservable(query)
    .map(result -> ApiResponse.success(result))
    .onErrorReturn(error -> ApiResponse.error(error))
    .startWith(ApiResponse.loading())
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(response -> getResponseLiveDataCombinedResult().setValue(response), error -> {/* should not happen*/})