Android内容提供器(三)——自定义内容提供器

一、创建内容提供器的步骤

1、继承ContentProvider

自定义内容提供器可以通过新建一个类去继承ContentProvider来创建自己的内容提供器,该类一共有6个抽象方法,新建MyProvider类:

public class MyProvider extends ContentProvider {
    
    // 初始化的时候使用,完成数据库创建和升级,返回true代表成功
    @Override
    public boolean onCreate() {
        return false;
    }
    
    // uri:表名 projection:列名 selection(args):约束 sortOrder:排序 查询的结果在Cursor中返回
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
    }

    // 根据传入的uri返回相应的MIME【本文后面有解释】
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }
    
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

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

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

2、设置URI匹配

  • *:表示匹配任意长度的任意字符
  • #:表示匹配任意长度的数字

借助UriMatcher 这个类可以实现匹配内容URI的功能,其有三个参数:

  • authority
  • path
  • 自定义代码【区分内部是哪张表】

query()做个示例:

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", "tabke1", TABLE1_DIR);
        uriMatcher.addURI("com.example.app.provider", "tabke1/#", TABLE1_ITEM);
        uriMatcher.addURI("com.example.app.provider", "tabke2", TABLE2_DIR);
        uriMatcher.addURI("com.example.app.provider", "tabke2/#", TABLE2_ITEM);
    }

    // uri:表名 projection:列名 selection(args):约束 sortOrder:排序 查询的结果在Cursor中返回
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        switch (uriMatcher.match(uri)) {
            case TABLE1_DIR:
                // 查询表一所有数据
                break;
            case TABLE1_ITEM:
                // 查询表一单条数据
                break;
            case TABLE2_DIR:
                break;
            case TABLE2_ITEM:
                break;
            default:
        }
        return null;
    }

。。。。。。
}

3、MIME类型

getType()在自定义时必须填写,这个方法会返回相应的MIME类型MIME由三部分组成:

  • 必须以vnd开头
  • 如果URI以路径结尾,则后接android.cursor.dir/ ;如果URI以ID结尾,则后接android.cursor.item/
  • 最后补充vnd.<authority>.<path>【不包含ID】

比如:

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

则为:

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

所以getType():

public String getType(@NonNull 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;
}

二、实现跨程序数据共享

这里采用《Android数据存储(三)——SQLiteDatabase 操作 SQLite》的项目代码day12_DatabaseTest的备份,并改名为day12_DatabaseTest_backup

1、准备

删除有关Toast的代码,因为跨程序访问不能用Toast
接着快速生成一个内容提供器:
在这里插入图片描述
选中自动导入和可用性:
在这里插入图片描述
这样就能自动导入相关的<provider>进行注册:
在这里插入图片描述

2、巴拉巴拉写代码

public class DatabaseProvider extends ContentProvider {
    public static final int BOOK_DIR = 0;
    public static final int BOOK_ITEM = 1;
    public static final int CATAGORY_DIR = 2;
    public static final int CATAGORY_ITEM = 3;
    public static final String AUTHORITY = "com.example.databasetest.provider";
    public 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, "catagory", CATAGORY_DIR);
        uriMatcher.addURI(AUTHORITY, "catagory/#", CATAGORY_ITEM);
    }

    public DatabaseProvider() {
    }

    @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 CATAGORY_DIR:
                deletedRows = db.delete("Category", selection, selectionArgs);
                break;
            case CATAGORY_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 CATAGORY_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.category";
            case CATAGORY_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.categoty";
        }
        return null;
    }

    @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 CATAGORY_DIR:
            case CATAGORY_ITEM:
                long newCategoryId = db.insert("Category", null, values);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newCategoryId);
                break;
            default:
                break;
        }
        return uriReturn;
    }

    @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 CATAGORY_DIR:
                cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case CATAGORY_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 int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        SQLiteDatabase db = dbhelper.getWritableDatabase();
        int updateRows = 0;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                updateRows = db.update("Book", values, selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                updateRows = db.update("Book", values, "id = ?", new String[]{bookId});
                break;
            case CATAGORY_DIR:
                updateRows = db.update("Category", values, selection, selectionArgs);
                break;
            case CATAGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                updateRows = db.update("Categoty", values, "id = ?", new String[]{categoryId});
                break;
            default:
                break;
        }
        return updateRows;
    }
}

首先从类的一开始,定义4个常量,表示访问BookCategory的所有数据和单条数据,接着初始化UriMatcher,将期望匹配的几种内容URI添加进去。

  • onCreate()中借用MyDataBaseHelper完成数据库的创建或升级
  • query()返回cursor
  • insert()返回能够表示这条新增数据的URI
  • update()delete()返回受影响的行数

getPathSegments()会将内容URI权限之后的部分用/分割,并把结果放到字符串列表当中,其第0个位置放的是路径,第二个位置就是id了。

三、跨应用访问数据

接着在模拟器卸载重装当前应用,再创建一个新项目:day13_ProviderTest

1、布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="向 Book 表添加数据"
        android:id="@+id/insert"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查询 Book 表中的数据"
        android:id="@+id/query"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/update"
        android:text="修改 Book 表中的数据"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/delete"
        android:text="删除 Book 表中的数据"/>

</LinearLayout>

2、主活动

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private String newId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button_insert = findViewById(R.id.insert);
        button_insert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = Uri.parse("content://com.example.databasetest.provider/book");
                ContentValues values = new ContentValues();
                values.put("name","老人与海");
                values.put("author", "海明威");
                values.put("pages",345);
                values.put("price",10.88);
                Uri newUri = getContentResolver().insert(uri, values);
                newId = newUri.getPathSegments().get(1);
            }
        });

        Button button_delete = findViewById(R.id.delete);
        button_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = Uri.parse("content://com.example.databasetest.provider/book/"+newId);
                getContentResolver().delete(uri, null, null);
            }
        });
        
        Button button_update = findViewById(R.id.update);
        button_update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = Uri.parse("content://com.example.databasetest.provider/book/"+newId);
                ContentValues values = new ContentValues();
                values.put("name", "绿野仙踪");
                values.put("pages", 666);
                values.put("price", 88.88);
                getContentResolver().update(uri, values, null, null);
            }
        });
        
        Button button_query = findViewById(R.id.query);
        button_query.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = Uri.parse("content://com.example.databasetest.provider/book");
                Cursor cursor = getContentResolver().query(uri, null, null, null,null);
                if(cursor != null){
                    while (cursor.moveToNext()){
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        String author = cursor.getString(cursor.getColumnIndex("author"));
                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                        double price = cursor.getDouble(cursor.getColumnIndex("price"));

                        Log.d(TAG, "书名:"+name);
                        Log.d(TAG, "作者:"+author);
                        Log.d(TAG, "页数:"+pages);
                        Log.d(TAG, "价格:"+price);
                    }
                }
            }
        });
    }
}

3、运行

在这里插入图片描述

发布了156 篇原创文章 · 获赞 13 · 访问量 7215

猜你喜欢

转载自blog.csdn.net/qq_41205771/article/details/104205285