11.从架构设计角度分析AAC源码-Room源码解析第0篇:开篇

本文从架构设计角度分析AAC源码,聚焦Room与Sqlite的关系。首先介绍Sqlite的基本增删改查操作,然后解析androidx中的Sqlite架构,包括SupportSQLite相关接口和类的实现,探讨其设计目的和用意。
摘要由CSDN通过智能技术生成

前言

本系列将从无到有一步步解析Room源码。解析过程中,我们始终不要记住,Room其实是对Sqlite的增删改查。只不过加了自己的很多思想去润色。

正文

解析顺序,本系列将根据以下系列解说Room源码架构:

  1. 涉及最基础的Sqlite增删改查(Room使用到的增删改查)和对Sqlite的封装(Androidx的Sqlite架构)

  2. 当前demo为主线涉及到的Room源码主线部分解说;

  3. Room compiler代码生成部分源码解说,以及对Room注解根据源码写一个使用文档;

  • room-compiler中androidx.room.parser中的SQLite 文件是如何生成的简单理解一下
  1. Room从架构层面分析;

Sqlite增删改查

如果对SQLite的应用不了解,没办法对Room进行解析。

说明一下几个关于数据库类的关系

SQLitDatabase家族部分成员,相关类的说明如下(除了下面以外,没做解释的可以不用看,和Room没啥多大关系):

  1. SQLiteOpenHelper是一个帮助(Utility)类,用于方便开发者创建和管理数据库。

  2. SQLiteDatabase代表SQLite数据库,它内部封装了一个Native层的sqlite3实例。

  3. SQLiteStatement用于描述和SQL语句相关的信息。

  4. SQLiteProgram是基类,它提供了一些API用于参数绑定。

  5. SQLiteQuery主要用于query查询操作,而SQLiteStatement用于query之外的一些操作(根据SDK的说明,如果SQLiteStatement用于query查询,其返回的结果集只能是1行*1列)。

demo应用

当前数据库存在demo.db数据库文件中,一个用户表users:userid和username两个字段,userid表示主键。实现如下:

  1. 创建数据库文件,并获取SQLiteDatabase数据库对象:

     public class OpenHelper extends SQLiteOpenHelper{
     
     	final Context mContext;
     
     	public OpenHelper(Context context, String name,int version){
     		super(context,name,null,version);
     		mContext = context;
     	}
     
     	public SQLiteDatabase getSQLiteDatabase(boolean writele){
     		String name = getDatabaseName();
             if (name != null) {
                 //数据库文件如果不存在,那么新建
                 File databaseFile = mContext.getDatabasePath(name);
                 File parentFile = databaseFile.getParentFile();
                 if (parentFile != null) {
                     parentFile.mkdirs();
                     if (!parentFile.isDirectory()) {
                         Log.w(TAG, "Invalid database parent file, not a directory: " + parentFile);
                     }
                 }
             }
     
             try {
                 return getWritableOrReadableDatabase(writable);
             } catch (Throwable t) {
                 // No good, just try again...
                 super.close();
             }
     		return null;
     	}
     
     	public SQLiteDatabase getWritableOrReadableDatabase(boolean writable) {
             if (writable) {
                 return super.getWritableDatabase();
             } else {
                 return super.getReadableDatabase();
             }
         }
     }
    

    //实例化OpenHelper,并且操作SQLiteDatabase都是在该类中通过getWritableOrReadableDatabase(writable)获取读写权限
    OpenHelper openHelper = new OpenHelper(context,“demo.db”,1);

  2. 添加和修改SQLite数据库 - 插入先开启事务,事务提示成功,最后结束事务:

     private void insert(User user){
     	SQLiteDatabase sqliteDatabase = openHelper.getSupportDatabase(true);
     	
     	sqliteDatabase.beginTransaction();
     	 try {
           insertUser(sqliteDatabase,user);
           sqliteDatabase.setTransactionSuccessful();
           return null;
         } finally {
           sqliteDatabase.endTransaction();
         }
    
     }
    
     private void insertUser(SQLiteDatabase sqliteDatabase,User user){
    
     	String query = "INSERT OR REPLACE INTO `users` (`userid`,`username`) VALUES (?,?)";
    
     	//compileStatement方法为了SQLiteStatement可重复利用
     	SQLiteStatement sqliteStatement = sqliteDatabase.compileStatement(query);
    
     	bind( stmt,  value);
     	stmt.executeInsert();
     }
    
     private void bind(SQLiteStatement stmt, User value) {
         if (value.getId() == null) {
           stmt.bindNull(1);
         } else {
           stmt.bindString(1, value.getId());
         }
         if (value.getUserName() == null) {
           stmt.bindNull(2);
         } else {
           stmt.bindString(2, value.getUserName());
         }
    
     	
       }
    
    • 如果userid相同,则覆盖;否则新建
  3. 删除SQLite,这个是删除表,删除某个字段应该也比较简单,修改query = "delete from users where userid = xxx"即可

     private void deleteUserTable(SQLiteStatement stmt){
     	String query = "DELETE FROM Users";
     	
     	//compileStatement方法为了SQLiteStatement可重复利用
     	SQLiteStatement sqliteStatement = sqliteDatabase.compileStatement(query);
     
     	SQLiteDatabase sqliteDatabase = openHelper.getSupportDatabase(true);
     			
     	sqliteDatabase.beginTransaction();
     	 try {
           stmt.executeUpdateDelete();
           sqliteDatabase.setTransactionSuccessful();
          
         } finally {
           sqliteDatabase.endTransaction();
         }
     }
    
  4. 查询SQLite

    public User getUser(SQLiteDatabase sqliteDatabase){
    final String sql = “SELECT * FROM Users LIMIT 1”;

     final Cursor cursor =sqliteDatabase.rawQuery(sql,null);
    
     try {
       final int cursorIndexOfMId = CursorUtil.getColumnIndexOrThrow(cursor, "userid");
       final int cursorIndexOfMUserName = CursorUtil.getColumnIndexOrThrow(cursor, "username");
       final User result;
       if(cursor.moveToFirst()) {
         final String _tmpMId;
         if (cursor.isNull(cursorIndexOfMId)) {
           tmpMId = null;
         } else {
           tmpMId = cursor.getString(cursorIndexOfMId);
         }
         final String tmpMUserName;
         if (cursor.isNull(cursorIndexOfMUserName)) {
           tmpMUserName = null;
         } else {
           tmpMUserName = cursor.getString(cursorIndexOfMUserName);
         }
         result = new User(tmpMId,tmpMUserName);
       } else {
         result = null;
       }
       return result;
     } finally {
       cursor.close();
     }
    

    }

代码是从源码你们抠出来的,理解起来也应该非常简单,这里理解对后面的源码理解有好处。

androidx中Sqlite架构源码解析

sqlite源码我只针对sqlite和sqlite-framework进行讲解:这两部分代码量也非常小,虽然简单,但对后面Room的理解至关重要。

sqlite

该模块主要启到规范使用SQLite的作用,当前操作SupportSQLite替代SQLite,省去其他SQLite中不必要的一些方法。

  1. SupportSQLiteOpenHelper接口:该接口定义了操作SupportSQLiteDatabase类的一些方法(最主要的是getWritableDatabase和getReadableDatabase,分别表示读写权限的数据库),另外有一些其他类或接口;
  • Callback抽象类:传入当前操作的数据库版本,用于对数据库的创建、打开、升级、降级、文件损坏处理;

  • Configuration类:创建sqliteOpenHelper类时的参数这里配置;

  • Builder类:使用构建者模式实例化Configuration类;

  • Factory接口:创建当前SupportSQLiteOpenHelper实例,传递Configuration类提供参数;

  1. SupportSQLiteDatabase接口:数据库操作方法,这里的方法和SQLiteDatabase基本一致;

  2. SupportSQLiteProgram接口:数据库字段绑定,根据字段类型,选取绑定类型,例如bindLong(int index,long value),表示当前绑定的字段是long类型,参数index表示当前字段处于数据库表中的位置;

  3. SupportSQLiteQuery接口:数据库query工作;

  4. SupportSQLiteStatement接口:规范数据库增删改查执行方法;

  5. SupportSQLiteCompat类:SQLiteDatabase兼容性处理;

  6. SimpleSQLiteQuery类:当前类继承SupportSQLiteQuery接口,存取sqlite的query和根据输入字段数组,确定SupportSQLiteProgram接口中的绑定类型;

  7. SupportSQLiteQueryBuilder类:构建者模式新建一个SimpleSQLiteQuery类,该类用于查询表中字段信息,可以实现精确查询。

以上说的非常非常抽象,可以按照SQLite去理解。不比过于纠结,我们继续看sqlite-framework(也是一个比较抽象的模块)

sqlite-framework

当前模块比较重要的特点:1. 继承sqlite模块下的接口;2. 采用代理模式执行代理方法;

  1. FrameworkSQLiteOpenHelperFactory类:工厂模式创建FrameworkSQLiteOpenHelper类;

  2. FrameworkSQLiteDatabase类:该类传递一个SQLiteDatabase数据库类作为代理对象delegate,继承SupportSQLiteDatabase接口,实现该接口的所有操作数据库方法,这些方法其实还是操作代理delegate的方法;

  3. FrameworkSQLiteProgram类:构造函数传递SQLiteProgram对象作为delegate代理,继承SupportSQLiteProgram接口,该接口实现方法实际操作的是delegate代理的相应方法;

  4. FrameworkSQLiteStatement类:继承FrameworkSQLiteProgram类,用于精确执行sql;构造函数传递SQLiteStatement delegate代理对象,该类继承SupportSQLiteStatement接口执行的实现方法最终执行的还是delegate代理的相应方法;

  5. FrameworkSQLiteOpenHelper类:该类只管重要

  • (1)当前类生成一个OpenHelper代理对象,该对象继承SQLiteOpenHelper类,所以实际实例化的是SQLiteOpenHelper类;
  • (2)OpenHelper类中创建FrameworkSQLiteDatabase实例,在SQLiteOpenHelper类中获取读写权限的SQLiteDatabase作为FrameworkSQLiteDatabase的构造函数参数;
  • (3)FrameworkSQLiteOpenHelper类继承SupportSQLiteOpenHelper接口,它操控的SupportSQLiteDatabase接口实际就是FrameworkSQLiteDatabase类;
  • (4)FrameworkSQLiteDatabase通过compileStatement方法返回SupportSQLiteStatement,同时将SQLiteStatement对象作为FrameworkSQLiteStatement构造函数的参数;
  • (5)为什么要使用OpenHelper类而不是直接使用SQLiteOpenHelper类?因为对sqlite的实际操作(创建,打开,升级,降级)都是通过回调Callback抽象类的相应方法去实现;

怎么说了感觉和没说一个样!!!我在哪?我是谁???我在干啥!!!

当前模块同样的比较抽象。可以从FrameworkSQLiteOpenHelper类的getDelegate方法为切入点去摸索,看个大概,我们继续往下才能明白人家具体含义。

参考

  1. Android内置SQLite的使用(超详细)

  2. SQLite–SQLiteDatabase、SQLiteOpenHelper、sqlite3.c–(jni、头文件)–源码分析基于Android M

  3. SQLiteDataBase事务

总结

代码还得仔细看下,因为后面room实际操作的就是sqlite-framework中的各个实现类,入口当然是FrameworkSQLiteOpenHelperFactory,新建一个操作FrameworkSQLiteDatabase类的FrameworkSQLiteOpenHelper类。

在思考一个问题,sqlite和sqlite-framework有必要吗?我直接使用SQlite不是更好,为什么要使用这里的SupportSqlite:通过一系列代理,实际执行的还是SQLite。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值