r7v r7v - 5 months ago 20
Android Question

Rxjava Andriod- How to get the results returned by a map function

I am getting a list of multimedia information as part of my api call using RXjava map function to create a list of image urls from the response json. How can I handle the returned list from the map function

BrowseAPI service = CKApplication.getInstance().getRestAdapter().create(BrowseAPI.class);
BrowseRequest request = new BrowseRequest("0","50","true","A");
service.getMultmedia(MyApplication.getInstance().getJSessionID(), request).map(new Func1<Multimedia, Object>() {
@Override
public Object call(Multimedia multimedia) {
ArrayList<String> imageURLs = new ArrayList<String>();
for(MultiMediaImage image : multimedia.getResultsWrapper().getMultiMediaImage()) {
String url = "https://xxxxxxx/service/content/imageByEntitlement/";
url += image.getEid();
url +="?thumbnail=true";
imageURLs.add(url);
}
return imageURLs;
}
}).subscribe(multimedia -> {
Log.d("dfa", "adga");
});


I am able to create the string list of URLs from the response , I would like to handle this list of URLs in a separate activity or fragment.

Using flatMap, I am sure this can be improved :

BrowseAPI service = CKApplication.getInstance().getRestAdapter().create(BrowseAPI.class);
BrowseRequest request = new BrowseRequest("0","50","true","A");
service.getMultmedia(CKApplication.getInstance().getJSessionID(), request).flatMap(new Func1<Multimedia, Observable<MultiMediaImage>>() {
@Override
public Observable<MultiMediaImage> call(Multimedia multimedia) {
Observable<MultiMediaImage> observable = Observable.from(multimedia.getResultsWrapper().getMultiMediaImage());
return observable;
}
}).subscribe(new Action1<MultiMediaImage>() {
@Override
public void call(MultiMediaImage multiMediaImage) {
service.getImageObject(CKApplication.getInstance().getJSessionID(), multiMediaImage.getEid()).observeOn(AndroidSchedulers.mainThread()).subscribe(imageObject -> {
mImages.add(imageObject.getAuthenticatedStoreUrl());
adapter.notifyDataSetChanged();
});
}
});

Answer

How about this?

Observable<Multimedia> multimediaObservable = service.getMultmedia(MyApplication.getInstance().getJSessionID(), request);

Subscription subscription = bindFragment(this, multimediaObservable
.observeOn(AndroidSchedulers.handlerThread(new Handler()))
.map(new Func1<Multimedia, ArrayList<String>>() {
    @Override
    public ArrayList<String> call(Multimedia multimedia) {
        ArrayList<String> imageURLs = new ArrayList<String>();
        for(MultiMediaImage image : multimedia.getResultsWrapper().getMultiMediaImage()) {               
            imageURLs.add(makeImageUrl(image);
        }
        return imageURLs;
    }
})).subscribe(multimediaArrayList -> {
    //do something with the list
});

...
private String makeImageUrl(MultiMediaImage image){
    String url = "https://xxxxxxx/service/content/"
    url += image.getEid();
    url +="?thumbnail=true";
    return url;
}

Or with Java8 syntax that you use in the subscribe() method:

.map(multimedia -> {
    ArrayList<String> imageURLs = new ArrayList<String>();
    for(MultiMediaImage image : multimedia.getResultsWrapper().getMultiMediaImage()) {               
        imageURLs.add(makeImageUrl(image);
    }
    return imageURLs;        
})

Some notes:

  • I assume that the multimediaObservable is a network call which should not be done in the main thread. If its an observable emitted from Retrofit you don't need to worry to have a separate async thread.

  • The bindFragment() is part of the RxAndroid library which automatically "observe(s)On" the mainThread(). For activities use bindActivity(). Alternatively use observeOn(mainThread()).

  • There is no need as you do in the second example to use flatmap because it converts without need the object to observable and back to normal object (which the map directly can receive).

  • Don't forget the onError in the subsribe().

Update:

You can use from() to flatten the array and handle per MultimediaImage item in the subscribe.

Subscription subscription = bindFragment(this, multimediaObservable
.observeOn(AndroidSchedulers.handlerThread(new Handler()))
.flatMap(multimedia-> 
   Observable.from(multimedia.getResultsWrapper().getMultiMediaImage())
).subscribe(multimediaImage -> {
    //multimediaImage is a MultimediaImage class object
    Log.i("ImageId", multimediaImage.getEid());
});