您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“Android本地數(shù)據(jù)存儲Room怎么優(yōu)化”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Android本地數(shù)據(jù)存儲Room怎么優(yōu)化”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
Room在SQLite基礎(chǔ)上做了ORM封裝,使用起來類似JPA,不需要寫太多的sql。
//room
def room_version="2.4.2"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
//implementation "androidx.room:room-rxjava2:$room_version"
//implementation "androidx.room:room-rxjava3:$room_version"
//implementation "androidx.room:room-guava:$room_version"
//testImplementation "androidx.room:room-testing:$room_version"
//implementation "androidx.room:room-paging:2.5.0-alpha01"
1、@Database:Room數(shù)據(jù)庫對象。該類需要繼承自RoomDatabase,通過Room.databaseBuilder()結(jié)合單例設(shè)計模式,完成數(shù)據(jù)庫的創(chuàng)建工作。我們創(chuàng)建的Dao對象,在這里以抽象方法的形式返回,只需一行代碼即可。
entities:指定該數(shù)據(jù)庫有哪些表
version:指定數(shù)據(jù)庫版本號,后續(xù)數(shù)據(jù)庫的升級正是依據(jù)版本號來判斷的
2、@Entity:該類與Room中表關(guān)聯(lián)起來。tableName屬性可以為該表設(shè)置名字,如果不設(shè)置,則表名與類名相同。
3、@PrimaryKey:用于指定該字段作為表的主鍵。
4、@ColumnInfo:設(shè)置該字段存儲在數(shù)據(jù)庫表中的名字并指定字段的類型;默認(rèn)字段名和屬性名一樣
5、@Ignore:忽略該字段
1、創(chuàng)建實體類,對應(yīng)數(shù)據(jù)庫中一張表,使用注解@Entity
2、創(chuàng)建Dao接口類,用于操作數(shù)據(jù),使用注解@Dao;不需要實現(xiàn),在編譯的時候,框架會自動生成實現(xiàn)類
3、創(chuàng)建數(shù)據(jù)庫對象Database,繼承RoomDatabase,使用單例模式返回實例
4、在Activity中使用,Room數(shù)據(jù)操作必須在異步線程中執(zhí)行,所以在Activity中使用線程池執(zhí)行,或者使用RxJava切換線程
使用代碼示例
1、創(chuàng)建實體類,對應(yīng)數(shù)據(jù)庫中一張表,使用注解@Entity
@Entity public class Person { // 主鍵,自增長 @PrimaryKey(autoGenerate = true) private int id; private String name; private String sex; private int age; }
2、創(chuàng)建Dao接口類,用于操作數(shù)據(jù),使用注解@Dao;不需要實現(xiàn),在編譯的時候,框架會自動生成實現(xiàn)類
@Dao public interface PersonDao { // 插入 @Insert void insertPersons(Person... persons); // 修改 @Update void updatePersons(Person... persons); // 刪除所有 @Query("delete from Person") void deleteAllPersons(); // 刪除指定實體 @Delete void deletePersons(Person... persons); // 根據(jù)id刪除 @Query("delete from Person where id in (:ids)") void deleteByIds(int ...ids); // 根據(jù)id查詢 @Query("select * from Person where id in (:ids)") List<Person> selectByIds(int ...ids); // 查詢所有 @Query("select * from Person order by id desc") List<Person> selectAllPersons(); }
3、創(chuàng)建數(shù)據(jù)庫對象Database,繼承RoomDatabase,使用單例模式返回實例
@Database(entities = {Person.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract PersonDao personDao(); private volatile static AppDatabase instance; public static AppDatabase getInstance(Context context){ if (instance == null) { synchronized (DBHelper.class) { if (instance == null) { instance = Room.databaseBuilder(context, AppDatabase.class, "person.db").build(); } } } return instance; } }
4、在Activity中使用
Room數(shù)據(jù)操作必須在異步線程中執(zhí)行,所以在Activity中使用線程池執(zhí)行
ExecutorService pool = Executors.newCachedThreadPool(); // 插入數(shù)據(jù) public void insertRoom(View view) { AppDatabase db = AppDatabase.getInstance(getApplicationContext()); pool.execute(() -> { PersonDao dao = db.personDao(); Person p1 = new Person("用戶1", "男", 18); Person p2 = new Person("用戶2", "男", 28); Person p3 = new Person("用戶3", "男", 38); dao.insertPersons(p1, p2, p3); }); } // 查詢數(shù)據(jù) public void queryRoom(View view) { AppDatabase db = AppDatabase.getInstance(getApplicationContext()); pool.execute(() -> { PersonDao dao = db.personDao(); List<Person> list = dao.selectAllPersons(); list.forEach(p-> Log.d("test", p.toString())); }); } // 根據(jù)id查詢 public void queryRoomById(View view) { AppDatabase db = AppDatabase.getInstance(getApplicationContext()); pool.execute(() -> { PersonDao dao = db.personDao(); List<Person> list = dao.selectByIds(3,4); list.forEach(p-> Log.d("test", p.toString())); }); } // 刪除 public void deleteRoom(View view) { AppDatabase db = AppDatabase.getInstance(getApplicationContext()); pool.execute(() -> { PersonDao dao = db.personDao(); dao.deleteByIds(1,2); }); }
SQLite支持null,integer,real,text,blob五種數(shù)據(jù)類型,實際上SQLite也接受varchar,char,decimal等數(shù)據(jù)類型,只不過在運算中或保存時會轉(zhuǎn)換成對應(yīng)的5種數(shù)據(jù)類型,因此,可以將各種類型數(shù)據(jù)保存到任何字段中。
除了上述基本類型外,其他如Date、BigDecimal、或Json對象等如何存儲呢?
Room給我們提供的非常方便的類型轉(zhuǎn)換器功能。
@TypeConverter,定義類型轉(zhuǎn)換靜態(tài)方法
@TypeConverters,定義包含一組轉(zhuǎn)換方法的class類
1、創(chuàng)建類型轉(zhuǎn)換類型,如,Date和Long互轉(zhuǎn)
使用注解@TypeConverter聲明具體的轉(zhuǎn)換方法,每個方法必須包含一個參數(shù),以及必須有返回值。
public class DateConverter { @TypeConverter public static Date toDate(Long dateLong) { return dateLong == null ? null : new Date(dateLong); } @TypeConverter public static Long fromDate(Date date) { return date == null ? null : date.getTime(); } }
2、將創(chuàng)建好的轉(zhuǎn)換器類,在entity上使用
使用注解@TypeConverters({DateConverter.class}),那么實體類中的所有的Date屬性都會被轉(zhuǎn)換成Long存儲,查詢?nèi)〕龅臅r候,會自動從Long轉(zhuǎn)換成Date顯示。
注意:@TypeConverters放在元素屬性、Class、Dao、Database上面
放在元素屬性,只對改屬性有效
放在實體Class上,對class中所有元素有效
放在Dao上,對Dao的所有方法有效
放在Database,對Database的所有實體和所有Dao都有效
為避免出現(xiàn)混亂,通常建議只在Entity或?qū)傩陨隙x轉(zhuǎn)換器
@Entity @TypeConverters({DateConverter.class}) public class BsGoods { private static final long serialVersionUID = 1122172437556010779L; // 主鍵 @PrimaryKey private Long id; private Date createdDate; private Date updatedDate; ... }
其他類型轉(zhuǎn)換示例,BigDecimal轉(zhuǎn)String。
如果是JavaBean等復(fù)雜對象,可以轉(zhuǎn)換成Json字符串存儲。
public class BigDecimalConverter { @TypeConverter public static String toStr(BigDecimal decimal) { return decimal == null ? null : decimal.toString(); } @TypeConverter public static BigDecimal toDecimal(String str) { return str == null ? null : new BigDecimal(str); } }
在Activity中使用,并且更新界面UI元素
Android的界面UI元素更新,必須在主線程中執(zhí)行,但是Room的數(shù)據(jù)查詢,又只能使用異常線程處理。那么如何將查詢到數(shù)據(jù),更新到頁面控件上面呢?
這里可以結(jié)合RxJava實現(xiàn)流式操作,線下切換!
示例代碼,查詢所有商品數(shù)據(jù),顯示在頁面控件上面,控件使用的是自定義的TableView,暫不展開,這里只顯示數(shù)據(jù)查詢以及顯示。
1、在Database類中定義查詢方法,傳入回調(diào)函數(shù)
public void selectAll(Consumer<List<BsGoods>> fun) { BsGoodsDao dao = bsGoodsDao(); Observable.just("select") .map(s -> dao.selectAll()) .subscribeOn(Schedulers.io())// 給上面的操作分配異步線程 .observeOn(AndroidSchedulers.mainThread())// 給終點分配安卓主線程 .subscribe(new Observer<List<BsGoods>>() { @Override public void onSubscribe(@NonNull Disposable d) { } @Override public void onNext(@NonNull List<BsGoods> bsGoods) { fun.accept(bsGoods); } @Override public void onError(@NonNull Throwable e) { } @Override public void onComplete() { } }); }
2、在Activity中使用,傳入回調(diào)函數(shù)更新界面UI
private void initializeTableViewLocal() { BsGoodsDatabase db = BsGoodsDatabase.getInstance(getContext()); db.selectAll(list -> { GoodsTableViewModel tableViewModel = new GoodsTableViewModel(list); TableViewAdapter tableViewAdapter = new TableViewAdapter(tableViewModel); mTableView.setAdapter(tableViewAdapter); mTableView.setTableViewListener(new TableViewListener(mTableView)); tableViewAdapter.setAllItems(tableViewModel.getColumnHeaderList(), tableViewModel .getRowHeaderList(), tableViewModel.getCellList()); }); }
讀到這里,這篇“Android本地數(shù)據(jù)存儲Room怎么優(yōu)化”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。