【问题标题】:RxJava / Retrofit API Call for every item in a list of unknown sizeRxJava / Retrofit API 调用未知大小列表中的每个项目
【发布时间】:2018-06-24 19:48:29
【问题描述】:

我目前正在尝试第一次将 RxJava 与 Retrofit 一起使用,但似乎无法为我的特定用例提供任何工作:

我首先使用改造调用 API 来显示用户位置附近的电影院。 然后,我使用用户单击的影院 ID 来显示该影院的放映时间,即...

public interface ListingApiService
{
    @GET("/get/times/cinema/{id}")
    Call<ListingResponse> getShowtimes (@Path("id") String id);
}


Then using the interface....


public void connectAndGetApiData(String id)
    {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

        ListingApiService listingApiService = retrofit.create(ListingApiService.class);

        Call<ListingResponse> call = listingApiService.getShowtimes(id);
        call.enqueue(new Callback<ListingResponse>() {
            @Override
            public void onResponse(Call<ListingResponse> call, Response<ListingResponse> response)
            {
                List<Listing> listings = response.body().getListings()
                getAndDisplayImage(listings.get(0).getTitle());
        recyclerView.setAdapter(new ListingAdapter(listings,R.layout.list_item_listing,getApplicationContext()));

            }

            @Override
            public void onFailure(Call<ListingResponse> call, Throwable t)
            {
                Log.e(TAG,t.toString());

            }
        });
    }

然后,我想调用不同的 API(上下文网络搜索)来为每个电影列表显示相关电影海报的图像(只是为了获得良好的视觉效果)。我知道如何为单个图像调用 API,但我不知道如何进行多次调用。我已经尝试使用在互联网上其他地方找到的 RxJava 代码,但它似乎都不起作用,因为我不知道我将进行多少次调用或搜索词将是什么。我用于单个调用的代码是:

public interface ListingImageApiService
{
    //https://contextualwebsearch-websearch-v1.p.mashape.com/api/Search/ImageSearchAPI?count=1&autoCorrect=false&q=Donald+Trump
    @Headers("X-Mashape-Key: apikey")
    @GET("/api/Search/ImageSearchAPI?count=5&autoCorrect=false")
    Call<ListingImageResponse> getListingImages (@Query("q") String term);
}


 public void getAndDisplayImage(String search)
    {
        if (retrofit2 == null)
        {
            retrofit2 = new Retrofit.Builder()
                    .baseUrl(BASE_URL2)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

    search = search + " poster";
    ListingImageApiService listingImageApiService = retrofit2.create(ListingImageApiService.class);


    Call<ListingImageResponse> call = listingImageApiService.getListingImages(search);
    call.enqueue(new Callback<ListingImageResponse>() {
        @Override
        public void onResponse(Call<ListingImageResponse> call, Response<ListingImageResponse> response)
        {
            System.out.println(response.body().toString());
            ListingImage a = new ListingImage();
            List<ListingImage> listingImages = response.body().getListingImage();
            System.out.println(listingImages.get(0).getUrl());

        }

        @Override
        public void onFailure(Call<ListingImageResponse> call, Throwable t) 
        {

        }
    });
}

我的问题是,我将如何使用 RxJava 使用未知大小的电影标题列表的数据进行多次调用(我可以将其传递给 getAndDisplayImage 而不是单个字符串)?我进行了几次尝试,但似乎都不适用于我的用例。谢谢。

【问题讨论】:

  • 您是否使用了来自RxJavamap 运算符?从第一个api 获取数据并使用运算符和请求图像将结果转换为新的observer
  • 您好,我已经研究了地图运算符,但我不知道它如何解决我的问题。我不知道如何对多个对象进行 API 调用。地图怎么可能做到这一点?是不是简单的对集合应用了一个函数,还是我误解了map的用途?

标签: android api rx-java retrofit2 rx-java2


【解决方案1】:

这个设计应该可以解决你的问题。

此接口包含应用程序中使用的端点。

public interface ListingApiService
{
    @GET("/get/times/cinema/{id}")
    Observable<List<MovieResponse>> getShowtimes (@Path("id") String id);

    @Headers("X-Mashape-Key: apikey")
    @GET("/api/Search/ImageSearchAPI?count=5&autoCorrect=false")
    Observable<ListingImageResponse> getListingImages (@Query("q") String term);
}

提供改造对象进行调用的方法

private API getAPI() {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("<your API endpoint address")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build();

    return retrofit.create(API.class);
}

拨打电话获取List&lt;MovieResponse&gt;。此方法还将List 转换为单独的可观察MovieResponse 对象。

private void getMovieListingsWithImages() {
    Observer<MovieResponse> observer = new Observer<MovieResponse>() {
        @Override
        public void onSubscribe(Disposable d) {
            Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onNext(MovieResponse movieResponse) {
            //for each movie response make a call to the API which provides the image for the movie
        }

        @Override
        public void onError(Throwable e) {
            Toast.makeText(getApplicationContext(), "Error getting image for the movie", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onComplete() {
            Toast.makeText(getApplicationContext(), "Finished getting images for all the movies in the stream", Toast.LENGTH_SHORT).show();
        }
    };

    getAPI().getShowtimes()
            .flatMapIterable(movieResponseList -> movieResponseList) // converts your list of movieResponse into and observable which emits one movieResponse object at a time.
            .flatMap(this::getObservableFromString) // method converts the each movie response object into an observable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer);
}

MovieResponse 对象转换为Observable 的方法。

private Observable<MovieResponse> getObservableFromString(MovieResponse movieResponse) {
    return Observable.just(movieResponse);
}

【讨论】:

  • 您好,感谢您的时间和精力回复。结果,我实现了与您在此处建议的方式类似的东西,我使用列表类型和平面映射它们来创建一个可观察的列表对象,该对象重复 onNext 直到完成。这真的给了我实现 RxJava 所需的推动力,再次感谢
猜你喜欢
  • 2020-04-18
  • 2015-06-26
  • 1970-01-01
  • 2016-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多