Room with Testing
and Rxjava
報告⼈人:Vincent
• ⽤用過sqlite

• ⽤用過dao

• ⽤用過room
• ⽤用過sqlite

• ⽤用過dao

• ⽤用過room
Gradle
implementation “android.arch.persistence.room:runtime:$room_version”
// use kapt for Kotlin
annotationProcessor “android.arch.persistence.room:compiler:$room_version"
// optional - RxJava support for Room
implementation "android.arch.persistence.room:rxjava2:$room_version"
Room architecture
RoomDatabase
@Database(entities = {WordMain.class, WordInfo.class, WordExample.class,
SearchTime.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract WordMainDao wordMainDao();
public abstract WordInfoDao wordInfoDao();
public abstract WordExampleDao wordExampleDao();
public abstract SearchTimeDao searchTimeDao();
}
class AppDbHepler{
AppDatabase appDatabase = Room.databaseBuilder(context, AppDatabase.class,
dbName).build();
appDatabase.wordMainDao();
appDatabase.wordInfoDao();
appDatabase.wordExampleDao();
appDatabase.searchTimeDao();
}
Entity
@Entity(indices={@Index(value="word", unique=true)})
public class WordMain {
@PrimaryKey
@NonNull
private String wordid;
@NonNull
@ColumnInfo(name = “English_Word")
private String word;
private int times;
}
Wordid English_word Times
1 One 1
Data Access Object (DAO)
@Dao
public interface WordMainDao {
@Insert
void insert(WordMain wordMain);
@Delete
void delete(WordMain wordMain);
@Update
void update(WordMain wordMain);
@Query("SELECT * FROM WordMain WHERE word IN (:word)")
Single<List<WordMain>> loadByword(String word);
}
Insert,Update,Delete
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(WordMain wordMain);
@Delete
void delete(WordMain... wordMain);
@Update
void update(List<WordMain> wordMain);
OnConflictStrategy
@Insert //ABORT
void insert(WordMain wordMain);
@Insert(onConflict = OnConflictStrategy.FAIL)
void insert(WordMain wordMain);
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(WordMain wordMain);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(WordMain wordMain);
@Insert(onConflict = OnConflictStrategy.ROLLBACK)
void insert(WordMain wordMain);
Query
@Query("SELECT * FROM WordMain WHERE word IN (:word)")
List<WordMain> loadByword(String word);
@Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid
= s.wordid group by w.wordid order by s.searchtime desc")
List<WordMain> loadAll();
@Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid
= s.wordid WHERE s.searchtime BETWEEN :from AND :to group by
w.wordid order by s.searchtime desc")
List<WordMain> findWordMainBetweenDates(Date from, Date to);
RxJava
@Query("SELECT * FROM WordMain WHERE word IN (:word)")
Flowable<List<WordMain>> loadByword(String word);
@Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid
= s.wordid group by w.wordid order by s.searchtime desc")
Maybe<List<WordMain>> loadAll();
@Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid
= s.wordid WHERE s.searchtime BETWEEN :from AND :to group by
w.wordid order by s.searchtime desc")
Single<List<WordMain>> findWordMainBetweenDates(Date from, Date to);
TypeConverter
public class DateConverters {
@TypeConverter
public static Date fromTimestamp(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long dateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
@Database(entities = {WordMain.class}, version = 1)
@TypeConverters({DateConverters.class})
public abstract class AppDatabase extends RoomDatabase {
……
}
Relation
單字 中英⽂文解釋 例例句句
Relation
@Entity(foreignKeys = @ForeignKey(entity = WordInfo.class,
parentColumns = "wordinfoid",
childColumns = "wordinfoid"),
indices={@Index(value="wordinfoid")})
public class WordExample {
…..
}
public class WordTotalInfo {
@Embedded
WordInfo wordInfo;
@Relation(parentColumn = "wordinfoid",
entityColumn = "wordinfoid", entity = WordExample.class)
List<WordExample> wordExamples;
…..
}
@Dao
public interface WordInfoDao {
@Query("SELECT * FROM WordInfo WHERE wordid IN (:wordid)")
Single<List<WordTotalInfo>> loadAllByIds(String wordid);
….
}
Testing
Testing
public class WordInfoDaoTest {
AppDatabase db;
@Before
public void setUp() throws Exception {
db = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext()
,AppDatabase.class).build();
}
@After
public void tearDown() throws Exception {
db.close();
}
}
@Test
public void OnConflictStrategy_ROLLBACK() {
try {
db.wordMainDao().insert(new WordMain("PrimaryKey3", "test", 123));
db.beginTransaction();
db.runInTransaction(new Runnable() {
@Override
public void run() {
List<WordMain> wordMains = new ArrayList<>();
wordMains.add(new WordMain("PrimaryKey2", "test1", 124));
wordMains.add(new WordMain("PrimaryKey3", "test7", 125));
db.wordMainDao().insert(wordMains);
db.setTransactionSuccessful();
}
});
} catch (Exception e) {
System.out.print(e.toString());
}
db.wordMainDao().all().subscribe(new SingleObserver<List<WordMain>>() {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onSuccess(List<WordMain> wordMains) {
Assert.assertThat(wordMains.size(), is(1));
Assert.assertThat(wordMains.get(0).getWordid(), is("PrimaryKey3"));
Assert.assertThat(wordMains.get(0).getWord(), is("test"));
Assert.assertThat(wordMains.get(0).getTimes(), is(123));
}
@Override
public void onError(Throwable e) {
System.out.print(e.toString());
}
});
}
@Test
public void wordTotalInfoQuery() {
wordMain = new WordMain("wordid3", "test", 123);
wordInfo = new WordInfo("wordinfoid2", "wordid3", "4", "5", "6");
wordExample = new WordExample("7", "wordinfoid2", "9", "10");
db.wordMainDao().insert(wordMain);
db.wordInfoDao().insert(wordInfo);
db.wordExampleDao().insert(wordExample);
Single<List<WordTotalInfo>> s = db.wordInfoDao().loadAllByIds("3");
s.subscribe(new Consumer<List<WordTotalInfo>>() {
@Override
public void accept(List<WordTotalInfo> wordTotalInfos) throws
Exception {
WordTotalInfo wordTotalInfo = wordTotalInfos.get(0);
WordInfo wordInfo = wordTotalInfo.getWordInfo();
WordExample wordExample = wordTotalInfo.getWordExamples().get(0);
Assert.assertThat(wordInfo.getWordinfoid(), is("wordinfoid2"));
Assert.assertThat(wordInfo.getWordid(), is("wordid3"));
Assert.assertThat(wordInfo.getChinesemean(), is("4"));
Assert.assertThat(wordInfo.getEnglishmean(), is("5"));
Assert.assertThat(wordInfo.getType(), is("6"));
Assert.assertThat(wordExample.getExampleid(), is("7"));
Assert.assertThat(wordExample.getWordinfoid(), is("wordinfoid2"));
Assert.assertThat(wordExample.getExample(), is("9"));
Assert.assertThat(wordExample.getExampletranslate(), is("10"));
}
});
}
Q&A

Room with testing and rxjava

  • 1.
    Room with Testing andRxjava 報告⼈人:Vincent
  • 2.
  • 3.
  • 4.
    Gradle implementation “android.arch.persistence.room:runtime:$room_version” // usekapt for Kotlin annotationProcessor “android.arch.persistence.room:compiler:$room_version" // optional - RxJava support for Room implementation "android.arch.persistence.room:rxjava2:$room_version"
  • 5.
  • 6.
    RoomDatabase @Database(entities = {WordMain.class,WordInfo.class, WordExample.class, SearchTime.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract WordMainDao wordMainDao(); public abstract WordInfoDao wordInfoDao(); public abstract WordExampleDao wordExampleDao(); public abstract SearchTimeDao searchTimeDao(); } class AppDbHepler{ AppDatabase appDatabase = Room.databaseBuilder(context, AppDatabase.class, dbName).build(); appDatabase.wordMainDao(); appDatabase.wordInfoDao(); appDatabase.wordExampleDao(); appDatabase.searchTimeDao(); }
  • 7.
    Entity @Entity(indices={@Index(value="word", unique=true)}) public classWordMain { @PrimaryKey @NonNull private String wordid; @NonNull @ColumnInfo(name = “English_Word") private String word; private int times; } Wordid English_word Times 1 One 1
  • 8.
    Data Access Object(DAO) @Dao public interface WordMainDao { @Insert void insert(WordMain wordMain); @Delete void delete(WordMain wordMain); @Update void update(WordMain wordMain); @Query("SELECT * FROM WordMain WHERE word IN (:word)") Single<List<WordMain>> loadByword(String word); }
  • 9.
    Insert,Update,Delete @Insert(onConflict = OnConflictStrategy.IGNORE) voidinsert(WordMain wordMain); @Delete void delete(WordMain... wordMain); @Update void update(List<WordMain> wordMain);
  • 10.
    OnConflictStrategy @Insert //ABORT void insert(WordMainwordMain); @Insert(onConflict = OnConflictStrategy.FAIL) void insert(WordMain wordMain); @Insert(onConflict = OnConflictStrategy.IGNORE) void insert(WordMain wordMain); @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(WordMain wordMain); @Insert(onConflict = OnConflictStrategy.ROLLBACK) void insert(WordMain wordMain);
  • 11.
    Query @Query("SELECT * FROMWordMain WHERE word IN (:word)") List<WordMain> loadByword(String word); @Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid = s.wordid group by w.wordid order by s.searchtime desc") List<WordMain> loadAll(); @Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid = s.wordid WHERE s.searchtime BETWEEN :from AND :to group by w.wordid order by s.searchtime desc") List<WordMain> findWordMainBetweenDates(Date from, Date to);
  • 12.
    RxJava @Query("SELECT * FROMWordMain WHERE word IN (:word)") Flowable<List<WordMain>> loadByword(String word); @Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid = s.wordid group by w.wordid order by s.searchtime desc") Maybe<List<WordMain>> loadAll(); @Query("SELECT * FROM WordMain w INNER JOIN SearchTime s ON w.wordid = s.wordid WHERE s.searchtime BETWEEN :from AND :to group by w.wordid order by s.searchtime desc") Single<List<WordMain>> findWordMainBetweenDates(Date from, Date to);
  • 13.
    TypeConverter public class DateConverters{ @TypeConverter public static Date fromTimestamp(Long value) { return value == null ? null : new Date(value); } @TypeConverter public static Long dateToTimestamp(Date date) { return date == null ? null : date.getTime(); } } @Database(entities = {WordMain.class}, version = 1) @TypeConverters({DateConverters.class}) public abstract class AppDatabase extends RoomDatabase { …… }
  • 14.
  • 15.
    Relation @Entity(foreignKeys = @ForeignKey(entity= WordInfo.class, parentColumns = "wordinfoid", childColumns = "wordinfoid"), indices={@Index(value="wordinfoid")}) public class WordExample { ….. } public class WordTotalInfo { @Embedded WordInfo wordInfo; @Relation(parentColumn = "wordinfoid", entityColumn = "wordinfoid", entity = WordExample.class) List<WordExample> wordExamples; ….. } @Dao public interface WordInfoDao { @Query("SELECT * FROM WordInfo WHERE wordid IN (:wordid)") Single<List<WordTotalInfo>> loadAllByIds(String wordid); …. }
  • 16.
  • 17.
    Testing public class WordInfoDaoTest{ AppDatabase db; @Before public void setUp() throws Exception { db = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext() ,AppDatabase.class).build(); } @After public void tearDown() throws Exception { db.close(); } }
  • 18.
    @Test public void OnConflictStrategy_ROLLBACK(){ try { db.wordMainDao().insert(new WordMain("PrimaryKey3", "test", 123)); db.beginTransaction(); db.runInTransaction(new Runnable() { @Override public void run() { List<WordMain> wordMains = new ArrayList<>(); wordMains.add(new WordMain("PrimaryKey2", "test1", 124)); wordMains.add(new WordMain("PrimaryKey3", "test7", 125)); db.wordMainDao().insert(wordMains); db.setTransactionSuccessful(); } }); } catch (Exception e) { System.out.print(e.toString()); } db.wordMainDao().all().subscribe(new SingleObserver<List<WordMain>>() { @Override public void onSubscribe(Disposable d) {} @Override public void onSuccess(List<WordMain> wordMains) { Assert.assertThat(wordMains.size(), is(1)); Assert.assertThat(wordMains.get(0).getWordid(), is("PrimaryKey3")); Assert.assertThat(wordMains.get(0).getWord(), is("test")); Assert.assertThat(wordMains.get(0).getTimes(), is(123)); } @Override public void onError(Throwable e) { System.out.print(e.toString()); } }); }
  • 19.
    @Test public void wordTotalInfoQuery(){ wordMain = new WordMain("wordid3", "test", 123); wordInfo = new WordInfo("wordinfoid2", "wordid3", "4", "5", "6"); wordExample = new WordExample("7", "wordinfoid2", "9", "10"); db.wordMainDao().insert(wordMain); db.wordInfoDao().insert(wordInfo); db.wordExampleDao().insert(wordExample); Single<List<WordTotalInfo>> s = db.wordInfoDao().loadAllByIds("3"); s.subscribe(new Consumer<List<WordTotalInfo>>() { @Override public void accept(List<WordTotalInfo> wordTotalInfos) throws Exception { WordTotalInfo wordTotalInfo = wordTotalInfos.get(0); WordInfo wordInfo = wordTotalInfo.getWordInfo(); WordExample wordExample = wordTotalInfo.getWordExamples().get(0); Assert.assertThat(wordInfo.getWordinfoid(), is("wordinfoid2")); Assert.assertThat(wordInfo.getWordid(), is("wordid3")); Assert.assertThat(wordInfo.getChinesemean(), is("4")); Assert.assertThat(wordInfo.getEnglishmean(), is("5")); Assert.assertThat(wordInfo.getType(), is("6")); Assert.assertThat(wordExample.getExampleid(), is("7")); Assert.assertThat(wordExample.getWordinfoid(), is("wordinfoid2")); Assert.assertThat(wordExample.getExample(), is("9")); Assert.assertThat(wordExample.getExampletranslate(), is("10")); } }); }
  • 20.