1
votes

I have two slightly different Question classes. One is an retrofit call results object, and the other is a Room @Entity in my Android App.

And now I want from my Interactor class (Use-case) class do the following:

  1. Make a call to the API and result (List where question is the Retrofit response class)
  2. On success, make a new Game object in my Room database. This operation have long (@Entity id which is autogenerated) as return type.
  3. for each Question from retrofit response (from (1)), question -> Converter which converts from retrofit.Question to database.Question. Converter method takes 2 parameters, the retrofit.Question object and the ID which was returned in step (2). After conversion, add to database.
  4. Observe on AndroidSchedulers.mainthread. (subscribeOn is called from repository)

Now the problem I am having is creating this stream with RxJava from my Interactor class.

Here is all the classes and calls. First is my Interactor.class method which should do the stream described above:

public Single<List<Question>> getQuestionByCategoryMultiple(String parameter);

The API CALL from MyAPI.class:

//this Question is of database.Question.
Single<List<Question>> getQuestionByCategory(String parameter);

The Room database repository.class:

Single<Long> addGameReturnId(Game game);

Completable addQuestions(List<Question> questions);

Converter.class:

public static List<database.Question> toDatabase(List<retrofit.Question> toConvert, int id);

I am having trouble creating the stream described above with these methods. I tried a mix of .flatmap, .zip, .doOnSuccess, etc without successfully creating the stream.

If there is anything else you need me to explain, or explain the problem better, please comment below.

public Single> getQuestionByCategoryMultiple(String parameters){

    return openTDBType
            .getQuestionByCategory(paramters)    //step 1
            // step 2
            // step 3
            .observeOn(AndroidSchedulers.mainThread());   //step 4

}

EDIT:

I tried something like this:

return openTDBType
                .getQuestionByCategory(parameters)
                .map(QuestionConverter::toDatabase)
                .flatMap(questions -> {
                    int id = gameRepositoryType.addGameReturnId(new Game(parameters).blockingGet().intValue();
                    questions.forEach(question -> question.setqId(id));
                    gameRepositoryType.addQuestions(questions);
                    return gameRepositoryType.getAllQuestions(); })
                .observeOn(AndroidSchedulers.mainThread());

^^ I don't know if this is the best way to go about this one? Can anyone confirm if this is a good way to design what I want to do here, or if there are better ways or any suggestions?

1
I am confused why the Room DAO doesn't expose its values as Observable (or Flowable, whichever is supported). - EpicPandaForce
@EpicPandaForce Could you explain what you mean, I don't quite understand? - Carlton

1 Answers

1
votes

Try not use blockingGet especially when it is avoidable. Also, addQuestions won't be executed at all because it is not subscribed. You can add both addGameReturnId and addQuestions into the chain like this:

return openTDBType
            .getQuestionByCategory(parameters)
            .map(QuestionConverter::toDatabase)
            .flatMap(questions -> {
                return gameRepositoryType.addGameReturnId(new Game(parameters)) // returns Single<Long>
                    .map(id -> {
                        questions.forEach(question -> question.setqId(id));
                        return questions;
                    })      
            }) // returns Single<List<Question>> with the GameId attached
            .flatMapCompletable(questions -> gameRepositoryType.addQuestions(questions)) // returns Completable
            .andThen(gameRepositoryType.getAllQuestions()) // returns Single<>
            .observeOn(AndroidSchedulers.mainThread());