您的位置:首页 > 其它

22读书笔记之创建自己的内容提供器

2017-08-29 17:41 218 查看
新建一个类继承ContentProvider的方式来创建一个自己的内容提供器。

ContentProvider类中有6个抽象方法,我们在使用子类继承它的时候,需要将这六个方法全部重写。

新建 MyProvider 继承自 ContentProvider。复写几个方法。

public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
return 0;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}

@Override
public String getType(Uri uri) {
return null;
}
}


1. onCreate()

初始化内容提供器的时候调用,通常会在这里完成对数据库的创建和升级等操作.

返回 true 表示内容提供器初始化成功,返回 false 则表示失败。

注意,只有当存在 ContentResolver 尝试访问我们程序中的数据时,内容提供器才会被初始化。

2. query()

从内容提供器中查询数据。

使用 uri 参数来确定查询哪张表,projection 参数用于确定查询哪些列,selection 和 selectionArgs 参数用于约束查询哪些行,sortOrder 参数用于对结果进行排序。

查询的结果存放在 Cursor 对象中返回。


4000
3. insert()


向内容提供器中添加一条数据。

使用 uri 参数来确定要添加到的表,待添加的数据保存在 values 参数中。

添加完成后,返回一个用于表示这条新记录的 URI。

4. update()

更新内容提供器中已有的数据。

使用 uri 参数来确定更新哪一张表中的数据,新数据保存在 values 参数中,selection 和 selectionArgs 参数用于约束更新哪些行。

受影响的行数将作为返回值返回。

5. delete()

从内容提供器中删除数据。

使用 uri 参数来确定删除哪一张表中的数据,selection 和 selectionArgs 参数用于约束删除哪些行。

被删除的行数将作为返回值返回。

6. getType()

根据传入的内容 URI 来返回相应的 MIME 类型。

一个内容 URI 所对应的 MIME 字符串主要由三部分组分:

必须以 vnd. 开头。

如果内容 URI 以路径结尾,则后接 android.cursor.dir/,如果内容 URI 以 id 结尾,则后接 android.cursor.item/。

最后接上 vnd..。

对于 content://com.example.app.provider/table1,对应的 MIME 类型为:

vnd.android.cursor.dir/vnd.com.example.app.provider.table1

对于 content://com.example.app.provider/table1/1,对应的 MIME 类型为:

vnd.android.cursor.item/vnd.com.example.app.provider.table1

实现 getType() 逻辑 :

public class MyProvider extends ContentProvider {
......
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case TABLE1_DIR:
return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
case TABLE1_ITEM:
return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
case TABLE2_DIR:
return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2";
case TABLE2_ITEM:
return "vnd.android.cursor.item/vnd.com.example.app.provider.table2";
default:
break;
}
return null;
}
}


借助 UriMatcher 匹配内容 URI,得知传入的 Uri 对象是想访问哪张表中的哪条数据。

能够匹配任意表的内容 URI:

content://com.example.app.provider/*

能够匹配 table1 表中任意一行数据的内容 URI:

content://com.example.app.provider/table1/#

UriMatcher 中提供了一个 addURI() 方法,接收三个参数,可以分别把权限、路径和一个自定义代码传进去。

当调用 UriMatcher 的 match() 方法时,就可以将一个 Uri 对象传入,返

回值是某个能够匹配这个 Uri 对象所对应的自定义代码。

利用这个代码,我们就可以判断出调用方期望访问的是哪张表或哪一行中的数据了。

public static final int TABLE1_DIR = 0;
public static final int TABLE1_ITEM = 1;
public static final int TABLE2_DIR = 2;
public static final int TABLE2_ITEM = 3;

private static UriMatcher uriMatcher;

static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR);
uriMatcher.addURI("com.example.app.provider ", "table1/#", TABLE1_ITEM);
uriMatcher.addURI("com.example.app.provider ", "table2", TABLE2_ITEM);
uriMatcher.addURI("com.example.app.provider ", "table2/#", TABLE2_ITEM);
}


在 MyProvider 的几个方法中用 switch 判断 uriMatcher.match(uri),根据不同 Uri 的目的,把目的定位到相应表或行。

public class MyProvider extends ContentProvider {
public static final int TABLE1_DIR = 0; public static final int TABLE1_ITEM = 1; public static final int TABLE2_DIR = 2; public static final int TABLE2_ITEM = 3; private static UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR); uriMatcher.addURI("com.example.app.provider ", "table1/#", TABLE1_ITEM); uriMatcher.addURI("com.example.app.provider ", "table2", TABLE2_ITEM); uriMatcher.addURI("com.example.app.provider ", "table2/#", TABLE2_ITEM); }
......
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
switch (uriMatcher.match(uri)) {
case TABLE1_DIR:
// 查询table1表中的所有数据
break;
case TABLE1_ITEM:
// 查询table1表中的单条数据
break;
case TABLE2_DIR:
// 查询table2表中的所有数据
break;
case TABLE2_ITEM:
// 查询table2表中的单条数据
break;
default:
break;
}
......
}
......
}


明确目的后,具体靠对 SQLiteDatabase 进行操作完成增删改查。

public class DatabaseProvider extends ContentProvider {
public static final int BOOK_DIR = 0;
public static final int BOOK_ITEM = 1;
public static final int CATEGORY_DIR = 2;
public static final int CATEGORY_ITEM = 3;
public static final String AUTHORITY = "com.example.databasetest.provider";
private static UriMatcher uriMatcher;
private MyDatabaseHelper dbHelper;

static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
uriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
uriMatcher.addURI(AUTHORITY, "category/#", CATEGORY_ITEM);
}

@Override
public boolean onCreate() {dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);
return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// 查询数据
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
cursor = db.query("Book", projection, "id = ?", new String[]{ bookId }, null, null, sortOrder);
break;
case CATEGORY_DIR:
cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
cursor = db.query("Category", projection, "id = ?", new String[] { categoryId }, null, null, sortOrder);
break;
default:
break;
}
return cursor;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
// 添加数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
Uri uriReturn = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
case BOOK_ITEM:
long newBookId = db.insert("Book", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
break;
case CATEGORY_DIR:
case CATEGORY_ITEM:
long newCategoryId = db.insert("Category", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
break;
default:
break;
}
return uriReturn;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// 更新数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
int updatedRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
updatedRows = db.update("Book", values, selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
updatedRows = db.update("Book", values, "id = ?", new String[] { bookId });
break;
case CATEGORY_DIR:
updatedRows = db.update("Category", values, selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
updatedRows = db.update("Category", values, "id = ?", new String[] { categoryId });
break;
default:
break;
}
return updatedRows;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// 删除数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
int deletedRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
deletedRows = db.delete("Book", selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
deletedRows = db.delete("Book", "id = ?", new String[] { bookId });
break;
case CATEGORY_DIR:
deletedRows = db.delete("Category", selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deletedRows = db.delete("Category", "id = ?", new String[] { categoryId });
break;
default:
break;
}
return deletedRows;
}

@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.example.databasetest. provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.example.databasetest. provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.com.example.databasetest. provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.com.example.databasetest. provider.category";
}
return null;
}
}


getPathSegments() 方法

它会将内容 URI 权限之后的部分以 “/” 符号进行分割,并把分割后的结果放入到一个字符串列表中,这个列表的第 0 个位置存放的就是路径,第 1 个位置存放的就是 id。

要在 AndroidManifest.xml 里注册。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.databasetest"
android:versionCode="1"
android:versionName="1.0" >
......
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
......
<provider
android:name="com.example.databasetest.DatabaseProvider"
android:authorities="com.example.databasetest.provider" >
</provider>

</application>
</manifest>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  读书笔记