我想为服务器延迟实现ProgressBar。
我基于:
借助Android中的MVVM,Dagger 2,LiveData和RxJava 2在Retrofit库中使用REST API
我做了一些工作,但是有几个问题(底部的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
答案 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*/})