同步MVP和RxJava NetworkCall的问题

时间:2019-02-20 13:30:26

标签: android rx-java2 mvp android-mvp

这是我的应用中的流量数据:

在视图中,我将方法onClick称为presenter.Method()。在presenter上的此方法中,我将调用传递给model(Model拥有自己的抽象层-> interface modelHelper。它通过Conctructor Presenter中的匕首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体系结构中,模型层是否应该注入抽象演示者的实例并将其连接到模型,就像使用view一样?如果不是,我应该如何将数据从模型发送到演示者?

  1. 我尝试通过RxJava2将演示者连接到模型,但出现同步问题。在模型中,我从以下位置创建可观察的对象:
private List<Items> items = new ArrayList<>();

和获取方法:

 public Observable<List<Items>> getItemsObservable() {
        return itemsObservable;
    }

在这里我创建可观察的:

    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个请求中获取数据的时间。我应该如何链接来自不同类的那两个RxJava方法?

1 个答案:

答案 0 :(得分:0)

1。在MVP体系结构中,模型层是否应该注入抽象演示者的实例并将其连接到模型,就像使用视图一样?

不。模型层不应直接访问视图层或表示层。 还要注意,将.observeOn(AndroidSchedulers.mainThread())放在模型层的任何实现中都没有多大意义。

如果不是,我应该如何将数据从模型发送到演示者?

模型应仅响应演示者的查询。这可能是一个简单的函数调用。模型不需要保存Presenter实例即可处理。


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();
                            }
                    )
    );
}

如果每个屏幕仅获取一次数据,则上述实现就足够了。但是您提到了诸如刷新按钮之类的东西。为此,您可以使用BehaviorSubjectBehaviorProcessor

演示者

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);
                    });
}

即使这可能无法完全满足您的需求,但也希望您能理解。另外,一些注意事项:

  1. Observable.fromArray()返回一个可观察的对象,该对象一次发出一个数组项。因此,在这种情况下,它不是很有用。

  2. 似乎您有一个对象以及包裹该对象的可观察对象。如果您将这两件事放在同一个地方,通常表示设计不好。

    私人可观察> itemsObservable; 私人列表项;

这不是使用可观察的正确方法,但也违反了单一的事实来源。 一种可能的重构方式:

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);
}