Android 中使用 Room 实践

使用Room进行持久化存储---综述
通过 Room entities 定义数据 ---Room 系列(1)
使用 Room 的 DAO 访问数据---Room 系列(2)
前面讲述了 Room 库的一些概念,这里记录一下自己的实践部分。

0. 添加依赖

    implementation "android.arch.persistence.room:runtime:1.0.0"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

1. 设置 Schema 的位置

在开始使用的时候,并没有注意 Schema 的问题,所以它就抛出了警告,希望我们指定 Schema 的输出位置,以更好的表明数据库的结构信息。这是,你需要在 build.gradle 中添加:

defaultConfig {
        applicationId "com.yuegs.test"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        //********注意这里**********
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
        //*************************
            }
        }
        ......
}

然后,编译运行之后,你就可以看到工程目录下的 schemas 问价夹。
每个数据库,会对应一个自己的 schema。
打开文件夹里面的 json 文件,你就能清楚看到自己定义的由Room 实际完成的数据库 schema 了。

2. 在数据库中存图片

遇到的第一个问题,就是如何使用 Room 库在数据库中存储图片。虽然,在数据库中存储图片实际上一般是不推荐的,但是还要看具体的使用场景和需求。
比如,我的需求主要来源于:将图片从服务器下载之后,持久化存储到本地;图片主要是一些勋章图片,大小在50k下;在需要的时候,需要快速检索出图片然后显示给用户;存储的时候,还需要记录图片的md5、勋章名称等。查了下资料,SQLite 可以存储的内容,在 TB 量级上,所以不需要担心数据库存不下你的内容,只要磁盘空间足够,就不存在问题。 (我使用模拟器,测试插入了1万张图片,在插入6千多图片后,大约2G,因为模拟器磁盘空间不足而抛出异常)。

@Entity
class User {
    @PrimaryKey(autoGenerate = true)
    public int id;

    public String firstName;

    @ColumnInfo(typeAffinity = ColumnInfo.BLOB)
    private byte[] headImage;
}

使用数据库存储图片,和直接在存储卡上存储文件相比,肯定往往不如直接存储文件效率高(文件搜索查询功能非常单纯),然而,数据库中存储了更多的结构性信息。
最后,为了以防万一,还是把图片再处理下,使用 OkHttp 下载图片,处理,插入数据库

OkHttpUtils.get(url, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                byte [] data = response.body().bytes() ;
                //以 50k 作为基准,50k以内不做处理,大于50k时,将压缩到50-100k之间
                float compressTimes = data.length / 1024.0f /50 ;
                ByteArrayOutputStream baos ;
                Bitmap bitmap ;
                if(compressTimes > 1){
                    baos = new ByteArrayOutputStream();
                    bitmap = BitmapFactory.decodeByteArray(data,0,data.length) ;
                    bitmap.compress(Bitmap.CompressFormat.JPEG, Math.round(100 /compressTimes), baos);
                    data = baos.toByteArray();
                }
                User user1 = new User();
                user1.setFirstName("compress");
                user1.setImage(data);
                db.userDao().insertAll(user1);
            }
        });

3. 将引用类型转换为基础类型存储

在 Room 中,是不支持引用类型的存储的(主要考虑到效率问题,往往我们在查询的时候想要查出的内容仅仅是一个属性,而不是一个对象),那么,我想存储时间 Date ,该怎么办呢?
需要提供一种转换,将引用类型转换为它可以存储的基础类型。

public class DateConverter {
    @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();
    }
}

上述代码块 ,将 Date 类型数据,转换为 long 类型的数据,可以存储在数据库中。
转换方法写完了,下面需要告诉数据库这个转换方法,否则它仍然无法完成转换,会报错告诉你它无法识别这个类型。

@Database(entities = { LogEntity.class},version = 1)
@TypeConverters({DateConverter.class})
public abstract class LogDatabase extends RoomDatabase {
    public abstract LogDao logEntityDao() ;
}

如上述代码块所示,在数据库上添加 @TypeConverters 注解。

4. 数据库导出与查看

我是在模拟器(系统4.4)中做的测试,那么直接使用 Android Studio 将数据库文件导出,使用 SQLite Expert 打开查看。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354