android - 同步 MVP 和 RxJava NetworkCall 的问题
问题描述
这是我的应用程序中的流数据:
在视图中,如果我调用presenter.Method(),我得到了方法onClick。在演示者的这个方法中,我将调用传递给模型(模型有他自己的抽象层 -> 接口 modelHelper。它通过构造函数演示器中的匕首 2 注入)。
在模型中,我得到了网络调用的方法:
@Override
public void networkCallForData(String request) {
request = "volumes?q=" + request;
compositeDisposable.add(
api.getBook(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
books -> {
items.clear();
items.addAll(books.items);
}
, Throwable::printStackTrace
, () -> {
}
)
);
}
}
我有 2 个问题: 1. 在 MVP 架构中,模型层是否应该注入抽象演示者的实例并将其连接到模型,就像使用视图一样?如果不是,我应该如何将数据从模型发送到演示者?
- 我尝试通过 RxJava2 将演示者连接到模型,但同步出现问题。在模型中,我从以下位置创建 observable:
private List<Items> items = new ArrayList<>();
和getter方法:
public Observable<List<Items>> getItemsObservable() {
return itemsObservable;
}
在这里我创建了 observable:
private Observable<List<Items>> itemsObservable = Observable.fromArray(items);
在演示者中,我得到了:
private void getDataFromModel() {
compositeDisposable.add(
findActivityModel.getItemsObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
books -> {
view.setRecycler(books);
}, Throwable::printStackTrace
, () -> {
view.setRecyclerVisible();
}
)
);
}
}
当我单击按钮进行搜索时,我得到了第一个空响应,因为我在列表中观察到尚未更新(它通过方法网络调用得到更新)。如果我第二次按下按钮,那是我从 1 个请求中获得所需数据的时候。我应该如何从不同的类中链接这 2 个 RxJava 方法?
解决方案
1. 在MVP架构中,Model层是否应该像view一样注入抽象presenter的实例并连接到model?
不,模型层不应直接访问视图或表示层。.observeOn(AndroidSchedulers.mainThread())
另请注意,放入任何模型层实现都没有多大意义。
如果不是,我应该如何将数据从模型发送到演示者?
模型应该只响应演示者的查询。这可能是一个简单的函数调用。模型不需要持有 Presenter 实例来处理它。
2. ...我应该如何从不同的类中链接这 2 个 RxJava 方法?
考虑这个实现:
模型
@Override
public Observable<List<Items>> networkCallForData(String request) {
request = "volumes?q=" + request;
return api.getBook(request);
}
主持人
// Call this once in the beginning.
private void getDataFromModel() {
compositeDisposable.add(
findActivityModel.networkCallForData(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
books -> {
view.setRecycler(books);
}, Throwable::printStackTrace
, () -> {
view.setRecyclerVisible();
}
)
);
}
如果您每个屏幕仅获取一次数据,上述实现应该就足够了。但是您提到了刷新按钮之类的东西。为此,您可以使用BehaviorSubject
or BehaviorProcessor
。
主持人
private BehaviorSubject<List<Item>> items =
BehaviorSubject.create(); // You may move this line to the Model layer.
// Call this once in the beginning to setup the recycler view.
private void getDataFromModel() {
// Instead of subscribing to Model, subscribe to BehaviorSubject.
compositeDisposable.add(
items.subscribe(books -> {
// Any change in BehaviorSubject should be notified
view.setRecycler(books);
view.setRecyclerVisible();
});
}
// Trigger this on button clicks
private void refreshData() {
compositeDisposable.add(
findActivityModel.networkCallForData(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(books -> {
// Refresh BehaviorSubject
items.onNext(books);
});
}
即使这可能并不完全符合您的需求,但希望您能理解。另外,一些旁注:
Observable.fromArray()
返回一个 observable,它一次发出一个数组项。因此,它在这种情况下不是很有用。似乎您有一个对象和一个包装该对象的可观察对象。如果你把这两个东西放在同一个地方,这通常是一个糟糕设计的标志。
私有 Observable> itemsObservable; 私有列表项;
这不是使用 observable 的正确方法,而且违反了单一事实来源。一种可能的重构方法:
private BehaviorSubject<List<Items>> itemsObservable;
// private List<Items> items; // Remove this line
public Observable<List<Items>> getItemsObservable() {
return itemsObservable.hide();
}
// Call this whenever you need to update itemsObservable
private void updateItems(List<Item> newItems) {
itemsObservable.onNext(newItems);
}
推荐阅读
- python - 无法使用年、月、日、小时和分钟列创建 DateTime 列
- newline - 电源自动化流程 - html 到文本 - 奇怪的新行
- apache-kafka - Kafka Producer 中的消息重试机制
- function - 将日期时间作为函数参数传递
- javascript - 如果使用 RegEx 中没有任何内容,请删除双撇号
- flutter - 如果选择的文件名没有扩展名,我们将如何在颤振中获取文件 mime 类型
- postgresql - Sql 将查询结果保存到在 postgres docker 上运行的变量
- python-3.x - ubuntu上的matplotlib,没有输出
- app-store - 如何在 iPhone 应用商店中查看畅销应用?
- mql5 - MQL5 中的 10015 错误(无效价格)元交易者