1. 程式人生 > >Android ContentProvider數據共享

Android ContentProvider數據共享

轉換 沒有 生成 edi 變化 .get 完成 androi short

一、構造一個自己的Provider實現App之間數據共享

 1、我們先來了解一下 Uri(統一資源定位符) 

定義:每一個Content Provider使用一個公開的URI唯一標示其數據集,Android所提供的ContentProvider都存放android.provider包中  
結構:分為A、B、C、D四個部分

A:標準前綴,用來說明一個Content Provider控制這些數據,無法改變的; B:URI 的標識,唯一標識ContentProvider,外部調用者可以根據這個標識來找到它。為了保證URI標識的唯一性,它必須是一個完整的、小寫的類名。一般是定義該ContentProvider的包.類的名稱 C:路徑(path),通俗的講就是你要操作的數據庫中表的名字,或者你也可以自己定義,記得在使用的時候保持一致就可以了; D:如果URI中包含表示需要獲取的記錄的ID;則就返回該id對應的數據,如果沒有ID,就表示返回全部; "content://com.gdnf.provider/tablename/#" #表示數據id。

路徑
(path)可以用來表示我們要操作的數據,路徑的構建應根據業務而定,如下:
1、要操作person表中id為10的記錄,可以構建這樣的路徑:/person/10
2、要操作person表中id為10的記錄的name字段, person/10/name
3、要操作person表中的所有記錄,可以構建這樣的路徑:/person
4、當然要操作的數據不一定來自數據庫,也可以是文件、xml或網絡等其他存儲方式,如下:要操作xml文件中person節點下的name節點,可以構建這樣的路徑:/person/name
5、如果要把一個字符串轉換成Uri,可以使用Uri類中的parse()方法,如下:Uri uri = Uri.parse("content://com.bing.provider.personprovider/person")

 2、UriMatcher

UriMatcher主要用在ContentProvider中,用來構建URI匹配項和判斷Uri的正確性,如在insert之前先判斷用戶傳進來的Uri是否與UriMatcher定義的匹配。

 3、ContentUris

Long id=ContentUris.parseId(uri);取出URI中傳遞的ID
Uri uri=ContentUris.withAppendedId(uri,id);為Uri追加ID

4、案例代碼

package com.example.provider;

import android.content.ContentProvider;
import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.net.Uri; import android.support.annotation.Nullable; import com.example.dao.StuDao; /** * Created by Administrator on 2017/12/18. */ public class StuProvider extends ContentProvider { //定義authorities--這是表示Uri的“B部分”,獲取ContentProvider的包名 private static final String authorities="com.example.provider.stuprovider"; //構建UriMatcher對象(用於管理和匹配Uri) private static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH); //為每一個Uri定義一個編碼 //所有Stu的編碼為1 private static final int STUS=1; //一個Stu的編碼為2 private static final int STU=2; //根據姓名查找Stu的編碼為3 private static final int STU_NAME=3; //根據性別查找Stu的編碼為4 private static final int STU_SEX=4; //應用UriMatcher對象構建Uri匹配項 static{ //A部分默認為:content:。只需帶入B、C、D的值 matcher.addURI(authorities,"/stu",STUS); matcher.addURI(authorities,"/stu/#",STU); matcher.addURI(authorities,"/stu/#/name",STU_NAME); matcher.addURI(authorities,"/stu/#/sex",STU_SEX); } //聲明上下文 private Context context; @Override public boolean onCreate() { context=getContext(); return false; } @Nullable @Override public String getType(Uri uri) { if(matcher.match(uri)==STUS){ return "vnd.android.cursor.dir/stu"; }else if(matcher.match(uri)==STU){ return "vnd.android.cursor.item/stu"; } return null; } @Nullable @Override public Uri insert(Uri uri, ContentValues contentValues) { if(matcher.match(uri)==STUS){ long id=new StuDao(context).addStu(contentValues);//添加學生 Uri newUri=ContentUris.withAppendedId(uri,id); //發生了數據變化,給出一個通知信號 getContext().getContentResolver().notifyChange(uri,null); return newUri; } return null; } @Override public int delete(Uri uri, String s, String[] strings) { StuDao dao=new StuDao(context); switch (matcher.match(uri)){ case STUS: dao.delete("tb_stu",null,null); break; case STU: long id=ContentUris.parseId(uri);//從Uri裏面解析出Id dao.delete("tb_stu","_id="+id,null); break; } //發生了數據編號,給出一個通知信號 getContext().getContentResolver().notifyChange(uri,null); return 0; } @Override public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { StuDao dao=new StuDao(context); int i=-1; switch (matcher.match(uri)){ case STUS: i=dao.update("tb_stu",contentValues,s,strings); break; case STU: long id=ContentUris.parseId(uri);//從Uri裏面解析出Id i=dao.update("tb_stu",contentValues,"_id="+id,null); break; } //發生了數據編號,給出一個通知信號 getContext().getContentResolver().notifyChange(uri,null); return 0; } @Nullable @Override public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) { StuDao dao=new StuDao(context); Cursor cursor=null; switch (matcher.match(uri)){ case STUS: cursor=dao.queryStu(strings,s,strings1,null,null,s1,null); break; case STU: long id=ContentUris.parseId(uri);//從Uri裏面解析出Id cursor=dao.queryStu(strings,"_id="+id,null,null,null,s1,null); break; } return cursor; } }

二、在另一個程序中如何使用ContentResolver內容解析器進行數據操作

 1、ContentResolver操作ContentProvider中的數據

當外部應用需要對ContentProvider中的數據進行添加、刪除、修改和查詢操作時,可以使用ContentResolver 類來完成,要獲取ContentResolver 對象,可以使用getContentResolver()方法獲取ContentResolver對象

 2、監聽ContentProvider中數據的變化

如果ContentProvider的訪問者需要監聽ContentProvider中的數據變化,可以註冊一個觀察者getContentResolver().registerContentObserver(uri,bool,observer)

 3、數據提供者在數據發生改變時發出消息

getContent().getContentResolver().notifyChange(uri,null)

 4、案例代碼

package com.example.android_contentprover_test;

import android.app.Activity;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

    //定義一個ContentResolver內容解析器
    private ContentResolver resolver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //獲取系統的ContentResolver對象
        resolver=getContentResolver();
        //為resolver添加一個監聽事件,監聽數據是否發生變化
        Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
        resolver.registerContentObserver(uri,true,new StuObServer(handler));
    }

    //構建一個handler對象執行數據操作
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==1){
                //為所欲為
                findStuList(null);//執行查詢
            }
        }
    };

    //構建一個觀察者類
    private class StuObServer extends ContentObserver{

        private Handler handler;
        public StuObServer(Handler handler) {
            super(handler);
            this.handler=handler;
        }
        //當發生改變時
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            //監聽到數據發生改變時,發出一個編號為1的消息
            handler.sendEmptyMessage(1);
        }
    }

    public void addStu(View view){
        //聲明數據來源——路徑
        Uri addUri=Uri.parse("content://com.example.provider.stuprovider/stu");
        //創建一個數據對象
        ContentValues values=new ContentValues();
        values.put("sname","Join");
        values.put("sage",21);
        values.put("ssex","男");
        //使用內容解析器執行添加(參數為:數據的來源,更改的數據)
        Uri newUri=resolver.insert(addUri,values);
        //通過解析器得到更改數據的ID
        long id= ContentUris.parseId(newUri);
        Toast.makeText(this, "添加學生成功,ID="+id, Toast.LENGTH_SHORT).show();

        //使用內容解析器調用查詢方法,查詢數據
        Cursor cursor=resolver.query(newUri,null,null,null,null);
        if(cursor.moveToNext()){
            int _id=cursor.getInt(cursor.getColumnIndex("_id"));
            String name=cursor.getString(cursor.getColumnIndex("sname"));
            Toast.makeText(this, "ID="+_id+",Name="+name, Toast.LENGTH_SHORT).show();
        }
        cursor.close();
    }

    public void findStuList(View view){
        Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
        Cursor cursor=resolver.query(uri,null,null,null,null);
        while(cursor.moveToNext()){
            int _id=cursor.getInt(cursor.getColumnIndex("_id"));
            String name=cursor.getString(cursor.getColumnIndex("sname"));
            Log.i("App1 StuList", "ID="+_id+",Name="+name);
        }
        cursor.close();
    }
}

Android ContentProvider數據共享