Android 數(shù)據(jù)存儲(chǔ)ContentProvider(類容提供者)之對(duì)外提供數(shù)據(jù)修改

Android鐘對(duì)數(shù)據(jù)的存儲(chǔ)與訪問(wèn)是很有必要的译打,在Android中對(duì)于數(shù)據(jù)存儲(chǔ)提供了如下幾種方法:

文件形式
SharedPreferences(參數(shù)-鍵值對(duì)形式)
SQLite數(shù)據(jù)庫(kù)(空間2T)
Content provider (Android組件-內(nèi)容提供者)
網(wǎng)絡(luò)(云存儲(chǔ))

這次寫的是Content provider (Android組件-內(nèi)容提供者)對(duì)外共享數(shù)據(jù)嘱蛋。將一個(gè)應(yīng)用中的數(shù)據(jù)庫(kù)通過(guò)ContentProvider共享給其他應(yīng)用,增剪验,刪苹祟,改显拳,查窿克。具體數(shù)據(jù)庫(kù)操作棕硫,請(qǐng)看上一篇

因?yàn)镃ontentProvider是Android四大組件之一髓涯,所以使用ContentProvider·是需要在清單文件AndroidManifest注冊(cè)的

  <!--authorities 是provider的唯一標(biāo)識(shí) ,name是要注冊(cè)的ContentProvider的路徑-->
        <provider
            android:authorities="com.example.administrator.foundationdemo.provider.PersonProvider"
            android:name="com.example.administrator.foundationdemo.provider.PersonProvider"/>

實(shí)現(xiàn)類PersonProvider代碼

package com.example.administrator.foundationdemo.provider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;

import com.example.administrator.foundationdemo.sqlite.service.MySQLite;

/**
 * Created by Administrator on 2016/12/14.
 */
public class PersonProvider extends ContentProvider {


    /** Uri講解:
     *  Uri代表要操作的數(shù)據(jù)哈扮,Uri主要包含了兩部分信息:
     *  1.需要操作的ContentProvider
     *  2.對(duì)ContentProvider中的什么數(shù)據(jù)進(jìn)行操作
     *  一個(gè)Uri由以下幾部分組成:
     *  content://com.example.administrator.foundationdemo.provider.PersonProvider/person/10
     *  |-scheme-|------------主機(jī)名或authority(唯一標(biāo)識(shí))----------------------|-路徑-|-ID-|
     *  ContentProvider(類容提供者)的scheme已經(jīng)由Android所規(guī)定纬纪,scheme為:content://
     *  主機(jī)名(或叫Authority)用于唯一標(biāo)識(shí)這個(gè)ContentProvider,外部調(diào)用者可以根據(jù)這個(gè)標(biāo)識(shí)找到他調(diào)用共享數(shù)據(jù)
     *  路徑(path)可以用來(lái)表示我們要操作的數(shù)據(jù)滑肉,路徑結(jié)構(gòu)根據(jù)實(shí)際情況而定包各,如下:
     *  要操作person表中id為10的記錄,可以這樣構(gòu)建路徑:/person/10
     *  要操作person表中id為10的記錄的name字段靶庙,可以這樣構(gòu)建路徑:/person/10/name
     *  要操作那個(gè)表XXX,那么機(jī)構(gòu)路徑就為:/XXX
     *  將字符串轉(zhuǎn)換成Uri
     *  調(diào)用方法:Uri uri = Uri.parse("string")
     */

    private MySQLite mySQLite;
    //用于判斷Uri是否匹配類
    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    //匹配碼
    private static final int PERSONS = 1;
    private static final int PERSON = 2;
    static {
        //添加待匹配的Uri    主機(jī)名(或叫Authority)                                         //路徑   匹配碼
        URI_MATCHER.addURI("com.example.administrator.foundationdemo.provider.PersonProvider","person",PERSONS);
        //添加待匹配的Uri    主機(jī)名(或叫Authority)                                         //路徑 #代表未知數(shù)字   匹配碼
        URI_MATCHER.addURI("com.example.administrator.foundationdemo.provider.PersonProvider","person/#",PERSON);
    }
    @Override
    public boolean onCreate() {
        //ContentProvider實(shí)例被創(chuàng)建時(shí)系統(tǒng)調(diào)用
        mySQLite = new MySQLite(this.getContext(),"mySQLite");
        return false;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] columns, String whereClause, String[] whereArgs, String orderBy) {
        //供外部應(yīng)用查詢ContentProvider內(nèi)的數(shù)據(jù)
        SQLiteDatabase db = mySQLite.getWritableDatabase();
        //操作ContentProvider數(shù)據(jù)前问畅,先判斷Uri是否匹配,判斷scheme與路徑是否是要操作的表的路徑
        switch (URI_MATCHER.match(uri)){
            case PERSONS:
                return db.query("person",columns, whereClause,whereArgs,null,null,orderBy);
            case PERSON:
                long rowid = ContentUris.parseId(uri);//獲取Uri中操作數(shù)據(jù)的ID
                String where = "personId="+rowid;//獲取操作數(shù)據(jù)庫(kù)的條件語(yǔ)句
                if (null == whereClause||"".equals(whereClause)){//判斷是否還有其他條件語(yǔ)句
                    where += " and "+ whereClause;//組拼條件語(yǔ)句
                }
                return db.query("person",columns, where,whereArgs,null,null,orderBy);
            default:
                throw new IllegalArgumentException("this id Unknown Uri "+uri);
        }
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        /**
         * 用于返回要操作數(shù)據(jù)MIME類型(類容類型)
         *   1六荒、如果操作的類型屬于集合類型數(shù)據(jù)护姆,那么MIME類型字符串應(yīng)該以‘vud.android.cursor.dir/’開(kāi)頭
         *      例如:如果要得到所有person記錄的Uri為:content://com.example.administrator.foundationdemo.provider.PersonProvider/person
         *            那么要返回的MIME類型字符串應(yīng)該為:vud.android.cursor.dir/person
         *   2、如果操作的類型屬于非集合類型數(shù)據(jù)恬吕,那么MIME類型字符串應(yīng)該以‘vud.android.cursor.item/’開(kāi)頭
         *      例如:如果要得到id為1的person記錄的Uri為:content://com.example.administrator.foundationdemo.provider.PersonProvider/person/1
         *            那么要返回的MIME類型字符串應(yīng)該為:vud.android.cursor.item/person
         */
        switch (URI_MATCHER.match(uri)){
            case PERSONS:
                return "vud.android.cursor.dir/person";
            case PERSON:
                return "vud.android.cursor.item/person";
            default:
                throw new IllegalArgumentException("this id Unknown Uri "+uri);
        }
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        //供外部應(yīng)用向ContentProvider內(nèi)插入數(shù)據(jù)
        SQLiteDatabase db = mySQLite.getWritableDatabase();
        //操作ContentProvider數(shù)據(jù)前签则,先判斷Uri是否匹配,判斷scheme與路徑是否是要操作的表的路徑
        switch (URI_MATCHER.match(uri)){
            case PERSONS:
                long rowid = db.insert("person","nsme",contentValues);//主鍵值
                //返回修改數(shù)據(jù)的Uri
                //方法一:手動(dòng)書寫(易錯(cuò))
                Uri insertUri = Uri.parse("content://com.example.administrator.foundationdemo.provider.PersonProvider/person/"+rowid);
                //方法二:Android提供API(推薦)
                insertUri = ContentUris.withAppendedId(uri,rowid);
                //設(shè)置數(shù)據(jù)的變化通知--> (uri,設(shè)置必須要的數(shù)據(jù)變化的監(jiān)聽(tīng)者)
                this.getContext().getContentResolver().notifyChange(uri,null);
                return insertUri;
            default:
                throw new IllegalArgumentException("this id Unknown Uri "+uri);
        }
    }

    @Override
    public int delete(Uri uri, String whereClause, String[] whereArgs) {
        //供外部應(yīng)用刪除ContentProvider內(nèi)的數(shù)據(jù)
        SQLiteDatabase db = mySQLite.getWritableDatabase();
        //操作記錄數(shù)
        int number = 0;
        //操作ContentProvider數(shù)據(jù)前铐料,先判斷Uri是否匹配渐裂,判斷scheme與路徑是否是要操作的表的路徑
        switch (URI_MATCHER.match(uri)){
            case PERSONS:
                number = db.delete("person",whereClause,whereArgs);
                break;
            case PERSON:
                long rowid = ContentUris.parseId(uri);//獲取Uri中操作數(shù)據(jù)的ID
                String where = "personId="+rowid;//獲取操作數(shù)據(jù)庫(kù)的條件語(yǔ)句
                if (null == whereClause||"".equals(whereClause)){//判斷是否還有其他條件語(yǔ)句
                    where += " and "+ whereClause;//組拼條件語(yǔ)句
                }
                number = db.delete("person",where,whereArgs);
                break;
            default:
                throw new IllegalArgumentException("this id Unknown Uri "+uri);
        }
        //返回操作記錄數(shù)
        return number;
    }

    @Override
    public int update(Uri uri, ContentValues contentValues, String whereClause, String[] whereArgs) {
        //供外部應(yīng)用更新ContentProvider內(nèi)的數(shù)據(jù)
        SQLiteDatabase db = mySQLite.getWritableDatabase();
        //操作記錄數(shù)
        int number = 0;
        //操作ContentProvider數(shù)據(jù)前,先判斷Uri是否匹配钠惩,判斷scheme與路徑是否是要操作的表的路徑
        switch (URI_MATCHER.match(uri)){
            case PERSONS:
                number = db.update("person", contentValues, whereClause,whereArgs);
                break;
            case PERSON:
                long rowid = ContentUris.parseId(uri);//獲取Uri中操作數(shù)據(jù)的ID
                String where = "personId="+rowid;//獲取操作數(shù)據(jù)庫(kù)的條件語(yǔ)句
                if (null == whereClause||"".equals(whereClause)){//判斷是否還有其他條件語(yǔ)句
                    where += " and "+ whereClause;//組拼條件語(yǔ)句
                }
                number = db.update("person",contentValues,where,whereArgs);
                break;
            default:
                throw new IllegalArgumentException("this id Unknown Uri "+uri);
        }
        //返回操作記錄數(shù)
        return number;
    }

}

監(jiān)聽(tīng)數(shù)據(jù)變化的SourceProviderActivity代碼

package com.example.administrator.foundationdemo.provider;

import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.example.administrator.foundationdemo.R;

public class SourceProviderActivity extends AppCompatActivity {

    //要監(jiān)聽(tīng)其變化的Uri
    private Uri uri = Uri.parse("content://com.example.administrator.foundationdemo.provider.PersonProvider/person");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_source_provider);
        //設(shè)置監(jiān)聽(tīng)器
        this.getContentResolver().registerContentObserver(uri,true,new PersonCotentObserver(new Handler()));
    }

    private class PersonCotentObserver extends ContentObserver{

        public PersonCotentObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {

            //是否是自己修改數(shù)據(jù)
            if (!selfChange){
                //select * from person order by personId decs limit 1
                Cursor cursor = getContentResolver().query(uri, null, null, null, "personId decs limit 1");
                if (cursor.moveToFirst()){
                     String name = cursor.getString(cursor.getColumnIndex("name"));
                    Log.d("FLY",name);
                }
            }
        }
    }
}

操作類ProviderActivity代碼:

package com.example.administrator.foundationdemo.provider;

import android.content.ContentResolver;
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 com.example.administrator.foundationdemo.R;

public class ProviderActivity extends AppCompatActivity {

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

    private void testInsert(){
        //別的應(yīng)用添加類容提供者數(shù)據(jù)需要代碼
        Uri uri = Uri.parse("content://com.example.administrator.foundationdemo.provider.PersonProvider/person");
        ContentResolver contentResolver = this.getContentResolver();
        ContentValues values = new ContentValues();
        values.put("name","laowang");
        values.put("phone", "12345678910");
        contentResolver.insert(uri, values);
    }
    private void testDelete(){
        //別的應(yīng)用添加類容提供者數(shù)據(jù)需要代碼
        Uri uri = Uri.parse("content://com.example.administrator.foundationdemo.provider.PersonProvider/person/1");
        ContentResolver contentResolver = this.getContentResolver();
        contentResolver.delete(uri, null, null);
    }
    private void testUpdate(){
        //別的應(yīng)用添加類容提供者數(shù)據(jù)需要代碼
        Uri uri = Uri.parse("content://com.example.administrator.foundationdemo.provider.PersonProvider/person/1");
        ContentResolver contentResolver = this.getContentResolver();
        ContentValues values = new ContentValues();
        values.put("name","xxxxx");
        contentResolver.update(uri, values, null, null);
    }
    private void testQuery(){
        //別的應(yīng)用添加類容提供者數(shù)據(jù)需要代碼
        Uri uri = Uri.parse("content://com.example.administrator.foundationdemo.provider.PersonProvider/person");
        ContentResolver contentResolver = this.getContentResolver();
                                 //所有字段所有類容 id升序排列
       Cursor cursor = contentResolver.query(uri, null, null, null, "personId asc");
        while (cursor.moveToNext()){
            String name = cursor.getString(cursor.getColumnIndex("name"));
            Log.d("FLY","name:"+name+"\n");
        }
        cursor.close();
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柒凉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子篓跛,更是在濱河造成了極大的恐慌膝捞,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愧沟,死亡現(xiàn)場(chǎng)離奇詭異蔬咬,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)沐寺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門林艘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人混坞,你說(shuō)我怎么就攤上這事狐援「痔梗” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵啥酱,是天一觀的道長(zhǎng)爹凹。 經(jīng)常有香客問(wèn)我,道長(zhǎng)镶殷,這世上最難降的妖魔是什么禾酱? 我笑而不...
    開(kāi)封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮批钠,結(jié)果婚禮上宇植,老公的妹妹穿的比我還像新娘。我一直安慰自己埋心,他們只是感情好指郁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著拷呆,像睡著了一般闲坎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茬斧,一...
    開(kāi)封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天腰懂,我揣著相機(jī)與錄音,去河邊找鬼项秉。 笑死绣溜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的娄蔼。 我是一名探鬼主播怖喻,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼岁诉!你這毒婦竟也來(lái)了锚沸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涕癣,失蹤者是張志新(化名)和其女友劉穎哗蜈,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坠韩,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡距潘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了只搁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绽昼。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖须蜗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤明肮,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布菱农,位于F島的核電站,受9級(jí)特大地震影響柿估,放射性物質(zhì)發(fā)生泄漏循未。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一秫舌、第九天 我趴在偏房一處隱蔽的房頂上張望的妖。 院中可真熱鬧,春花似錦足陨、人聲如沸嫂粟。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)星虹。三九已至,卻和暖如春镊讼,著一層夾襖步出監(jiān)牢的瞬間宽涌,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工蝶棋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卸亮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓玩裙,卻偏偏與公主長(zhǎng)得像兼贸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子献酗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容