目录
1、安卓数据存储方式
2、数据库事务
数据库事务的特性(ACID)
事务的隔离级别
事务总结
3、ContetProvider
作用
编辑
统一资源标识符URI
编辑
MIME类型
ContentProvider主要方法
4、ContentResolver
作用
主要方法
使用案例
辅助工具类
ContentUris
UriMatcher
ContentObserver
1、安卓数据存储方式
- SharedPreference
- 文件存储
- SQLite
- 网络存储
2、数据库事务
数据库事务的特性(ACID)
- 原子性:事务包含所有操作要么全部成功,要不回滚到原状态
- 一致性:事务执行前后,数据库的状态保持一致
- 隔离性:多用户并发访问数据库,多事务间相互不影响
- 持久性:事务一旦被提交,则永久修改数据库的数据
事务的隔离级别
- 读未提交
- 读已提交:避免脏读(读到未提交数据)
- 可重复度:避免不可重复读(当前事务而言,即使被另一个事务修改源数据,其看到的数据仍然是事务开始时刻的状态)
- 串行化:避免幻读(一个事务已经开始并且读取了数据之后,另一个事务插入了新的记录,使得第一个事务在后续的操作中可能会看到之前未读到的新数据。)
事务总结
3、ContetProvider
作用
- 原理底层是采用Binder机制
- 为存储和获取数据提供统一接口,实现应用程序间数据共享
- 通过URI可操作不同ContentProvider中数据
- 外部进程可通过ContentResolver类与ContentProvider进行交互
- 进程间数据交互与共享,实现跨进程通信
- ContentProvider相当于搬运工,真正数据源还是数据库、文件、XML、网络
统一资源标识符URI
唯一标识ContentProvider中数据
MIME类型
指定某个扩展名文件用某种应用打开
MIME类型组成 = 类型+子类型
如:
- text/html
- text/xml
- text/css
- application/pdf
MIME类型形式
ContentProvider主要方法
//外部进程向ContentProvider中添加数据 fun insert(uri:Uri,contentValues values):Uri //外部进程删除ContentProvider中数据 fun delete(uri:Uri,selection:String,selectionArgs:String[]):Int //外部进程更新ContentProvider中数据 fun update(uri:Uri,values:ContentValues,selection:String,selectionArgs:String[]):int //外部应用获取ContentProvider中数据 fun query (uri:Uri,projection:String[],selection:String,selectionArgs:String[],sortOrder:String):Cursor
4、ContentResolver
作用
通过 URI 即可操作不同 ContentProvider中数据
外部进程通过ContentResolver与ContentProvider进行交互
对所有的ContentProvider进行统一管理
主要方法
ContentResolver
类提供了与ContentProvider
类相同名字 & 作用的4个方法
//外部进程向ContentProvider中添加数据 fun insert(uri:Uri,contentValues values):Uri //外部进程删除ContentProvider中数据 fun delete(uri:Uri,selection:String,selectionArgs:String[]):Int //外部进程更新ContentProvider中数据 fun update(uri:Uri,values:ContentValues,selection:String,selectionArgs:String[]):int //外部应用获取ContentProvider中数据 fun query (uri:Uri,projection:String[],selection:String,selectionArgs:String[],sortOrder:String):Cursor
使用案例
val resolver = getContentResolver() val uri = Uri.parse("content://cn.scu.myprovider/user") val cursor:Cursor = resolver.query(uri,null,null,null,"userid desc")
辅助工具类
ContentUris
向URI追加&获取ID
// withAppendedId()作用:向URI追加一个id Uri uri = Uri.parse("content://cn.scu.myprovider/user") Uri resultUri = ContentUris.withAppendedId(uri, 7); // 最终生成后的Uri为:content://cn.scu.myprovider/user/7 // parseId()作用:从URL中获取ID Uri uri = Uri.parse("content://cn.scu.myprovider/user/7") long personid = ContentUris.parseId(uri); //获取的结果为:7
UriMatcher
在ContentProvider中注册URI,根据URI返回注册码,匹配ContentProvider中对应的数据表
// 步骤1:初始化UriMatcher对象 UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); //常量UriMatcher.NO_MATCH = 不匹配任何路径的返回码 // 即初始化时不匹配任何东西 // 步骤2:在ContentProvider 中注册URI(addURI()) int URI_CODE_a = 1; int URI_CODE_b = 2; matcher.addURI("cn.scu.myprovider", "user1", URI_CODE_a); matcher.addURI("cn.scu.myprovider", "user2", URI_CODE_b); // 若URI资源路径 = content://cn.scu.myprovider/user1 ,则返回注册码URI_CODE_a // 若URI资源路径 = content://cn.scu.myprovider/user2 ,则返回注册码URI_CODE_b // 步骤3:根据URI 匹配 URI_CODE,从而匹配ContentProvider中相应的资源(match()) @Override public String getType(Uri uri) { Uri uri = Uri.parse(" content://cn.scu.myprovider/user1"); switch(matcher.match(uri)){ // 根据URI匹配的返回码是URI_CODE_a // 即matcher.match(uri) == URI_CODE_a case URI_CODE_a: return tableNameUser1; // 如果根据URI匹配的返回码是URI_CODE_a,则返回ContentProvider中的名为tableNameUser1的表 case URI_CODE_b: return tableNameUser2; // 如果根据URI匹配的返回码是URI_CODE_b,则返回ContentProvider中的名为tableNameUser2的表 } }
ContentObserver
观察URI引起ContentProvider中的数据变化&通知访问者
// 步骤1:注册内容观察者ContentObserver getContentResolver().registerContentObserver(uri); // 通过ContentResolver类进行注册,并指定需要观察的URI // 步骤2:当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者) public class UserContentProvider extends ContentProvider { public Uri insert(Uri uri, ContentValues values) { db.insert("user", "userid", values); getContext().getContentResolver().notifyChange(uri, null); // 通知访问者 } } // 步骤3:解除观察者 getContentResolver().unregisterContentObserver(uri); // 同样需要通过ContentResolver类进行解除