Android—ContentProvider运用

创建内容提供器实现跨程序数据共享

主要实现步骤:
1、新建一个MyContentProvider类继承自ContentProvider。
2、MyContentProvider类中5个必须实现的方法的逻辑实现,
3、内容提供器的注册。

打字真是太费劲了,,下面把代码直接粘进来啦。。。。。。

public class MyContentProvider extends ContentProvider {


    public static final int TABLE1_DIR = 0;//访问table1表中的所有数据

    public static final int TABLE1_ITEM = 1;//访问table1表中的单条数据

    public static final int TABLE2_DIR = 2;//访问table2表中的所有数据

    public static final int TABLE2_ITEM = 3;//访问table2表中的单条数据

    private static UriMatcher uriMatcher;

    private MyDataBaseHelper myDataBaseHelper;


    //讲台代码块中uriMatcher初始化操作
    static {

        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI("com.example.adiqueen.contentprovidertest","table1",TABLE1_DIR);
        uriMatcher.addURI("com.example.adiqueen.contentprovidertest","table1/#",TABLE1_ITEM);
        uriMatcher.addURI("com.example.adiqueen.contentprovidertest","table2",TABLE2_DIR);
        uriMatcher.addURI("com.example.adiqueen.contentprovidertest","table2/#",TABLE2_ITEM);

    }


    @Override
    public boolean onCreate() {

        //创建了一个MyDataBaseHelper实例,并返回true 表示内容提供起初始化完成
        //这个时候数据库已经完成了创建和升级的操作
        myDataBaseHelper = new MyDataBaseHelper(getContext(),"BookStore.db",null,2);

        return true;
    }


    @SuppressLint("Recycle")
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {

        //查询数据
        SQLiteDatabase db = myDataBaseHelper.getReadableDatabase();

        Cursor cursor = null;

        switch (uriMatcher.match(uri)){

            case TABLE1_DIR:

                //查询table1表中的所有数据
                cursor = db.query("table1",strings, s, strings1, null, null, s1);

                break;

            case TABLE1_ITEM:

                //查询table1表中的单条数据
                String table1Id = uri.getPathSegments().get(1);
                cursor = db.query("table1",strings, "id = ?", new String[]{table1Id}, null, null, s1);

                break;

            case TABLE2_DIR:

                //查询table2表中的所有数据
                cursor = db.query("table2",strings, s, strings1, null, null, s1);

                break;

            case TABLE2_ITEM:
                //查询table2表中的单条数据
                String table2Id = uri.getPathSegments().get(1);
                cursor = db.query("table2",strings, "id = ?", new String[]{table2Id}, null, null, s1);

                break;

            default:
                break;

        }

        return null;
    }


    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {

        SQLiteDatabase db = myDataBaseHelper.getReadableDatabase();

        Uri uriReturn = null;

        switch (uriMatcher.match(uri)){

            case TABLE1_DIR:
            case TABLE1_ITEM:
                 long newBookId = db.insert("table1",null,contentValues);

                uriReturn = Uri.parse("content://com.example.adiqueen.contentprovidertest.provider/table1/"+newBookId);

                break;
            case TABLE2_DIR:
            case TABLE2_ITEM:

                long newBookId1 = db.insert("table2",null,contentValues);

                uriReturn = Uri.parse("content://com.example.adiqueen.contentprovidertest.provider/table2/"+newBookId1);

            default:
                    break;
        }




        return uriReturn;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {

        SQLiteDatabase db = myDataBaseHelper.getReadableDatabase();

        int updateRows = 0;

        switch (uriMatcher.match(uri)){

            case TABLE1_DIR:

                updateRows = db.update("table1",contentValues,s,strings);
                break;

            case TABLE1_ITEM:

                String table1Id = uri.getPathSegments().get(1);

                updateRows = db.update("table1",contentValues,"id = ?",new String[]{table1Id});


                break;

            case TABLE2_DIR:
                updateRows = db.update("table2",contentValues,s,strings);

                break;

            case TABLE2_ITEM:

                String table2Id = uri.getPathSegments().get(1);

                updateRows = db.update("table2",contentValues,"id = ?",new String[]{table2Id});

                break;

            default:

                    break;

        }

        return updateRows;
    }



    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {

        SQLiteDatabase db = myDataBaseHelper.getReadableDatabase();

        int deleteRows = 0;

        switch (uriMatcher.match(uri)){

            case TABLE1_DIR:

                deleteRows = db.delete("table1",s,strings);
                break;

            case TABLE1_ITEM:

                String table1Id = uri.getPathSegments().get(1);

                deleteRows = db.delete("table1","id = ?",new String[]{table1Id});


                break;

            case TABLE2_DIR:

                deleteRows = db.delete("table2",s,strings);

                break;

            case TABLE2_ITEM:

                String table2Id = uri.getPathSegments().get(1);

                deleteRows = db.delete("table2","id = ?",new String[]{table2Id});

                break;

            default:

                break;
        }

        return deleteRows;
    }


    /*
    * getType()方法是所有的内容提供起都必须实现的一个方法,用于获取Uri对象所对应的MIME类型
    * 一个Uri对象所对应的MIME类型主要有3部分组成,Android对这3部分内容做了如下规定
    *
    * 1、必须以vnd开头
    * 2、如果内容URI以路径结尾,则后接android.curser.dir/,如果内容URI以id结尾则后接android.curser.item/
    * 3、最后接上vnd.<authority>.<path>
    *
    * 所以,对于content://com.example.adiqueen.contentprovidertest.provider/table1这个内容Uri所对应的MIME类型为
    * vnd.android.curser.dir/vnd.com.example.adiqueen.contentprovidertest.provider/table1
    *
    * 所以,对于content://com.example.adiqueen.contentprovidertest.provider/table1/1这个内容Uri所对应的MIME类型为
    * vnd.android.curser.item/vnd.com.example.adiqueen.contentprovidertest.provider/table1
    *
    *
    * */

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {

        switch (uriMatcher.match(uri)){

            case TABLE1_DIR:

                return "vnd.android.curser.dir/vnd.com.example.adiqueen.contentprovidertest.provider/table1";

            case TABLE1_ITEM:

                return "vnd.android.curser.item/vnd.com.example.adiqueen.contentprovidertest.provider/table1";


            case TABLE2_DIR:

                return "vnd.android.curser.dir/vnd.com.example.adiqueen.contentprovidertest.provider/table2";


            case TABLE2_ITEM:

                return "vnd.android.curser.item/vnd.com.example.adiqueen.contentprovidertest.provider/table2";


            default:

                break;
        }

        return null;
    }
}

MyDataBaseHelper是我们在之前的学习内容中用到的一个类,继承自 SQLiteOpenHelper的类。在此不错过多的解释。不过针对以上内容,有一些细节需要提一下。

可以看到每一个方法都有Uri参数,这个参数正是ContentProvider调用增删改查方法所传递过来的参数。
下面我们对Uri参数进行分析,分析出调用放想要访问的表和数据
回顾一下,一个标准的URI的写法是这样的
content:/ /com.example.adiqueen.contentprovidertest.provider/table1

这就表示调用方期望访问的是com.example.adiqueen.contentprovidertest这个应用的表table1中的数据

除此之外,我们还可以在这个URI的后面增加一个id

content:/ /com.example.adiqueen.contentprovidertest.provider/table1/1
这就表示调用方期望访问的是com.example.adiqueen.contentprovidertest这个应用的表table1中的id为1的数据

内容URI的格式主要就只有以上两种,以路径结尾就表示调用方期望访问该表中的所有数据,以id结尾的表示调用方期望访问该表中对应于id的数据我们可以使用通配符的方式来分别匹配以上两种格式的内容URI:

""表示匹配任意长度的任意字符 下面的写法是匹配任意表的内容
content:/ /com.example.adiqueen.contentprovidertest.provider/

"#"表示匹配任意长度的数字 下面的写法是匹配table1表中任意行的内容
content:/ /com.example.adiqueen.contentprovidertest.provider/table1/#

最后一步是注册, 在manifest中增加<provider>及内容

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.adiqueen.contentprovidertest">

    <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">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <provider
            android:authorities="com.example.adiqueen.contentprovidertest.provider"
            android:name=".MyContentProvider"
            android:enabled="true"
            android:exported="true"
            />
        
    </application>

</manifest>
访问内容提供器、实现增删改查

我们需要新建一个项目AccessProviderTest来访问ContentProviderTest中的内容提供器,实现对其内容的增删改查功能。

public class MainActivity extends AppCompatActivity {


    //增删改查按钮
    private Button add;
    private Button delete;
    private Button update;
    private Button query;

    private String newId;

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


        add = (Button)findViewById(R.id.add);
        delete = (Button)findViewById(R.id.delete);
        update = (Button)findViewById(R.id.update);
        query = (Button)findViewById(R.id.query);


        //添加数据
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Uri uri = Uri.parse("content://com.example.adiqueen.contentprovidertest.provider/table1");

                ContentValues values = new ContentValues();
                values.put("name","心理学导论");
                values.put("price",22.5);
                values.put("author","王先生");
                values.put("pages",326);

                Uri uri1 = getContentResolver().insert(uri,values);
                newId = uri1.getPathSegments().get(1);
            }
        });

        //删除数据
        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Uri uri = Uri.parse("content://com.example.adiqueen.contentprovidertest.provider/table1/"+newId);

                getContentResolver().delete(uri,null,null);


            }
        });

        //更改数据
        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Uri uri = Uri.parse("content://com.example.adiqueen.contentprovidertest.provider/table1/"+newId);

                ContentValues values = new ContentValues();
                values.put("name","高等化学");
                values.put("price",88.88);
                values.put("author","Liu先生");

                getContentResolver().update(uri,values,null,null);

            }
        });

        //查询数据
        query.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Uri uri = Uri.parse("content://com.example.adiqueen.contentprovidertest.provider/table1");

                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"));

                        double price = cursor.getDouble(cursor.getColumnIndex("price"));

                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));

                        Log.d("","name="+name+" author="+author+" price="+price+" pages="+pages);

                    }

                    cursor.close();
                }
            }
        });
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269