Android之创建自己的内容提供器

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

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

```handlebars
 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>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值