2

I am working on the application, where on the application startup I am downloading categories and posts from Rest service for storing them in the SQLite database. I have a few questions:

  1. How can I determine which object is Category and which Post? Or how can I access them at all? objects variable is pretty strange.
  2. Where I should put the code for inserting items in the database using Room library?
  3. I need to download images for each post, where I should do so?

Code:

ItemsApi client = this.getClient(); // Retrofit2

List<Observable<?>> requests = new ArrayList<>();
requests.add(client.getCategories());
requests.add(client.getPosts());

Observable<Object> combined = Observable.zip(
        requests,
        new Function<Object[], Object>() {
            @Override
            public Object apply(Object[] objects) throws Exception {
                Timber.d("Length %s", objects.length); // Length 2
                Timber.d("objects.getClass() %s", objects.getClass()); // objects.getClass() class [Ljava.lang.Object;

                return new Object();
            }
        });

Disposable disposable = combined.subscribe(
        new Consumer<Object>() {
            @Override
            public void accept(Object o) throws Exception {
               Timber.d("Object %s", o.toString());
            }
        },

        new Consumer<Throwable>() {
            @Override
            public void accept(Throwable e) throws Exception {
                Timber.d("error: %s", e.toString());
            }
        }
);


private ItemsApi getClient() {
    Retrofit.Builder builder = new Retrofit
            .Builder()
            .client(this.getOkHttpClient())
            .addConverterFactory(GsonConverterFactory.create(this.getGson()))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
            .baseUrl(Config.WEBSERVICE_URL_PREFIX);

    return builder.build().create(ItemsApi.class);
}

ItemsApi.class:

public interface ItemsApi {
    @GET("categories")
    Observable<List<CategoryEntity>> getCategories();

    @GET("posts")
    Observable<List<ArticleEntity>> getPosts();
}
LONGMAN
  • 980
  • 1
  • 14
  • 24
  • 1. `objects variable is pretty strange` because you're not using proper POJO class for the response (or caste it to POJO class you want). 2. Where's the sample JSON response? 3. You don't have to download images, just use image loading libraries instead. – Shashanth Feb 20 '19 at 04:27
  • @Shashanth I've added more code in the post. 1. Do I have to use POJO in the `apply` method? 2. Is it matters? service returns objects. 3. I need to download them – LONGMAN Feb 20 '19 at 07:28

2 Answers2

5

Here are answers:

1) For parallel requests, you should use Observable.zip, like this

Observable<Boolean> obs = Observable.zip(
    client.getCategories(),
    client.getPosts(), 
    (categoriesList, postsList) -> {
         // you have here both categories and lists
         // write any code you like, for example inserting to db
         return true;
});

Here you have parameters (categoriesList, postsList) each of its types, List and List.

2) You should put your code where I specified in comments. Make sure you have it in correct Thread

3) Downloading images could also be done there. You can have another zip-s in the function, combining parallel downloading images, insertions to db etc. All of them should be observables, combined with zip.

In zip you can combine as many observables, as you wish, their results will be available as combining function's parameters.

Misha Akopov
  • 12,241
  • 27
  • 68
  • 82
1

1._ Did you try addConverterFactory of Retrofit?

Retrofit restAdapter = new Retrofit.Builder().baseUrl("https://abc")
                .addConverterFactory(GsonConverterFactory.create(new Gson()))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        RestAuthenticationService restAuthenticationService = restAdapter.create(RestAuthenticationService.class);

In RestAuthenticationService.class:

public interface RestAuthenticationService {

    @POST("security/login")
    Observable<User> login(@Body LoginRequest loginRequest);

}
  1. You mean handle caching data at local? I think you should use Realm instead of Room/native SQLite.

  2. You should use Picasso or Glide.

Phong Nguyen
  • 6,897
  • 2
  • 26
  • 36
  • I've updated the post and added more code. 1. See my example. 2. I need to make fulltext search after downloading content, so SQLite is the choice. 3. Where I should put the code for downloading? In the `apply`? Or in the `accept`? – LONGMAN Feb 20 '19 at 07:35
  • I think should should change the way use RxJava with retrofit, take a look at here: https://stackoverflow.com/questions/34741970/how-to-run-2-queries-sequentially-in-a-android-rxjava-observable/47543995#47543995 – Phong Nguyen Feb 20 '19 at 08:36