1

I am new to Rx java and I have a scenario where I want to get data from multiple APIs. These APIs are independent of each other but I want to show data from these APIs in a View. So I want to make these APIs calls in such a manner so that I can get every API data at the same time. I already using retrofit 2. I know a little bit about RX JAVA, but I only know how to make one request at a time. Please help

Retorfit Rest Client:

public class RestClient {

    private static ApiService apiService = null;    
    public static ApiService getApiService(String url) {
        apiService = null;    
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient okClient = new OkHttpClient.Builder().
                connectTimeout(1, TimeUnit.MINUTES).
                readTimeout(3, TimeUnit.MINUTES).
                addInterceptor(interceptor).build();    

        Gson gson = new GsonBuilder().setLenient().create();    

        Retrofit = new Retrofit.Builder()
                .baseUrl(url).client(okClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        apiService = restAdapter.create(ApiService.class);    
        return apiService;
    }
}

Api Service Interface:

public interface ApiService {


    @GET("v2/nearest_city")
    Observable<AqiDto> getAQI(@Query("lat") String latitude,
                          @Query("lon") String longitude,
                          @Query("key") String key);

    @GET("data/2.5/weather")
    Observable<WeatherDTO> getWeather(@Query("lat") String latitude,
                                  @Query("lon") String longitude,
                                  @Query("appid") String id);




}

Repository Class:

public class SiteListRepository {

    private static final String TAG = "SITE_LIST_REPO";
    private final CompositeDisposable disposable;
    private Context mContext;
    private AppUtilities mAppUtilities;

    public SiteListRepository(Application application) {
        mContext = application.getApplicationContext();
        disposable = new CompositeDisposable();
        mAppUtilities = new AppUtilities(mContext);
    }

public Object getData() {


    disposable = Observable.merge(RestClient.getApiService(BASE_URL_AIR_INDEX).getAQI(EcoHubApplication.mAppSharedPreference.getLatitude(), EcoHubApplication.mAppSharedPreference.getLongitude(), "2664b262-6369-415c-aa5a-ef2bd9ccf1cf")
            .subscribeOn(Schedulers.newThread()), RestClient.getApiService(BASE_URL_OPEN_WEATHER).getWeather(EcoHubApplication.mAppSharedPreference.getLatitude(), EcoHubApplication.mAppSharedPreference.getLongitude(), "b6907d289e10d714a6e88b30761fae22")
            .subscribeOn(Schedulers.newThread())).observeOn(AndroidSchedulers.mainThread()).subscribe(obj -> {

        object = obj;

    });



    return object;
}
}

Want to merge these 2 APIs calls together.

ViewModel:

public class SiteListViewModel extends AndroidViewModel {

    private SiteListRepository siteListRepository;
    public MutableLiveData<AqiDto> aqiDTOMutableLiveData = new MutableLiveData<>();
    public MutableLiveData<WeatherDTO> weatherDTOMutableLiveData = new MutableLiveData<>();
    private Object object;

    public SiteListViewModel(@NonNull Application application) {
        super(application);
        siteListRepository = new SiteListRepository(application);
    }

    public void getData(){
        object = siteListRepository.getData();

        if (object instanceof AqiDto){
            aqiDTOMutableLiveData.setValue((AqiDto) object);
        } else if (object instanceof WeatherDTO){
            weatherDTOMutableLiveData.setValue((WeatherDTO) object);
        }

    }

}
10
  • You can do either Single.zip(...) or Single.zipArray(...) Commented Dec 13, 2019 at 8:12
  • Zip is not the most effective way to manage it. I am looking out for a merge. Commented Dec 13, 2019 at 8:40
  • Then use Single.merge(...). Also, what do you mean by 'not the most effective way'? According to your usage, zip will be able to achieve what you want. Commented Dec 13, 2019 at 8:42
  • proandroiddev.com/… have a read, let me know I if am wrong. Commented Dec 13, 2019 at 9:19
  • In which part of the article does it say that zip is not effective? Because it seems to me that the article is praising its capabilities. Commented Dec 13, 2019 at 9:23

2 Answers 2

1

You can use Rxjava zip function for that

 @GET("v2/nearest_city")
    Observable<AqiDto> getAQI(@Query("lat") String latitude,
                          @Query("lon") String longitude,
                          @Query("key") String key);

    @GET("data/2.5/weather")
    Observable<WeatherDTO> getWeather(@Query("lat") String latitude,
                                  @Query("lon") String longitude,
                                  @Query("appid") String id);


    Observable.zip(ApiService.getAQI(your params),ApiService.getWeather(params)
    ,
    Function2<AqiDto, WeatherDTO,>> { 
        aqiDto, weatherDTO ->

        // Your operation here

        return weatherDTO;
    })
    .observeOn(AndroidSchedulers.mainThread())
    .doOnSubscribe { /* Loading Start */ }
    .doOnTerminate { /* Loading End */ }
    .subscribe(
            { /* Successfully Synced */ },
            { /* Having error */ }
    )
Sign up to request clarification or add additional context in comments.

1 Comment

Sir According to this document Zip is not the most effective way out: proandroiddev.com/…
1

Repository Class

public class SiteListRepository {

    private static final String TAG = "SITE_LIST_REPO";
    private final CompositeDisposable disposable;
    private Context mContext;
    private AppUtilities mAppUtilities;

    public SiteListRepository(Application application) {
        mContext = application.getApplicationContext();
        disposable = new CompositeDisposable();
        mAppUtilities = new AppUtilities(mContext);
    }

    public Observable getData() {
        return Observable.merge(RestClient.getApiService(BASE_URL_AIR_INDEX).getAQI(EcoHubApplication.mAppSharedPreference.getLatitude(), EcoHubApplication.mAppSharedPreference.getLongitude(), "2664b262-6369-415c-aa5a-ef2bd9ccf1cf")
            .subscribeOn(Schedulers.io()), RestClient.getApiService(BASE_URL_OPEN_WEATHER).getWeather(EcoHubApplication.mAppSharedPreference.getLatitude(), EcoHubApplication.mAppSharedPreference.getLongitude(), "b6907d289e10d714a6e88b30761fae22")
            .subscribeOn(Schedulers.io())).observeOn(AndroidSchedulers.mainThread())
    }
}

ViewModel

public class SiteListViewModel extends AndroidViewModel {

    private SiteListRepository siteListRepository;
    public MutableLiveData<AqiDto> aqiDTOMutableLiveData = new MutableLiveData<>();
    public MutableLiveData<WeatherDTO> weatherDTOMutableLiveData = new MutableLiveData<>();
    private Object object;
    private CompositeDisposable disposables = new CompositeDisposable();

    public SiteListViewModel(@NonNull Application application) {
        super(application);
        siteListRepository = new SiteListRepository(application);
    }

    public void getData(){
        disposables.add( 
            siteListRepository.getData()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe ( obj -> {
                     if (error != null) {
                         Log.e(TAG, error.message, error);
                     }
                     else {
                         if (obj instanceof AqiDto){
                             aqiDTOMutableLiveData.setValue((AqiDto) obj);
                         } else if (obj instanceof WeatherDTO){
                             weatherDTOMutableLiveData.setValue((WeatherDTO) obj);
                         }
                     }

                },
                error -> Log.e(TAG, error.message, error) // provide a second argument here to handle error
                )
        );


    }

@Override
protected void onCleared() {
    super.onCleared();
    disposable.clear();
    }
}

3 Comments

@KanwarpreetSingh I've edited my code to account for exceptions. You can also checkout this helpful link that I found for handling errors github.com/ReactiveX/RxJava/wiki/Error-Handling-Operators
Hi, Can you add code on how to handle exception for the same? If the response of any of APIs is not coming.
I don't understand where you have declared an error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.