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

来源:互联网 发布:淘宝网tfboys同款书包 编辑:程序博客网 时间:2024/05/22 12:47

新建一个类继承ContentProvider的方式来创建一个自己的内容提供器。
ContentProvider类中有6个抽象方法,我们在使用子类继承它的时候,需要将这六个方法全部重写。

  1. 新建 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 对象中返回。

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;  }}
  1. 借助 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);}
  1. 在 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;        }......    }......}
  1. 明确目的后,具体靠对 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。

  1. 要在 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>
阅读全文
0 0
原创粉丝点击