RxJava / Retrofit2 / Java - 未触发通用NetworkBoundResource

时间:2018-04-03 09:55:40

标签: java android rx-java

我是RxJava的新手,所以我深深的道歉,如果这个主题已经被覆盖或对你们中的某些人来说似乎很容易。我一直在寻找一个没有运气的解决方案。

我的许多API调用都基于原始的Google LiveData NetworkBoundResource类。由于业务逻辑的复杂性,我决定从LiveData迁移到RxJava。我将Kotlin版本https://android.jlelse.eu/networkboundresource-with-rxjava-and-kotlin-sealed-classes-1574bc516f82转换为Java版本并相应地调整了其余的实现。

public abstract class NetworkBoundResource<ResultType, RequestType> {

private final String TAG = NetworkBoundResource.class.getSimpleName();

private Flowable<Resource<ResultType>> result;

protected NetworkBoundResource() {

    // Lazy db observable.
    Flowable<ResultType> dbObservable = Flowable.defer(() ->
        loadFromDb()
            // Read from disk on Computation Scheduler
            .subscribeOn(Schedulers.computation())
    );

    // Lazy network observable.
    Flowable<ResultType> networkObservable = Flowable.defer(() ->
            createCall()
            // Request API on IO Scheduler
            .subscribeOn(Schedulers.io())
            // Read/Write to disk on Computation Scheduler
            .observeOn(Schedulers.computation())
            .doOnNext (request -> {
                    if (request.isSuccessful()) {
                        saveCallResult(processResponse(request));
                    } else {
                        processInternalError(request);
                    }
                })
            .onErrorReturn (throwable -> {
                throw Exceptions.propagate(throwable);
            })
            .flatMap(__ -> loadFromDb())
    );

    result = NetworkUtils.isNetworkStatusAvailable()
        ? networkObservable
                .map(Resource::success)
                .onErrorReturn (t -> Resource.error(t.getMessage(), null))
                .observeOn(AndroidSchedulers.mainThread())
                .startWith(Resource::loading)
        : dbObservable
                .map(Resource::success)
                .onErrorReturn (t -> Resource.error(t.getMessage(), null))
                .observeOn(AndroidSchedulers.mainThread())
                .startWith(Resource::loading);
}

public Flowable<Resource<ResultType>> asFlowable() {
    return result;
}

private RequestType processResponse(Response<RequestType> response) {
    return response.body();
}

private void processInternalError(Response<RequestType> response){
    String error = null;
    if (response.errorBody() != null) {
        try {
            error = response.errorBody().string();
        } catch (java.io.IOException ignored) {
            android.util.Log.e(TAG, "Error while parsing response: " + ignored.getMessage());
        }
        throw Exceptions.propagate(new Throwable(response.code() + ": " + error));
    }
}

protected abstract void saveCallResult(@NonNull RequestType item);

protected abstract Flowable<ResultType> loadFromDb();

protected abstract Flowable<Response<RequestType>> createCall();

}

订阅Steam的My View模型

public abstract class ItemListViewModel<T extends IListItem> extends AndroidViewModel {

private MutableLiveData<Resource<List<T>>> itemListObservable;
private Disposable disposable;

protected ItemListViewModel(Application application) {
    super(application);
    itemListObservable = new MutableLiveData<>();
    subscribe();
}

public LiveData<Resource<List<T>>> getItemListObservable() {
    return itemListObservable;
}

private void subscribe() {
    disposable = loadListItem()
            .subscribe(
                    list -> itemListObservable.setValue(list),
                    (Throwable t) -> itemListObservable.setValue(Resource.error(t.getMessage(), null))
            );
    DisposableManager.add(disposable);
}

@Override
protected void onCleared() {
    disposable.dispose();
}

protected abstract void init();

protected abstract Flowable<Resource<List<T>>> loadListItem();
}

我的通用片段正在处理资源状态

public abstract class ListItemFragment<T extends IListItem> extends Fragment {

protected ItemListAdapter<T> adapter;
protected RecyclerViewBinding binding;

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    binding = DataBindingUtil.inflate(inflater, R.layout.recycler_view, container, false);

    binding.recyclerView.setAdapter(adapter);
    binding.recyclerView.setHasFixedSize(true);
    binding.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    binding.setIsLoading(true);

    return binding.getRoot();
}

protected void observeViewModel(ItemListViewModel<T> viewModel) {
    // Observe and update the list when the data changes
    viewModel.getItemListObservable().observe(this, (@Nullable Resource<List<T>> iObservables) -> {
        if (iObservables != null) {
            processResponse(iObservables);
        }
    });
}

private void processResponse(Resource<List<T>> resource) {
    switch (resource.status) {
        case LOADING:
            renderLoadingState();
            break;

        case SUCCESS:
            renderDataState(resource.data);
            break;

        case ERROR:
            renderErrorState(resource.message);
            break;
    }
}

private void renderLoadingState(){
    binding.setIsLoading(true);
    adapter.replace(Collections.emptyList());
}

private void renderDataState(List<T> data){
    binding.setIsLoading(false);
    adapter.replace(data);
}

private void renderErrorState(String error){
    Toast.makeText(this.getContext(),error, Toast.LENGTH_SHORT).show();
}
}

虽然我按照说明订阅了createCall(),但它永远不会被触发。在我的日志拦截器中看不到它像之前那样

我的猜测是Flowable&gt; Retrofit没有正确识别。我确保将squareplapo中的CallAdapterFactory添加到我的HttpClient

BDRepository(String URL) {

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.enableComplexMapKeySerialization();
Gson gson = gsonBuilder.create();

retrofit = new Retrofit
            .Builder()
            .baseUrl(URL)
            .client(CustomTrust.getHttpClient())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();
}

我的gradle conf

//API request
implementation "com.squareup.retrofit2:retrofit:$rootProject.retrofit"
implementation "com.squareup.retrofit2:converter-gson:$rootProject.retrofit"
implementation "com.squareup.retrofit2:adapter-rxjava2:$rootProject.retrofit"

API调用在浏览器中尝试时返回数据。 在分解代码时,我的网络始终可用,因此networkObservable应该是实际的流。

我的改装服务

@GET("items")
Flowable<Response<List<Items>>> getItemList(@Query("lang") String 
language);

非常感谢任何帮助

0 个答案:

没有答案