美文网首页Android开发Android开发Android开发经验谈
Content Provider 之 最终弹 实战体验跨程序

Content Provider 之 最终弹 实战体验跨程序

作者: 凌川江雪 | 来源:发表于2018-08-29 01:19 被阅读12次

    本模块共有四篇文章,参考郭神的《第一行代码》,对Content Provider的学习做一个详细的笔记,大家可以一起交流一下:


    简单起见,我们还是在之前的DatabaseTest项目(点击前往码云地址)的基础上继续开发。
    需求是:通过内容提供器来给它加人外部访问接口。

    程序设计的步骤:

    1.在A程序中注册内容提供器,写好接口处理方法;
          具体的,全局变量:定义自定义代码常量,定义authority常量,声明uriMatcher和DatabaseHelper对象;
          1.1 内容提供器中增删改查的程序设计步骤为:
                1.1.1  调用实例化DatabaseHelper的get方法获得SQLiteDatabase实例化对象;
                          (get方法即getWritableDatabase或者getReadableDatabase)
                1.1.2   接着,query需定义一个Cursor对象(cursor)用于接收返回结果;
                                      insert需定义一个Uri对象(urireturn)用于接收insert新增的数据行的uri
                                      update需定义一个int对象(updatedRows)用于接收受影响的行数;
                                      delete需定义一个int对象(deletedRows)用于接收受影响的行数(被删除的行数);
                1.1.3  使用switch语句进行对uri的判断及判断结果的处理;
    2.在需要访问A程序的内容提供器的程序中,构建对应的Uri,通过getContentResolver调用增删改查即可;
    


    下面开始详细解析:
    打开DatabaseTest项目(点击前往码云地址),首先将MyDatabaseHelper中使用Toast弹出创建数据库成功的提示去除掉,因为跨程序访问时我们不能直接使用Toast(!!!!!)。然后创建一个内容提供器,右击com.example.databasetest包—New—Other—ContentProvider,



    会弹出如图所示:


    package com.example.databasetest;
    
    import android.content.ContentProvider;
    import android.content.ContentValues;
    import android.content.UriMatcher;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.net.Uri;
    
    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);          //插入后返回一个id!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);//id构造用于返回的URI!!!!!!!!!!!!!!!!!!!!!!
                    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().get(1)的解释参考:



    <?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/add_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Add To Book" />
    
        <Button
            android:id="@+id/query_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Query From Book" />
    
        <Button
            android:id="@+id/update_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Update Book" />
    
        <Button
            android:id="@+id/delete_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Delete From Book" />
    
    </LinearLayout>
    

    MainActivity.java:

    package com.example.providertest;
    
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
    
        private String newId;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button addData = (Button) findViewById(R.id.add_data);
            addData.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", "A Clash of Kings");
                    values.put("author", "George Martin");
                    values.put("pages", 1040);
                    values.put("price", 55.55);
                    Uri newUri = getContentResolver().insert(uri, values);
                    newId = newUri.getPathSegments().get(1);
                }
            });
            Button queryData = (Button) findViewById(R.id.query_data);
            queryData.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("MainActivity", "book name is " + name);
                            Log.d("MainActivity", "book author is " + author);
                            Log.d("MainActivity", "book pages is " + pages);
                            Log.d("MainActivity", "book price is " + price);
                        }
                        cursor.close();
                    }
                }
            });
            Button updateData = (Button) findViewById(R.id.update_data);
            updateData.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", "A Storm of Swords");
                    values.put("pages", 1216);
                    values.put("price", 24.05);
                    getContentResolver().update(uri, values, null, null);
                }
            });
            Button deleteData = (Button) findViewById(R.id.delete_data);
            deleteData.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);
                }
            });
        }
    }
    

    其中值得注意的是:

    从以上代码中,我们可以看到DIR类型常量匹配的,selection, selectionArgs参数位是由调用本内容提供器的时候由调用方程序提供的,
    ITEM则不同,uri中已经包含了ID,我们可以使用getPathSegments将之get出来再使用,即ITEM类型常量匹配的,调用方程序无需提供selection, selectionArgs参数位(如下方的代码截图),uri中已经包含了信息,处理方法也在内容提供器中写好了。
    (这一点在调用getContentResolver().update()以及getContentResolver().delete()的时候都一样)

    下面进行代码的简析:


    现在运行一下ProviderTest项目,效果图如下:

    这里可以看到DatabaseTest程序中只有我们刚刚添加的一条数据,
    databaseTest的SQLite数据库是我们在点击Add To Book的时候,试图访问DatabaseTest的内容提供器,由此DatabaseTest的内容提供器(DatabaseProvider)会触发DatabaseProvider.java中的onCreate()方法,如下,
    由此创建了数据库,并返回True,这一点在 跨程序共享数据——Content Provider 之 创建自己的内容提供器中曾经有提及;
    创建了数据库之后,便添加了添加了一条数据,由此DatabaseTest程序中只有我们刚刚添加的那一条数据而已。

    最后点击Delete From Book按钮删除数据,此时再点击Query From Book按钮就查询不到数据了。

    由此可以看出,我们的跨程序共享数据功能已经成功实现了!

    现在不仅是ProviderTest程序,任何一个程序都可以轻松访问DatabaseTest中的数据,而且我们还丝毫不用担心隐私数据泄漏的问题。

    相关文章

      网友评论

        本文标题:Content Provider 之 最终弹 实战体验跨程序

        本文链接:https://www.haomeiwen.com/subject/lmgcwftx.html