Android中的ContentProvider小结

xiaoxiao2021-02-28  102

ContentProvider作用

为存储和获取数据提供了统一的接口

实现了不用应用间的数据共享

Android为常用数据(如声音、图片、视频和通讯录等)提供的默认的ContentProvider支持

相关概念介绍

ContentProvider简介

为了实现向其他应用共享数据,需要继承一个抽象类ContentProvider,并实现如下几个抽象方法。

public class MyProvider extends ContentProvider { @Override public boolean onCreate() { return false; } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Nullable @Override public String getType(Uri uri) { return null; } @Nullable @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } }

看到这些抽象方法的参数是不是和数据库的相关操作很像。因此一般情况下,我们都是用数据库来存储数据。

Uri简介

概念:通用资源标示符(Uniform Resource Identifier)

组成部分:

scheme 访问资源的命名机制

authority 存放资源的主机名

path 资源自身的名称

格式:scheme://authority/path,其中authority还包括host的port。例如:

content://com.cydia.test:200/login/username

content为schemecom.cydia.test:200为authority(com.cydia.test为host,200为port)login/username为path。

Sqlite简介

参考文章《Android中的数据库应用小结》

本应用内的provider构建

众所周知,ContentProvider是用来向其他应用共享本应用内的数据,因此,我们首先需要确定数据在本应用内的存储方式。而考虑到继承ContentProvider需要实现的抽象方法(与sqlite的操作方法太相似),我们使用sqlite来存储数据。

创建数据库: MySqliteHelper

public class MySqliteHelper extends SQLiteOpenHelper { public static final String DB_NAME = "cydia.db"; public static final int DB_VERSION = 3; public static final String TABLE_NAME = "bookstore"; public static final String COLUMN_ID = "id"; public static final String COLUMN_NAME = "name"; public static final String COLUMN_AUTHOR = "author"; public static final String COLUMN_PRICE = "price"; public static final String COLUMN_PAGES = "pages"; public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + COLUMN_ID + " integer primary key autoincrement," + COLUMN_NAME + " text NOT NULL," + COLUMN_AUTHOR + " text," + COLUMN_PRICE + " real," + COLUMN_PAGES + " integer)"; public MySqliteHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_TABLE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } }

创建数据管理类: DBManager

public class DBManager { private volatile static DBManager sInstance; private SQLiteDatabase db; private DBManager(Context context) { MySqliteHelper helper = new MySqliteHelper(context); db = helper.getWritableDatabase(); } public static DBManager getInstance(Context context) { if (sInstance == null) { synchronized (DBManager.class) { if (sInstance == null) { sInstance = new DBManager(context); } } } return sInstance; } public long add(ContentValues contentValues) { return db.insert(MySqliteHelper.TABLE_NAME, null, contentValues); } public int delete(String whereClause, String[] whereArgs) { return db.delete(MySqliteHelper.TABLE_NAME, whereClause, whereArgs); } public int update(ContentValues contentValues, String whereClause, String[] whereArgs) { return db.update(MySqliteHelper.TABLE_NAME, contentValues, whereClause, whereArgs); } public Cursor query(String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) { return db.query(MySqliteHelper.TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy); } public void closeDB() { db.close(); } }

继承ContentProvider类

public class MyProvider extends ContentProvider { private Context context; private ContentResolver contentResolver; private static final String AUTHORITY = "com.pptv.test"; private static final int ALL_BOOKS = 1; private static final int SINGLE_BOOK = 1; //匹配Uri private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { //匹配Uri为content://com.pptv.test/bookstore 返回整数1 uriMatcher.addURI(AUTHORITY, MySqliteHelper.TABLE_NAME, ALL_BOOKS); //匹配Uri为content://com.pptv.test/bookstore/# 返回整数2,注#为通配符 //如content://com.pptv.test/bookstore/1 就返回2 uriMatcher.addURI(AUTHORITY, MySqliteHelper.TABLE_NAME + "/#", SINGLE_BOOK); } @Override public boolean onCreate() { context = getContext(); contentResolver = context.getContentResolver(); return true; } @Nullable @Override public String getType(Uri uri) { if (uriMatcher.match(uri) == ALL_BOOKS) { return "vnd.android.cursor.dir/" + MySqliteHelper.TABLE_NAME; } else if(uriMatcher.match(uri) == SINGLE_BOOK) { return "vnd.android.cursor.item/" + MySqliteHelper.TABLE_NAME; } return null; } @Nullable @Override public Uri insert(Uri uri, ContentValues values) { Uri ret = null; if (uriMatcher.match(uri) == ALL_BOOKS) { //uri为 content://com.pptv.test/bookstore 可以执行插入操作 long id = DBManager.getInstance(context).add(values); ret = ContentUris.withAppendedId(uri, id); contentResolver.notifyChange(ret, null); } //content://com.pptv.test/bookstore/4 没有插入权限 return ret; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int id = 0; if (uriMatcher.match(uri) == ALL_BOOKS) { //content://com.pptv.test/bookstore 删除满足条件的所有记录 id = DBManager.getInstance(context).delete(selection, selectionArgs); contentResolver.notifyChange(uri, null); } else if(uriMatcher.match(uri) == SINGLE_BOOK) { //content://com.pptv.test/bookstore/4 删除id=4的记录 long deleted_id = ContentUris.parseId(uri); id = DBManager.getInstance(context).delete(MySqliteHelper.COLUMN_ID + "=?", new String[]{deleted_id +""}); contentResolver.notifyChange(uri, null); } return id; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int id = 0; if (uriMatcher.match(uri) == ALL_BOOKS) { //content://com.pptv.test/bookstore 更新满足条件的所有记录 id = DBManager.getInstance(context).update(values, selection, selectionArgs); contentResolver.notifyChange(uri, null); } else if(uriMatcher.match(uri) == SINGLE_BOOK) { //content://com.pptv.test/bookstore/4 更新id=4的记录 long update_id = ContentUris.parseId(uri); id = DBManager.getInstance(context).update(values, MySqliteHelper.COLUMN_ID + "=?", new String[]{update_id +""}); contentResolver.notifyChange(uri, null); } return id; } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = null; if (uriMatcher.match(uri) == ALL_BOOKS) { //content://com.pptv.test/bookstore 查找满足条件的所有记录 cursor = DBManager.getInstance(context).query(projection, selection, selectionArgs, null, null, sortOrder); cursor.setNotificationUri(contentResolver, uri); } else if(uriMatcher.match(uri) == SINGLE_BOOK) { //content://com.pptv.test/bookstore/4 查找id=4的记录 long select_id = ContentUris.parseId(uri); cursor = DBManager.getInstance(context).query(projection, MySqliteHelper.COLUMN_ID + "=?", new String[]{select_id +""}, null, null, sortOrder); cursor.setNotificationUri(contentResolver, uri); } return cursor; } }

UriMatcher的作用在于,控制不同Uri的操作权限以及操作内容。 比如上述code所示:content://com.pptv.test/bookstore 执行查找其返回所有符合条件的记录,而content://com.pptv.test/bookstore/4 执行查找方法,其仅仅返回id为4的记录

在AndroidManifest中注册provider

<provider android:name=".provider.MyProvider" android:authorities="com.pptv.test" android:enabled="true" android:exported="true" /> android:authorities 访问这个provider的权限,需要和MyProvider中定义的AUTHORITY保持一致。android:enabled 指定这个内容提供器是否能够被系统安装android:exported 指定该内容提供器是否能够被其他的应用程序组件使用

其他应用使用Provider来访问数据

获取一个ContentResolver类

直接使用Content类的getContentResolver()方法就能获取到。

通过ContentResolver执行增删改查操作

ContentResolver的主要方法:

返回值函数声明final Uriinsert(Uri url, ContentValues values)final intdelete(Uri url, String where, String[] selectionArgs)final intupdate(Uri uri, ContentValues values, String where, String[] selectionArgs)final Cursorquery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

例如:查询所有的数据

private String getData(){ StringBuilder sb =new StringBuilder(); ContentResolver cr = this.getContentResolver(); Uri uri = Uri.parse("content://com.pptv.test/bookstore"); Cursor cursor = cr.query(uri, null, null,null,null); if(cursor != null){ Log.i(TAG, "cursor != null"); while(cursor.moveToNext()){ String name = cursor.getString(cursor.getColumnIndex("name")); String author = cursor.getString(cursor.getColumnIndex("author")); float price = cursor.getFloat(cursor.getColumnIndex("price")); int pages = cursor.getInt(cursor.getColumnIndex("pages")); sb.append("name = " + name + ", ") .append("author = " + author + ", ") .append("price = " + price + " ,") .append("pages = " + pages + "\n"); } cursor.close(); } return sb.toString(); }
转载请注明原文地址: https://www.6miu.com/read-29166.html

最新回复(0)