Use RxJava and Retrofit to iterate through list and augment results based on subqueries

前端 未结 3 1955
滥情空心
滥情空心 2021-02-08 07:07

I\'m using retrofit and I feel like rxjava (with retrolambda) would be a good fit for the following flow:

  1. get list of widgets (http)
  2. for each widget

相关标签:
3条回答
  • You could insert doOnNext at certain points of the stream to add side-effects:

    apiService.getWidgets(token)
    .flatMapIterable(v -> v)
    .flatMap(w -> 
        apiService.getArticles(token, w.type)
        .flatMapIterable(a -> a)
        .doOnNext(a -> db.insert(a))
        .doOnNext(a -> {
             w.articleName = a.name;
             w.articleUrl = a.url;
        })
        .takeLast(1)
        .map(a -> w)
    )
    .toList()
    .subscribe(
        modifiedWidgets -> saveWidgets(modifiedWidgets),
        throwable -> processWidgetError(throwable)
    );
    

    Here is runnable example of this.

    0 讨论(0)
  • 2021-02-08 07:42

    akarnokd's answer is quite helpful but that may cause NetworkOnMainThreadException. To solve that I have added

    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    

    on every requests

    apiService.getWidgets(token)
    .observeOn(AndroidSchedulers.mainThread())      //added this
    .subscribeOn(Schedulers.io())                   //added this
    .flatMapIterable(v -> v)
    .flatMap(w -> 
        apiService.getArticles(token, w.type)
        .observeOn(AndroidSchedulers.mainThread())  //added this
        .subscribeOn(Schedulers.io())               //added this
        .flatMapIterable(a -> a)
        .doOnNext(a -> db.insert(a))
        .doOnNext(a -> {
             w.articleName = a.name;
             w.articleUrl = a.url;
        })
        .takeLast(1)
        .map(a -> w)
    )
    .toList()
    .subscribe(
        modifiedWidgets -> saveWidgets(modifiedWidgets),
        throwable -> processWidgetError(throwable)
    );
    
    0 讨论(0)
  • 2021-02-08 07:44

    adding this here since I couldn't find an example of iterating a list that is returned in an object as variable.

    getUserAccount(token)
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap(userResponse -> Observable.just(userResponse.list))      //get list from response
        .flatMapIterable(baseDatas -> baseDatas)                          //make the list iterable
        .flatMap(baseData ->                                              //on each project, get the details
                getProjectDetails(baseData.name,token)
                        .subscribeOn(Schedulers.io())                     //get network call off the main thread
                        .observeOn(AndroidSchedulers.mainThread()))
        .subscribe(
                (dataResponse) -> {
                    Timber.d( "Got Data Details:" + dataResponse);
                },
                (error) -> {
                    Timber.e( "Got Error:" + error.getMessage());
                },
                () -> {
                    Timber.d("Completed Data Details");
                }
        );
    
    0 讨论(0)
提交回复
热议问题