最近出现了一个bug,room报错为“disk I/O error (code 522)”导致room用不了,第一次还是好好地,然后就不行了。我就学了和写了一个room的demo版本。

废话不多说,找到一个jetback demo很好的资源,分享给大家。

飞机票:https://github.com/zhiwei1990/android-jetpack-demo

一、jetback是什么

2018年谷歌I/O 发布了一系列辅助android开发者的实用工具,合称Jetpack,以帮助开发者构建出色的 Android 应用。

Android Jetpack 附带五个新组件:

  • WorkManager alpha 版
  • 导航 alpha 版
  • 分页稳定版
  • 切片 alpha 版
  • Android KTX(Kotlin 扩展程序)alpha 版

分页稳定版:它可以从本地存储和/或网络加载分页数据,并让您能够定义内容的加载方式。此组件原生支持 Room、LiveData 和 RxJava。

其他具体这里就不详细说明了,大家可以参考:Android Jetpack简介

二、Room简介

2.1 Room是什么

Room是Google提供的一个ORM库。Room提供了三个主要的组件:

  • @Database:@Database用来注解类,并且注解的类必须是继承自RoomDatabase的抽象类。该类主要作用是创建数据库和创建Daos(data access objects,数据访问对象)。
  • @Entity:@Entity用来注解实体类,@Database通过entities属性引用被@Entity注解的类,并利用该类的所有字段作为表的列名来创建表。
  • @Dao:@Dao用来注解一个接口或者抽象方法,该类的作用是提供访问数据库的方法。在使用@Database注解的类中必须定一个不带参数的方法,这个方法返回使用@Dao注解的类

2.2 Room架构图如下

 

room_architecture

三、实例

3.1 代码结构图

3.2 用到的Library文件

//jetpack room
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'

3.3 User.java文件

// 定义User表, 用Entity注解来表示这个类是一个数据库表
@Entity(tableName = "users")
public class User {
    @PrimaryKey(autoGenerate = true)
    public int uid;

    @ColumnInfo(name = "user_name")
    public String name = "";

    @ColumnInfo(name = "user_age")
    public int age = 0;

    @Override
    public String toString() {
        return "{User, uid : $uid ,name : $name ,age :$age}";
    }
}

3.4 IUserDao.java---IUserDao接口

// 定义数据访问对象的接口
@Dao
public interface IUserDao {
    @Insert
    void insertAll(User... users);//支持可变参数

    @Delete
    void delete(User user);

    @Delete
    void deleteAll(List<User> users);

    @Query("SELECT * FROM users")
    List<User> getAllUsers();

    @Query("SELECT * FROM users WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);//根据uid查询

    @Update
    void updateUser(User user);
}

3.5 AppDatabase.java---database对象类

/**
 * Room框架的database对象类,应该使用单例模式
 * Author: .tangwuke
 * Date: 2019/09/02
 */
@Database(entities = {User.class}, version = 1,exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {

    public static final String DB_NAME = "user.db";
    private static AppDatabase instance;

    public static synchronized AppDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(context, AppDatabase.class, DB_NAME)
                    .allowMainThreadQueries()//默认room不允许在主线程操作数据库,这里设置允许
                    .build();
        }
        return instance;
    }

    public abstract IUserDao getUserDao();

}

3.6 MainActivity.java---使用类


public class MainActivity extends AppCompatActivity {

    private static final String TAG = "tangtang";
    IUserDao userDao = null;
    private AppDatabase instance;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        deleteUser(-1);

        addUser("用户A",15);
        addUser("用户B",16);
        addUser("用户C",17);
        queryAll();

        updateUser(1,"用户A被改名了");
        queryAll();

        deleteUser(2);
        queryAll();
    }
    public void init(){
        Log.d(TAG, "init: This is init");
        userDao = AppDatabase.getInstance(this.getApplication()).getUserDao();
    }

    // 增加用户
    public void addUser(String name, int age){
        User user = new User();
        user.name = name;
        user.age = age;
        Log.d(TAG, "addUser: " + user.name+"  "+user.age);
        userDao.insertAll(user);
    }

    //删除指定id 用户
    public void deleteUser(int uid){
        User user = new User();
        user.uid = uid;
        Log.d(TAG, "deleteUser: " + user.uid);
        userDao.delete(user);
        if(uid == -1){
            List<User> users = userDao.getAllUsers();
            userDao.deleteAll(users);
        }
    }

    //更新某指定id 用户
    public void updateUser(int uid,String strName){
        User user = new User();
        user.uid = uid;
        user.name = strName;
        userDao.updateUser(user);
    }

    //查找全部用户
    public void queryAll() {
        List<User> users = userDao.getAllUsers();
        for (User oneUser : users){
            Log.d(TAG, "queryAll:  name:" + oneUser.name+" age: "+oneUser.age+" uid: "+oneUser.uid);
        }
    }
}

以上就是所有的源码分布,有不知道或者不清楚的欢迎再公众号来留言交流。

四、报错原因

4.1 原因分析

写完demo测试是没有问题的。然后回看问题代码,研究发现在room 创建数据对象的方法中databaseBuilder修改个database名称就没有问题了。

当然这不是问题的根源,问题的根源是,这个库在jni中使用sqlite3_open地方打开,然后导致冲突报错。

4.2 Room中打开

4.3 sqlite3中打开

4.4 尝试解决

将打开方式由sqlite3_open改成sqlite3_open_v2中使用SQLITE_OPEN_READONLY(只读模式)打开

结果还是报错。这个问题暂时我没有什么好方法,就留给大家。大家有好方法记得给我留言或者去我们公众号分享给我,谢谢!

结束语

以上就是本次分享的Room写法以及disk I/O error (code 522)错误原因。最后惯例给大家推介一下我们的技术工作号,欢迎大家来交流技术问题,谢谢!

在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐