• 25. Android开发笔记:内容提供器(二) 创建自己的内容提供器


    1.创建自己的内容提供器

    1.1 基础知识

    如果想要实现跨程序共享数据的功能,官方推荐的方式就是使用内容提供器,可以通过新建一个类去继承ContentProvider的方式来创建一个自己的内容提供器。ContentProvider类中有6个抽象方法,我们在使用子类继承它的时候,需要将这6个方法全部重写。

    1.1.1 内容URL

    回顾一下,一个标准的内容URI写法是这样的:
    content://com.example.app.provider/table1
    这就表示调用方期望访问的是com.example.app这个应用的table1表中的数据。
    除此之外,我们还可以在这个内容URI的后面加上一个id,如下所示: content://com.example.app.provider/table1/1 这就表示调用方期望访问的是com.example.app这个应用的table1表中id为1的数据。

    内容URI的格式主要就只有以上两种,以路径结尾就表示期望访问该表中所有的数据,以id结尾就表示期望访问该表中拥有相应id的数据。我们可以使用通配符的方式来分别匹配这两种格式的内容URI,规则如下。
    *:表示匹配任意长度的任意字符。

    :表示匹配任意长度的数字。

    所以,一个能够匹配任意表的内容URI格式就可以写成:

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

    而一个能够匹配table1表中任意一行数据的内容URI格式就可以写成:

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

    1.1.2 UriMatcher

    接着,我们再借助UriMatcher这个类就可以轻松地实现匹配内容URI的功能。
    当调用UriMatcher的match()方法时,就可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,我们就可以判断出调用方期望访问的是哪张表中的数据了。

    郭霖. 第一行代码 Android 第2版 (图灵原创) (Kindle位置4747). 人民邮电出版社. Kindle 版本.

    1.1.3 getType()方法

    其中方法 getType(): 根据传入的内容URI来返回相应的MIME类型。
    它是所有的内容提供器都必须提供的一个方法,用于获取Uri对象所对应的MIME类型。
    一个内容URI所对应的MIME字符串主要由3部分组成,Android对这3个部分做了如下格式规定。
    必须以 vnd 开头, 如果内容URI以路径结尾,则后接
    android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/ 。
    最后接上 vnd.. 。 所以,

    • 对于content://com.example.app.provider/table1这个内容URI,它所对应的MIME类型就可以写成:
    vnd.android.cursor.dir/vnd.com.example.app.provider.table1 
    
    • 对于content://com.example.app.provider/table1/1这个内容URI,它所对应的MIME类型就可以写成:
     vnd.android.cursor.item/vnd.com.example.app.provider.table1
    

    2. 示例

    2.1 创建内容提供器类

    打开之前的工程【DatabaseDemo】,右键包名->New ->Other->Content Provider:
    l类名:DatabaseContentProviderauthority 指定为 com.example.databasedemo.provider

    • Exported属性表示是否允许外部程序访问我们的内容提供器,
    • Enabled属性表示是否启用这个内容提供器。将两个属性都勾中,点击Finish完成创建。

    修改类DatabaseContentProvider: 实现继承ContentProvider的6个方法

    public class DatabaseContentProvider extends ContentProvider {
    
        public static final int Book_Dir = 0;
        public static final int Book_Item = 1;
        public static final int Gategory_Dir = 2;
        public static final int Gategory_Item = 3;
    
        public static final String Authority = "com.example.databasedemo.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, "gategory", Gategory_Dir);
            uriMatcher.addURI(Authority, "gategory/#", Gategory_Item);
        }
    
        public DatabaseContentProvider() {
        }
    
        @Override
        public boolean onCreate() {
            //获取 SQLiteOpenHelper 实例,以便操作数据库
            dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, MainActivity.DataBaseVersion);
            return true;
        }
    
        @Override
        public String getType(Uri uri) {
            //Implement this to handle requests for the MIME type of the data
            // at the given URI.
            switch (uriMatcher.match(uri)) {
                case Book_Dir:
                    return "vnd.android.cursor.dir/vnd.com.example.app.provider.book";
                case Book_Item:
                    return "vnd.android.cursor.item/vnd.com.example.app.provider.book";
                case Gategory_Dir:
                    return "vnd.android.cursor.dir/vnd.com.example.app.provider.gategory";
                case Gategory_Item:
                    return "vnd.android.cursor.item/vnd.com.example.app.provider.gategory";
            }
            return null;
        }
    
        /**
         * 查询
         */
        @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); //获取Id
                    cursor = db.query("Book", projection, "id=?", new String[]{ bookId}, null, null, sortOrder);
                    break;
                case Gategory_Dir:
                    cursor = db.query("category", projection, selection, selectionArgs, null, null, sortOrder);
                    break;
                case Gategory_Item:
                    String categoryId = uri.getPathSegments().get(1); //获取Id
                    cursor = db.query("category", projection, "id=?", new String[]{ categoryId}, null, null, sortOrder);
                    break;
            }
    
            return cursor;
        }
    
    
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            SQLiteDatabase db = dbHelper.getWritableDatabase();
            Uri retunUrl = null;
    
            switch (uriMatcher.match(uri)) {
                case Book_Dir:
                case Book_Item:
                    long newbookId = db.insert("Book", null, values);
                    retunUrl = Uri.parse("content://" + Authority + "/book/" + newbookId);
                    break;
    
                case Gategory_Dir:
                case Gategory_Item:
                    long newGategoryId = db.insert("Book", null, values);
                    retunUrl = Uri.parse("content://" + Authority + "/gategory/" + newGategoryId);
                    break;
            }
    
            return  retunUrl;
        }
    
    
        @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 Gategory_Dir:
                    updateRows = db.update("gategory", values, selection, selectionArgs);
                    break;
                case Gategory_Item:
                    String gategoryId =  uri.getPathSegments().get(1);
                    updateRows = db.update("gategory", values, "id=?", new String[]{ gategoryId});
                    break;
            }
            return  updateRows;
        }
    
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            SQLiteDatabase db = dbHelper.getWritableDatabase();
            int deleteRows = 0; //影响的行数
    
            switch (uriMatcher.match(uri)) {
                case Book_Dir:
                    deleteRows = db.delete("book", selection, selectionArgs);
                    break;
                case Book_Item:
                    String bookId =  uri.getPathSegments().get(1);
                    deleteRows = db.delete("book", "id=?", new String[]{ bookId});
                    break;
                case Gategory_Dir:
                    deleteRows = db.delete("gategory", selection, selectionArgs);
                    break;
                case Gategory_Item:
                    String gategoryId =  uri.getPathSegments().get(1);
                    deleteRows = db.delete("gategory", "id=?", new String[]{ gategoryId});
                    break;
            }
            return  deleteRows;
        }
    
    }
    

    2.2 注册内容提供器

    Android Studio 自动在AndroidManifest.xml自动添加:provider标签,对内容提供器进行了注册

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.databasedemo">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            
            <provider
                android:name=".DatabaseContentProvider"
                android:authorities="com.example.databasedemo.provider"
                android:enabled="true"
                android:exported="true"></provider>
            
            ......
            
    

    2.3 外部程序使用该内容提供器

    新建一个项目【UsingOutsideContentProvider】

    在创建4个按钮,分别用于增、删、改、查

    • activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <Button android:id="@+id/btn_insert"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:text="添加数据"/>
    
        <Button android:id="@+id/btn_query"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:text="查询数据"/>
    
        <Button android:id="@+id/btn_update"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:text="更新数据"/>
    
        <Button android:id="@+id/btn_delete"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:text="删除数据"/>
    
    </LinearLayout>
    
    • MainActivity.java
    public class MainActivity extends AppCompatActivity {
    
        private String newBookId;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //添加数据
            Button btn_insert = findViewById(R.id.btn_insert);
            btn_insert.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    ContentResolver contentResolver = getContentResolver();
                    Uri uri = Uri.parse("content://com.example.databasedemo.provider/book/");
    
                    ContentValues values = new ContentValues();
                    values.put("name", "waibuchengxu");
                    values.put("author", "lao wai");
                    values.put("pages", 30);
                    values.put("price", 6.40);
    
                    Uri newUri = contentResolver.insert(uri, values);
                    newBookId = newUri.getPathSegments().get(1);
                    Log.d("contentProvider-data", "newBookId: " + newBookId);
    
                    values.clear();
                    values.put("name", "waibuchengxu-2");
                    values.put("author", "lao wai");
                    values.put("pages", 30);
                    values.put("price", 6.40);
    
                    Uri newUri2 = contentResolver.insert(uri, values);
                    String newId2 = newUri2.getPathSegments().get(1);
                    Log.d("contentProvider-data", "newId2: " + newId2);
                }
            });
    
            //查询数据
            Button btn_query = findViewById(R.id.btn_query);
            btn_query.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    ContentResolver contentResolver = getContentResolver();
                    Uri uri = Uri.parse("content://com.example.databasedemo.provider/book/");
                    //Cursor cursor = contentResolver.query(uri, new String[]{ "name", "price","author"}, "author=?", new String[]{"lao wai"},null);
                    Cursor cursor = contentResolver.query(uri, new String[]{ "id, name", "price", "author"}, null, null,null);
    
                    int index=0;
                    if ( cursor != null){
                        while (cursor.moveToNext()) {
                            String id = cursor.getString(cursor.getColumnIndex("id"));
                            String name = cursor.getString(cursor.getColumnIndex("name"));
                            String price = cursor.getString(cursor.getColumnIndex("price"));
                            String author = cursor.getString(cursor.getColumnIndex("author"));
    
                            String msg = (++index)+". id:" + id +" | name:" + name + " | author:" + author+ " | price:" + price;
    
                            Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                            Log.d("contentProvider-data", msg);
                        }
                    }
    
                    cursor.close(); //记得关闭指针
                }
            });
    
            //更新数据
            Button btn_update = findViewById(R.id.btn_update);
            btn_update.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ContentResolver contentResolver = getContentResolver();
                    Uri uri = Uri.parse("content://com.example.databasedemo.provider/book/");
    
                    ContentValues values = new ContentValues();
                    values.put("price", 100);  //只更新标明的字段,其它字段值不会被修改
                    int updateRows = contentResolver.update(uri, values, "author=?", new String[]{"lao wai"});
    
                    Log.d("contentProvider-data", "影响行数:"+updateRows );
                }
            });
    
            //删除数据
            Button btn_delete = findViewById(R.id.btn_delete);
            btn_delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ContentResolver contentResolver = getContentResolver();
                    Uri uri = Uri.parse("content://com.example.databasedemo.provider/book/");
                    int deleteRows = contentResolver.delete(uri, "name=?", new String[]{"waibuchengxu-2"});
                    Log.d("contentProvider-data", "book/  影响行数:"+ deleteRows );
    
                    Log.d("contentProvider-data", "newBookId: " + newBookId);
                    Uri uriItem = Uri.parse("content://com.example.databasedemo.provider/book/" + newBookId);
                    int deleteItemRows = contentResolver.delete(uriItem, null, null);
    
                    Log.d("contentProvider-data", "book/id:影响行数:"+ deleteItemRows );
                }
            });
    
        }
    }
    
    

    2.3.1使用要点

    • 获取ContentResolverContentResolver contentResolver = getContentResolver();

    • 创建Uri:

      • 面向全表:Uri uri = Uri.parse("content://com.example.databasedemo.provider/book/");
      • 面向某行:Uri uri = Uri.parse("content://com.example.databasedemo.provider/book/id");
    • 增:Uri newUri = contentResolver.insert(uri,...);

    • 删:int rows =contentResolver.delete(uri,...);

    • 改:int rows = contentResolver.update(uri,...);

    • 查: Cursor cursor = contentResolver.query(uri,...);

  • 相关阅读:
    移动性能测试 | 持续集成中的 Android 稳定性测试
    iOS 测试 | iOS 自动化性能采集
    Google 测试总监聊如何经营成功的测试职业生涯
    浅谈一下可扩展性网站架构设计
    一条SQL执行慢的原因有哪些
    为什么在做微服务设计的时候需要DDD?
    是时候拥抱.NET CORE了
    MySql多表查询优化
    九种高性能可用高并发的技术架构
    HTTP协议总结
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/12592606.html
Copyright © 2020-2023  润新知