Android LiveData实现顺序网络请求(无RxJava)方案咨询
如何用Retrofit+LiveData实现顺序网络请求(无需RxJava)
我完全懂你现在的痛点——用多个LiveData观察者嵌套处理顺序请求,不仅代码看起来乱糟糟,还容易出现状态管理的漏洞。其实咱们可以把整个顺序请求的逻辑封装在ViewModel层,让视图层只需要观察一个统一的结果LiveData,这样代码会清晰很多,维护起来也更省心。
核心思路
- 在ViewModel中创建一个专门的
LiveData,用来暴露整个流程的状态(加载中/成功/失败) - 内部监听仓库层返回的请求结果:等
createItems成功后再触发deleteItem,任一环节失败就立刻终止流程并返回错误 - 借助
observeForever+手动移除观察者的方式,避免在视图层做嵌套观测,同时防止内存泄漏
具体代码改造
1. ViewModel层:封装顺序请求逻辑
我们新增一个处理顺序请求的方法,以及对应的结果LiveData,把所有链式请求的逻辑都放在这里:
private final MutableLiveData<Resource<Void>> sequentialRequestResult = new MutableLiveData<>(); public LiveData<Resource<Void>> getSequentialRequestResult() { return sequentialRequestResult; } // 执行「创建+删除」的顺序请求 public void executeCreateThenDelete(String id) { sequentialRequestResult.setValue(Resource.loading(null)); // 第一步:执行创建请求 LiveData<Resource<List<Items>>> createLiveData = eventItemRepository.createItems(); createLiveData.observeForever(new Observer<Resource<List<Items>>>() { @Override public void onChanged(Resource<List<Items>> createResult) { createLiveData.removeObserver(this); // 用完立刻移除,避免内存泄漏 if (createResult.status == Status.SUCCESS) { // 创建成功,执行第二步:删除请求 LiveData<Resource<EmptyResponse>> deleteLiveData = eventItemRepository.deleteItem(id); deleteLiveData.observeForever(new Observer<Resource<EmptyResponse>>() { @Override public void onChanged(Resource<EmptyResponse> deleteResult) { deleteLiveData.removeObserver(this); if (deleteResult.status == Status.SUCCESS) { sequentialRequestResult.postValue(Resource.success(null)); } else { sequentialRequestResult.postValue(Resource.error(deleteResult.message, null)); } } }); } else { // 创建失败,直接返回错误 sequentialRequestResult.postValue(Resource.error(createResult.message, null)); } } }); } // 单独执行删除请求的方法(对应原逻辑中的isCustomizedItem分支) public void executeDeleteOnly(String id) { sequentialRequestResult.setValue(Resource.loading(null)); LiveData<Resource<EmptyResponse>> deleteLiveData = eventItemRepository.deleteItem(id); deleteLiveData.observeForever(new Observer<Resource<EmptyResponse>>() { @Override public void onChanged(Resource<EmptyResponse> deleteResult) { deleteLiveData.removeObserver(this); if (deleteResult.status == Status.SUCCESS) { sequentialRequestResult.postValue(Resource.success(null)); } else { sequentialRequestResult.postValue(Resource.error(deleteResult.message, null)); } } }); }
2. 视图层:简化为单一观察者
现在视图层只需要调用对应的方法,然后观察一个LiveData就能处理所有状态:
String id = "items/1233"; if (isCustomizedItem) { viewModel.executeDeleteOnly(id); } else { viewModel.executeCreateThenDelete(id); } // 只需要监听这一个LiveData就够了 viewModel.getSequentialRequestResult().observe(this, result -> { if (result.status == Status.SUCCESS) { Timber.i("操作成功完成"); } else if (result.status == Status.ERROR) { Timber.e("操作失败:%s", result.message); // 这里可以统一处理错误提示,比如Toast或弹窗 } else if (result.status == Status.LOADING) { // 显示加载中UI,比如ProgressBar } });
3. 优化:抽取通用工具方法
为了避免重复写observeForever和removeObserver的代码,咱们可以抽一个工具类:
public class LiveDataUtils { public static <T> void observeOnce(LiveData<T> liveData, Observer<T> observer) { liveData.observeForever(new Observer<T>() { @Override public void onChanged(T t) { liveData.removeObserver(this); observer.onChanged(t); } }); } }
之后ViewModel里的代码可以简化成这样:
// 执行创建请求的部分 LiveDataUtils.observeOnce(createLiveData, createResult -> { if (createResult.status == Status.SUCCESS) { LiveDataUtils.observeOnce(eventItemRepository.deleteItem(id), deleteResult -> { // 处理删除结果 }); } else { // 处理创建失败 } });
方案优势
- 视图层代码极简:不用再处理多个观察者的嵌套,只关注最终的流程状态
- 逻辑内聚:所有顺序请求、错误处理的逻辑都在ViewModel里,符合MVVM的架构原则
- 状态统一:加载中、成功、失败的状态都通过同一个LiveData传递,避免状态不一致的问题
内容的提问来源于stack exchange,提问作者Saurabh Khare
相关产品推荐
相关产品推荐

