データベースにテーブルの連絡先があり、電話番号の連絡先があるかどうかを確認したい。
@Query("SELECT * FROM contact WHERE phone_number = :number")
Flowable<Contact> findByPhoneNumber(int number);
電話番号との連絡があるかどうかを確認するために、上記のステートメントでRxJava 2 Compositeディスポーザブルを使用しています。
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");
}
}));
クエリで必要な電話番号の連絡先が見つかった場合、これは正常に機能しますが、結果がある場合は何も起こりません。
ここに私が書いた2つのテストケースがあり、それらはうまく機能します:
@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();
}
}
これをどのように解決できますか?
here のように、この場合はMaybe
またはSingle
を使用できます。
@Query("SELECT * FROM Users WHERE id = :userId")
Maybe<User> getUserById(String userId);
ここで何が起こります:
@Query("SELECT * FROM Users WHERE id = :userId")
Single<User> getUserById(String userId);
以下にいくつかのシナリオを示します。
バージョン1.0.0-alpha5で追加されました。
シングルでラッパーを使用することもできると思います。お気に入り:
public class QueryResult<D> {
public D data;
public QueryResult() {}
public QueryResult(D data) {
this.data = data;
}
public boolean isEmpty(){
return data != null;
}
}
そして次のように使用します:
public Single<QueryResult<Transaction>> getTransaction(long id) {
return createSingle(() -> database.getTransactionDao().getTransaction(id))
.map(QueryResult::new);
}
ここでcreateAsyncSingle
:
protected <T> Single<T> createSingle(final Callable<T> func) {
return Single.create(emitter -> {
try {
T result = func.call();
emitter.onSuccess(result);
} catch (Exception ex) {
Log.e("TAG", "Error of operation with db");
}
});
}
IOスレッドを使用することを忘れないでください。