Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handel no results with Android Room and RxJava 2?

Tags:

I have database with table contact and I want to check if there is contact with some phone number.

@Query("SELECT * FROM contact WHERE phone_number = :number") Flowable<Contact> findByPhoneNumber(int number); 

I have RxJava 2 Composite disposable with statement from above to check if there is contact with phone number.

disposable.add(Db.with(context).getContactsDao().findByPhoneNumber(phoneNumber)             .subscribeOn(Schedulers.io())             .observeOn(AndroidSchedulers.mainThread())             .subscribeWith(new DisposableSubscriber<Contact>() {                 @Override                 public void onNext(final Contact contact) {                     Log.d("TAG", "phone number fined");                     Conversation conversation;                     if(contact != null){                         conversation = Db.with(context).getConversationsDao().findBySender(contact.getContactId());                         if(conversation != null){                             conversation.setUpdatedAt(Utils.getDateAndTimeNow());                             saveConversation(contact, conversation, context, text, phoneNumber, false);                         } else {                             conversation = getConversation(contact, contact.getPhoneNumber());                             saveConversation(contact, conversation, context, text, phoneNumber, true);                         }                     } else {                         conversation = Db.with(context).getConversationsDao().findByPhone(phoneNumber);                         if(conversation != null){                             conversation.setUpdatedAt(Utils.getDateAndTimeNow());                             saveConversation(contact, conversation, context, text, phoneNumber, false);                         } else {                             conversation = getConversation(contact, phoneNumber);                             saveConversation(contact, conversation, context, text, phoneNumber, true);                         }                     }                 }                  @Override                 public void onError(Throwable t) {                     Log.d("TAG", "find phone number throwable");                     Toast.makeText(context, t.getLocalizedMessage(), Toast.LENGTH_LONG).show();                 }                  @Override                 public void onComplete() {                     Log.d("TAG", "onComplete");                 }             })); 

This is working fine if query can find contact with required phone number, but if there is result, it nothing happens.

Here are two test cases that I wrote and they work fine:

@RunWith(AndroidJUnit4.class) public class ContactsTest {      private AppDatabase db;      @Rule     public InstantTaskExecutorRule instantTaskExecutorRule =             new InstantTaskExecutorRule();      @Before     public void initDb() throws Exception {         db = Room.inMemoryDatabaseBuilder(                 InstrumentationRegistry.getContext(),                 AppDatabase.class)                 // allowing main thread queries, just for testing                 .allowMainThreadQueries()                 .build();     }      @After     public void close(){         db.close();     }      @Test     public void insertAndFindTest(){         final Contact contact = new Contact();         contact.setName("Test");         contact.setPhoneNumber(555);         db.contactsDao()                 .insert(contact);          db.contactsDao().findByPhoneNumber(contact.getPhoneNumber())                 .test()                 .assertValue(new Predicate<Contact>() {                     @Override                     public boolean test(@NonNull Contact savedContact) throws Exception {                         if(savedContact.getPhoneNumber() == contact.getPhoneNumber()){                             return true;                         }                         return false;                     }                 });     }      @Test     public void findNoValues(){         db.contactsDao().findByPhoneNumber(333)                 .test()                 .assertNoValues();     }  } 

How I can solve this?

like image 582
Zookey Avatar asked Jul 06 '17 09:07

Zookey


People also ask

What does room query return if nothing is found?

If nothing is found based on your criteria, it will return null.

How do you use a RxJava room?

Insert. The Room integration with RxJava allows the following corresponding return types for insert: Completable — where onComplete is called as soon as the insertion was done. Single<Long> or Maybe<Long> — where the value emitted on onSuccess is the row id of the item inserted.

Is Android room an ORM?

Is Android Room an ORM? Room isn't an ORM; instead, it is a whole library that allows us to create and manipulate SQLite databases more easily. By using annotations, we can define our databases, tables, and operations.

What is Androidx room?

Room is a Database Object Mapping library that makes it easy to access database on Android applications. Rather than hiding the details of SQLite, Room tries to embrace them by providing convenient APIs to query the database and also verify such queries at compile time.


Video Answer


1 Answers

As said here, you can use Maybe or Single for this case:

Maybe

@Query("SELECT * FROM Users WHERE id = :userId") Maybe<User> getUserById(String userId); 

Here’s what happens:

  • When there is no user in the database and the query returns no rows, Maybe will complete.
  • When there is a user in the database, Maybe will trigger onSuccess and it will complete.
  • If the user is updated after Maybe was completed, nothing happens.

Single

@Query("SELECT * FROM Users WHERE id = :userId") Single<User> getUserById(String userId); 

Here are some scenarios:

  • When there is no user in the database and the query returns no rows, Single will trigger onError(EmptyResultSetException.class)
  • When there is a user in the database, Single will trigger onSuccess.
  • If the user is updated after Single.onComplete was called, nothing happens, since the stream was completed.

It was added in version 1.0.0-alpha5.

like image 121
J-rooft Avatar answered Nov 01 '22 12:11

J-rooft