欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android本地數(shù)據(jù)存儲Room實踐和優(yōu)化技巧

 更新時間:2023年04月26日 11:08:55   作者:頑石九變  
本文詳細介紹了Android本地數(shù)據(jù)存儲框架Room的使用,包括基本概念、核心組件、最佳實踐、優(yōu)化技巧等,幫助開發(fā)者學(xué)習(xí)和掌握Room的使用方法,提升數(shù)據(jù)存儲效率和應(yīng)用性能

Room在SQLite基礎(chǔ)上做了ORM封裝,使用起來類似JPA,不需要寫太多的sql。

導(dǎo)入依賴

//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"

關(guān)鍵注解說明

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);
    });
}

二、類型轉(zhuǎn)換器

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);
    }
}

三、結(jié)合RxJava

在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());
    });
}

到此這篇關(guān)于Android本地數(shù)據(jù)存儲Room實踐和優(yōu)化技巧的文章就介紹到這了,更多相關(guān)Android數(shù)據(jù)存儲Room內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Flutter渲染原理深入解析

    Flutter渲染原理深入解析

    眾所周知?Flutter是由Google推出的開源的高性能跨平臺框架,一個2D渲染引擎。在Flutter中,Widget是Flutter用戶界面的基本構(gòu)成單元,可以說一切皆Widget。下面來看下Flutter框架的整體結(jié)構(gòu)組成
    2023-04-04
  • android獲取手機唯一標(biāo)識的方法

    android獲取手機唯一標(biāo)識的方法

    這篇文章主要介紹了獲取安卓的手機或者平板的唯一標(biāo)識的方法,需要的朋友可以參考下
    2014-02-02
  • 基于Android6.0實現(xiàn)彈出Window提示框

    基于Android6.0實現(xiàn)彈出Window提示框

    這篇文章主要為大家詳細介紹了基于Android6.0實現(xiàn)彈出Window提示框,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Android中ViewPager獲取當(dāng)前顯示的Fragment

    Android中ViewPager獲取當(dāng)前顯示的Fragment

    這篇文章主要介紹了Android中ViewPager獲取當(dāng)前顯示的Fragment的兩種方法,一種是使用 getSupportFragmentManager().findFragmentByTag()方法,另一種是重寫適配器的 setPrimaryItem()方法,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • Android金額輸入框只允許輸入小數(shù)點后兩位效果

    Android金額輸入框只允許輸入小數(shù)點后兩位效果

    實現(xiàn)android 金額輸入框輸入小數(shù)點后兩位的效果也不是很復(fù)雜,只需要設(shè)置輸入框輸入的字符類型、設(shè)置InputFilter、設(shè)置輸入變化監(jiān)聽即可。這篇文章主要介紹了Android金額輸入框只允許輸入小數(shù)點后兩位 ,需要的朋友可以參考下
    2017-05-05
  • Android ViewFlipper簡單應(yīng)用

    Android ViewFlipper簡單應(yīng)用

    這篇文章主要為大家詳細介紹了Android ViewFlipper簡單應(yīng)用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Flutter實現(xiàn)單選,復(fù)選和開關(guān)組件的示例代碼

    Flutter實現(xiàn)單選,復(fù)選和開關(guān)組件的示例代碼

    在App開發(fā)過程中,選擇交互是非常常見的,今天主要介紹下關(guān)于選擇的三個組件的使用:開關(guān)、單選和復(fù)選,感興趣的小伙伴可以了解一下
    2022-04-04
  • Android 通過Intent使用Bundle傳遞對象詳細介紹

    Android 通過Intent使用Bundle傳遞對象詳細介紹

    這篇文章主要介紹了Android 通過Intent使用Bundle傳遞對象詳細介紹的相關(guān)資料,并附實例代碼講解,具有一定的參考價值,需要的朋友可以參考下
    2016-11-11
  • Android6.0開發(fā)中屏幕旋轉(zhuǎn)原理與流程分析

    Android6.0開發(fā)中屏幕旋轉(zhuǎn)原理與流程分析

    這篇文章主要介紹了Android6.0開發(fā)中屏幕旋轉(zhuǎn)原理與流程,結(jié)合實例形式詳細分析了Android6.0屏幕旋轉(zhuǎn)的原理與相關(guān)實現(xiàn)流程,并附帶了Android動態(tài)開啟與禁用屏幕旋轉(zhuǎn)的實現(xiàn)方法,需要的朋友可以參考下
    2017-11-11
  • Android實現(xiàn)環(huán)形進度條

    Android實現(xiàn)環(huán)形進度條

    這篇文章主要為大家詳細介紹了Android實現(xiàn)環(huán)形進度條,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07

最新評論