應用場景:html
在Android官方指出的Android的數據存儲方式總共有五種,分別是:Shared Preferences、網絡存儲、文件存儲、外儲存儲、SQLite。可是咱們知道通常這些存儲都只是在單獨的一個應用程序之中達到一個數據的共享,並且這些知識在前面我都有介紹,有時候咱們須要操做其餘應用程序的一些數據,例如咱們須要操做系統裏的媒體庫、通信錄等,這時咱們就可能經過ContentProvider來知足咱們的需求了java
ContentProvider概述:android
ContentProvider向咱們提供了咱們在應用程序以前共享數據的一種機制,而咱們知道每個應用程序都是運行在不一樣的應用程序的,數據和文件在不一樣應用程序之間達到數據的共享不是沒有可能,而是顯得比較複雜,而正好Android中的ContentProvider則達到了這一需求,好比有時候咱們須要操做手機裏的聯繫人,手機裏的多媒體等一些信息,咱們均可以用到這個ContentProvider來達到咱們所需。web
如何理解ContentProvidersql
上面說了一大堆ContentProvider的概述,可能你們仍是不太特別理解ContentProvider究竟是幹什麼的,那麼咱們以一個網站來形象的描述這個ContentProvider吧,能夠這麼理解爲ContentProvider就是一個網站,它向咱們去訪問網站這裏的數據達到了一種可能,它就是一個向外提供數據的接口。那麼既然它是向外提供數據,咱們有時候也須要去修改數據,這時咱們就能夠用到另一個類來實現這個對數據的修改ContentResolver類,這個類就能夠經過URI來操做數據。至於這些類的做用及描述在下面就會一一的介紹到。網絡
如何實現ContentProviderapp
理解了ContentProvider類,那麼咱們怎麼去實現ContentProvider呢?怎麼樣讓外部程序去訪問或者修改咱們的數據呢?這樣的一個操做實際上是很是簡單的,咱們只須要下面的兩步就能夠實現ContentProvideride
一、 編寫一個實現ContentProvider的在,這個子類必需要實現一些必須實現的方法,在ContentProvider類裏面,有一系列針對於數據的增、刪、改、查等方法工具
二、 ContentProvider也是Android中的四大組件,所以也必須在AndroidMainfest.xml中完成對ContentProvider的註冊。註冊方式爲:oop
與ContentProvider相關操做的類介紹
從Uri談起
什麼是Uri?
Uri是指通用資源標誌符
A:前綴代表數據受控於一個內容提供者。它從不修改,也就是schema
B:是指在AndroidMainfest.xml中咱們註冊的provider中的android:authorities屬性所對應的
C:具體操做於哪一個條目
D:具體指定到哪一個條目下的哪條記錄
再看它的類結構和經常使用方法:
Uri
在這個裏它是沒有構造方法的,它一般經過下面的這個方法來返回一個Uri對象
方法名稱 |
描述 |
public static Uri parse (String uriString) |
經過一個傳入的字符串來構造一個Uri對象 |
熟悉完Uri類再看與之相關的另外兩個類
UriMatcher類:
由於Uri表明了要操做的數據,因此咱們常常須要解析Uri,並從Uri中獲取數據。Android系統提供了兩個用於操做Uri的工具類,分別爲UriMatcher 和ContentUris 。掌握它們的使用,會便於咱們的開發工做。
先看下它比較經常使用的幾個方法:
方法名稱 |
描述 |
public void addURI (String authority, String path, int code) |
往UriMatcher類裏添加一個拼湊的Uri,在此咱們能夠理解爲UriMatcher爲一個Uri的容器,爲個容器裏面包含着咱們即將可能要操做的Uri,它用於咱們業務邏輯的處理,特別是第三個參數code,若是經過下面的match()方法匹配成功就返回這個code值 |
public int match (Uri uri) |
與傳入的Uri匹配,它會首先與找咱們以前經過addURI方法添加進來的Uri匹配,若是匹配成功就返回以前咱們設置的code值,不然返回一個UriMatcher.NO_MATCH常量值爲-1 |
熟悉完上面的方法,那麼咱們再來看它如何使用:
UriMatcher類用於匹配Uri,它的用法以下:
UriMatcher類的用法
首先第一步把你須要匹配Uri路徑所有給註冊上,以下:
//常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//若是match()方法匹配content:// com.jiahui.provider.myprovider/person路徑,返回匹配碼爲1
sMatcher.addURI(「com.jiahui.provider.myprovider」, 「person」, 1);//添加須要匹配uri,若是匹配就會返回匹配碼
//若是match()方法匹配content:// com.jiahui.provider.myprovider /person/230路徑,返回匹配碼爲2
sMatcher.addURI(「com.jiahui.provider.myprovider」, 「person/#」, 2);//#號爲通配符
switch (sMatcher.match(Uri.parse("content:// com.jiahui.provider.myprovider /person/10"))) {
case 1
break;
case 2
break;
default://不匹配
break;
}
註冊完須要匹配的Uri後,就可使用sMatcher.match(uri)方法對輸入的Uri進行匹配,若是匹配就返回匹配碼,匹配碼是調用addURI()方法傳入的第三個參數,假設匹配content://cn.itcast.provider.personprovider/person路徑,返回的匹配碼爲1
再看另一個工具類
ContentUris:
它用於在Uri後面追加一個ID或者解析出傳入的Uri所帶上的ID值,經常使用的兩個方法以下:
方法名稱 |
描述 |
public static Uri withAppendedId (Uri contentUri, long id) |
用於爲路徑加上ID部分 |
public static long parseId (Uri contentUri) |
從路徑中獲取ID部分 |
熟悉完上面所說起的相關的類,接下來咱們再看這個ContentProvider核心類
ContentProvider
經常使用方法
方法名稱 |
描述 |
public abstract boolean onCreate () |
在ContentProvider建立後被調用。 |
public abstract Uri insert (Uri uri, ContentValues values) |
根據Uri插入values對就的數據 |
public abstract int delete (Uri uri, String selection, String[] selectionArgs) |
根據Uri刪除selection指定的條件所匹配的所有記錄 |
public abstract int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) |
根據Uri修改selection指定的條件所匹配的所有記錄 |
public abstract Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) |
根據Uri查詢出selection指定的條件所匹配的所有記錄,而且能夠指定查詢哪些列(projection),以什麼方式(sortOrder)排序 |
public abstract String getType (Uri uri) |
返回當前Uri所數據的MIME類型,若是該Uri對應的數據可能包括多條記錄,那麼MIME類型字符串就是以vnd.android.cursor.dir/開頭,若是Uri對應的數據只包含一條記錄,那麼MIME類型字符串就是以vnd.android.cursor.item/開頭 |
既然咱們知道了ContentProvider類是向外提供數據的一種機制,那麼在以前咱們也說過要想來操做這個對外提供的數據,咱們就用到了另一個類:
ContentResolver
在這個類裏面也定義了一系列的增、刪、改、查方法,與其ContentProvider定義的方法基本上相同,在此再也不復核。讀者能夠本身查閱相關文檔。
可能你們在這裏仍是有點理不清這些類的一些關係,特別是ContentResolver與ContentProvider與Uri類的關係,那麼我上張圖吧,或許對你們有所幫助:
好了熟悉完上面所述的這麼多類那麼咱們就在實踐中見證真理吧:
實例:
實現效果:
代碼實現:
先開發咱們本身的ContentProvider:
- package com.jiahui.provider;
-
- import com.jiahui.db.DBHelper;
-
- 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;
-
- public class MyProvider extends ContentProvider {
-
- private DBHelper dbHelper;
- // 定義一個UriMatcher類
- private static final UriMatcher MATCHER = new UriMatcher(
- UriMatcher.NO_MATCH);
- private static final int PERSONS = 1;
- private static final int PERSON = 2;
- static {
- MATCHER.addURI("com.jiahui.provider.myprovider", "person", PERSONS);
- MATCHER.addURI("com.jiahui.provider.myprovider", "person/#", PERSON);
-
- }
- @Override
- public boolean onCreate() {
- System.out.println("---oncreate----");
- dbHelper = new DBHelper(this.getContext());
- return false;
- }
-
- // 查詢數據
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
-
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- switch (MATCHER.match(uri)) {
- case PERSONS:
- // 查詢全部的數據
- return db.query("person", projection, selection, selectionArgs,
- null, null, sortOrder);
-
- case PERSON:
- // 查詢某個ID的數據
- // 經過ContentUris這個工具類解釋出ID
- long id = ContentUris.parseId(uri);
- String where = " _id=" + id;
- if (!"".equals(selection) && selection != null) {
- where = selection + " and " + where;
-
- }
-
- return db.query("person", projection, where, selectionArgs, null,
- null, sortOrder);
- default:
-
- throw new IllegalArgumentException("unknow uri" + uri.toString());
- }
-
- }
-
- // 返回當前操做的數據的mimeType
- @Override
- public String getType(Uri uri) {
- switch (MATCHER.match(uri)) {
- case PERSONS:
- return "vnd.android.cursor.dir/person";
- case PERSON:
- return "vnd.android.cursor.item/person";
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- }
-
- // 插入數據
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- Uri insertUri = null;
- switch (MATCHER.match(uri)) {
- case PERSONS:
-
- long rowid = db.insert("person", "name", values);
- insertUri = ContentUris.withAppendedId(uri, rowid);
-
- break;
-
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- return insertUri;
- }
-
- // 刪除數據
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- int count = 0;
- switch (MATCHER.match(uri)) {
- case PERSONS:
- count = db.delete("person", selection, selectionArgs);
- return count;
-
- case PERSON:
- long id = ContentUris.parseId(uri);
- String where = "_id=" + id;
- if (selection != null && !"".equals(selection)) {
- where = selection + " and " + where;
- }
- count = db.delete("person", where, selectionArgs);
- return count;
-
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- }
-
- // 更新數據
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
-
- SQLiteDatabase db = dbHelper.getWritableDatabase();
-
- int count = 0;
- switch (MATCHER.match(uri)) {
- case PERSONS:
- count = db.update("person", values, selection, selectionArgs);
- break;
- case PERSON:
- // 經過ContentUri工具類獲得ID
- long id = ContentUris.parseId(uri);
- String where = "_id=" + id;
- if (selection != null && !"".equals(selection)) {
- where = selection + " and " + where;
- }
- count = db.update("person", values, where, selectionArgs);
- break;
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- return count;
- }
-
- }
千萬別忘記了要在AndroidMainfest.xml文件中註冊這個組件哦:
- <provider
- android:authorities="com.jiahui.provider.myprovider"
- android:name=".MyProvider" >
- </provider>
而後在一個主Activity編寫一些實現代碼:
- package com.jiahui.provider;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.Intent;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ListView;
- import android.widget.SimpleAdapter;
- import android.widget.Toast;
-
- import com.jiahui.model.Person;
-
- public class ContentProviderDemoActivity extends Activity {
-
- private Button btnadd, btnqueryall;
- private EditText edtname, edtage;
-
- private ListView lvall;
-
- private List<Person> persons;
- private SimpleAdapter simpleAdapter;
- private Handler handler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
-
- List<Map<String, Object>> data = (List<Map<String, Object>>) msg.obj;
-
- System.out.println(data.size());
-
-
- simpleAdapter = new SimpleAdapter(
- ContentProviderDemoActivity.this, data, R.layout.list_item,
- new String[] { "id", "name", "age" }, new int[] {
- R.id.tvId, R.id.tvname, R.id.tvage });
-
- lvall.setAdapter(simpleAdapter);
-
- }
-
- };
-
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- persons = new ArrayList<Person>();
-
- btnqueryall = (Button) this.findViewById(R.id.btnqueryall);
- btnadd = (Button) this.findViewById(R.id.btnadd);
- edtname = (EditText) this.findViewById(R.id.edtname);
- edtage = (EditText) this.findViewById(R.id.edtage);
- lvall = (ListView) this.findViewById(R.id.lvall);
-
- btnadd.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- ContentResolver contentResolver = ContentProviderDemoActivity.this
- .getContentResolver();
-
- Uri url = Uri
- .parse("content://com.jiahui.provider.myprovider/person");
- ContentValues values = new ContentValues();
- values.put("name", edtname.getText().toString());
- values.put("age", edtage.getText().toString());
- Uri result = contentResolver.insert(url, values);
-
- System.out.println(result.toString());
-
- if (ContentUris.parseId(result)>0) {
- Toast.makeText(ContentProviderDemoActivity.this, "添加成功", Toast.LENGTH_LONG).show();
- //添加成功後再啓動線程查詢
- MyThread thread = new MyThread(ContentProviderDemoActivity.this);
- thread.start();
- }
- }
- });
- //查詢全部
- btnqueryall.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- MyThread thread = new MyThread(ContentProviderDemoActivity.this);
- thread.start();
- }
- });
-
- lvall.setOnItemClickListener(new OnItemClickListener() {
-
- @Override
- public void onItemClick(AdapterView<?> parent, View view,
- int position, long id) {
- // Toast.makeText(ContentProviderDemoActivity.this, position,
- // Toast.LENGTH_LONG).show();
- System.out.println("position:" + position);
-
- Person person = persons.get(position);
- Bundle bundle = new Bundle();
- bundle.putInt("id", person.getId());
-
- bundle.putString("name", person.getName());
-
- bundle.putInt("age", person.getAge());
-
- Intent intent = new Intent(ContentProviderDemoActivity.this,
- ItemActivity.class);
- intent.putExtra("item", bundle);
- startActivityForResult(intent, 1);
-
- }
- });
-
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-
- if (resultCode==2) {
- MyThread thread = new MyThread(ContentProviderDemoActivity.this);
- thread.start();
-
- }
-
- }
-
-
- class MyThread extends Thread {
-
- Context context;
-
- public MyThread(Context context) {
- //必定要清空。不然會 有問題,每執行一次都會把以前的所有的item加進去
- persons.clear();
- lvall.setAdapter(null);
-
- this.context = context;
- }
-
- @Override
- public void run() {
-
- Uri url = Uri
- .parse("content://com.jiahui.provider.myprovider/person");
-
- Cursor cursor = context.getContentResolver().query(url,
- new String[] { "_id", "name", "age" }, null, null, "_id");
-
- while (cursor.moveToNext()) {
-
- // System.out.println("_id:"
- // + cursor.getInt(cursor.getColumnIndex("_id")));
- // System.out.println("name:"
- // + cursor.getString(cursor.getColumnIndex("name")));
- // System.out.println("age:"
- // + cursor.getInt(cursor.getColumnIndex("age")));
- Person person = new Person();
- person.setId(cursor.getInt(cursor.getColumnIndex("_id")));
- person.setName(cursor.getString(cursor.getColumnIndex("name")));
- person.setAge(cursor.getInt(cursor.getColumnIndex("age")));
- persons.add(person);
-
- }
-
- cursor.close();
-
- List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
-
- Map<String, Object> map=null;
- for (int i = 0; i < persons.size(); i++) {
-
- map = new HashMap<String, Object>();
-
- map.put("id", persons.get(i).getId());
- map.put("name", persons.get(i).getName());
-
- map.put("age", persons.get(i).getAge());
- data.add(map);
-
- }
- if (data.size()>=persons.size()) {
-
- }
- Message msg = handler.obtainMessage();
- msg.obj = data;
- handler.sendMessage(msg);
- }
-
- }
-
- }
ItemActivity代碼:
- package com.jiahui.provider;
-
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.content.Intent;
- import android.net.Uri;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.TextView;
- import android.widget.Toast;
-
- public class ItemActivity extends Activity {
-
- private EditText edt_item_name;
- private EditText edt_item_age;
- private EditText edt_item_id;
- private Button btndel, btnupdate;
-
- private Intent intent;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.item);
-
- edt_item_id = (EditText) this.findViewById(R.id.edt_item_id);
- edt_item_id.setEnabled(false);// 控制不可用
- edt_item_name = (EditText) this.findViewById(R.id.edt_item_name);
- edt_item_age = (EditText) this.findViewById(R.id.edt_item_age);
- // 獲得傳過來的數據
- btndel = (Button) this.findViewById(R.id.btndel);
- btnupdate = (Button) this.findViewById(R.id.btnupdate);
-
- intent = getIntent();
-
- Bundle bundle = intent.getBundleExtra("item");
-
- int id = bundle.getInt("id");
- System.out.println("id----" + id);
- String name = bundle.getString("name");
- int age = bundle.getInt("age");
-
- edt_item_id.setText(String.valueOf(id));
- edt_item_name.setText(name);
- edt_item_age.setText(String.valueOf(age));
-
- btndel.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- ContentResolver contentResolver = ItemActivity.this
- .getContentResolver();
- // 構建Uri
- String url = "content://com.jiahui.provider.myprovider/person/"
- + edt_item_id.getText();
- Uri uri = Uri.parse(url);
-
- int result = contentResolver.delete(uri, null, null);
- System.out.println("delete result:" + result);
-
- if (result >= 1) {
- Toast.makeText(ItemActivity.this, "刪除成功", Toast.LENGTH_LONG)
- .show();
- ItemActivity.this.setResult(2);
- ItemActivity.this.finish();
- }
-
- }
- });
-
- btnupdate.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- ContentResolver contentResolver = ItemActivity.this
- .getContentResolver();
- // 構建Uri
- String url = "content://com.jiahui.provider.myprovider/person/"
- + edt_item_id.getText();
- Uri uri = Uri.parse(url);
- ContentValues values = new ContentValues();
- values.put("name", edt_item_name.getText().toString());
- values.put("age",
- Integer.parseInt(edt_item_age.getText().toString()));
- int result = contentResolver.update(uri, values, null, null);
- System.out.println("update result:" + result);
- if (result >= 1) {
- Toast.makeText(ItemActivity.this, "更新成功", Toast.LENGTH_LONG)
- .show();
- ItemActivity.this.setResult(2);
- ItemActivity.this.finish();
- }
-
- }
- });
-
- }
-
- }
特別說明:這個例子也是與以前講過的一講與SQLite知識相關的代碼中一個類,讀者須要用到以前的DBHelper類,請自行拷貝。