Android ContentProvider 内容提供者

     ContentProvider 内容提供者,是Android四大组件之一。

一、简述

     可以理解为一个特殊的存储数据的类型,它提供了一套标准的接口来获取和操作数据。可以把数据封装到ContentProvider 中,从而是这些数据可以被其他的应用程序所共享。搭建起了所有应用程序之间数据交换的桥梁!
     1. 内容提供者可以将应用中的数据对外进行共享

  2.内容提供者将数据的访问方式统一,不必针对不同数据类型采取不同的访问策略

  3.内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据

  4.内容提供者中数据更改可被监听

二、创建内容提供者

   定义类继承ContentProvider,根据需要重写内部方法

     在清单文件的<application>节点下进行配置,<provider>标签中需要指定name和authorities属性

    name为类名,包名从程序Package开始,以“.”开始

    authorities:是访问Provider时的路径,要唯一

       URI代表要操作的数据,由scheme、authorites、path三部分组成

    content://com.bruce.contentprovider.demo/student

    scheme:固定为content,代表访问内容提供者

    authorites:<provider>节点中的authorites属性

    path:程序定义的路径,可根据业务逻辑定义

--------------------------------------------------------------------------------------------------

 <provider
            android:name="com.bruce.contentprovider.demo.MyContentProvider"
            android:authorities="com.bruce.contentprovider.demo"
            ></provider>

--------------------------------------------------------------------------------------------------

getType方法中:

?   如果返回数据是单条数据:vnd.android.cursor.item

?   如果返回数据是多条数据:vnd.android.cursor.dir

三、完成CRUD方法

?   当程序调用CRUD方法时会传入Uri, 我们通过Uri判断调用者要操作的数据,可以使用工具类UriMatcher来判断Uri,addURI方法可以添加Uri,match方法可以匹配一个Uri判断其类型;根据业务逻辑操作数据。

  1.onCreate() :初始化该ContentProvider
      2.query(Uri,String[],String,Sring[],String) :通过Uri进行查询,返回Uri
      3.intert(Uri,ContentValues):将数据插入到Uri所指定的位置
      4.update(Uri,ContentValues,String,String []):更新uri指定位置的数据
      5.delete(Uri,String,String[]):删除uri指定位置的数据
      6.getType(Uri):返回数据的类型
四、建立contentprovider工程,添加单元测试(http://www.cnblogs.com/kingshow123/p/sqlitecreate.html 中有介绍)
Android ContentProvider 内容提供者

五、创建DbOpenHelper类

Android ContentProvider 内容提供者
package com.bruce.contentprovider.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DbOpenHelper extends SQLiteOpenHelper {
    
    private static String name = "mycont.db";
    private static int version = 1;
    public DbOpenHelper(Context context) {
        super(context, name, null, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "create table student( id integer primary key autoincrement,name varchar(64),address varchar(64))";
        db.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
        // TODO Auto-generated method stub

    }

}
View Code

六、创建MyContentProvider类

Android ContentProvider 内容提供者
package com.bruce.contentprovider.demo;

import com.bruce.contentprovider.db.DbOpenHelper;

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 MyContentProvider extends ContentProvider {
    
    private DbOpenHelper helper;
    private final static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    private final static int STUDENT = 0;
    private final static int STUDENTS = 1;
    static{
        matcher.addURI("com.bruce.contentprovider.demo", "student/#", STUDENT); //单条记录
        matcher.addURI("com.bruce.contentprovider.demo", "student", STUDENTS);  //多条记录
    }
    
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int count = -1;
        SQLiteDatabase database = helper.getWritableDatabase();
        switch (matcher.match(uri)) {
        case STUDENT:
            long id = ContentUris.parseId(uri);
            selection = (selection == null ? " id = " + id : " id = " + id + " and " + selection);
            count = database.delete("student", selection, selectionArgs);
            break;
        case STUDENTS:
            count = database.delete("student", selection, selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("No match uri:" + uri);
        }
        return count;
    }

    @Override
    public String getType(Uri uri) {
        
        switch (matcher.match(uri)) {
        case STUDENT:
            return "vnd.android.cursor.item/student";
        case STUDENTS:
            return "vnd.android.cursor.dir/student";
        default:
            throw new IllegalArgumentException("No match uri:" + uri);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Uri resultUri = null;
        switch (matcher.match(uri)) {
        case STUDENTS:
            SQLiteDatabase database = helper.getWritableDatabase();
            long id = database.insert("student", null,values);
            resultUri = ContentUris.withAppendedId(uri, id);
            break;

        default:
            throw new IllegalArgumentException("No match uri:" + uri);
        }
        
        return resultUri;
    }

    @Override
    public boolean onCreate() {
        helper = new DbOpenHelper(getContext());
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor cursor = null;
        switch (matcher.match(uri)) {
        case STUDENT:
            long id = ContentUris.parseId(uri);
            selection = selection == null ? " id = " + id : " id = " + id + " and " + selection;
        case STUDENTS:
            SQLiteDatabase database = helper.getWritableDatabase();
            cursor = database.query("student", projection, selection, selectionArgs, null, null, sortOrder);
            break;
        default:
            throw new IllegalArgumentException("No match uri:" + uri);
        }
        return cursor;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        switch (matcher.match(uri)) {
        case STUDENT:
            long id = ContentUris.parseId(uri);
            selection = (selection == null ? " id = " + id : " id = " + id + " and " + selection);
        case STUDENTS:
            SQLiteDatabase database = helper.getWritableDatabase();
            return database.update("student", values, selection, selectionArgs); //directly return the number of rows affected
        default:
            throw new IllegalArgumentException("No match uri:" + uri);
        }
    }

}
View Code

七、创建MyTestProvider类

Android ContentProvider 内容提供者
package com.bruce.contentprovider.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;

public class MyTestProvider extends AndroidTestCase {
    
    private String TAG = "MyTestProvider";
    
    public void insertStudent(){
        ContentResolver resolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
        ContentValues values = new ContentValues();
        values.put("name", "姚明");
        values.put("address", "上海");
        Uri reUri = resolver.insert(uri, values);
        
        Cursor cursor = resolver.query(reUri, null, null, null, null);
        if(cursor.moveToNext()){
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String address = cursor.getString(2);
            Log.i(TAG, "-->test insert id:" + id + ",name:" + name + ",address:" + address);
        }
        
    }
    
    public void deleteStudent(){
        ContentResolver resolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/5");
        //String  selection = " name = ? ";
        //String[]  selectionArgs = {"姚明"};
        //int count = resolver.delete(uri, selection, selectionArgs);
        int count = resolver.delete(uri, null, null);
        Log.i(TAG, "-->test delete count=" + count);
        
    }
    
    public void updateStudent(){
        ContentResolver resolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/1");
        ContentValues values = new ContentValues();
        values.put("name", "邹市明");
        values.put("address","遵义");
        //String selection = " name = ? ";
        //String[] selectionArgs = {"老毛"};
        //int count = resolver.update(uri, values, selection, selectionArgs);
        int count = resolver.update(uri, values, null, null);
        Log.i(TAG, "-->test update count = " + count);
    }
    
    public void queryById(){
        ContentResolver resolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/1");
        Cursor cursor = resolver.query(uri, null, null, null, null);
        while(cursor.moveToNext()){
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String address = cursor.getString(2);
            Log.i(TAG, "--> test queryById id = " + id + ",name = " + name + ",address= " + address);
        }
    }
    
    public void queryByName(){
        Map<String, String> map = new HashMap<String, String>();
        ContentResolver resolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
        String selection = " name = ? ";
        String[] selectionArgs = {"姚明"};
        Cursor cursor = resolver.query(uri, null, selection, selectionArgs, null);
        int count = cursor.getColumnCount();
        while(cursor.moveToNext()){
            for(int i=0; i<count; i++){
                String cols_name = cursor.getColumnName(i);
                String cols_value = cursor.getString(cursor.getColumnIndex(cols_name));
                map.put(cols_name, cols_value);
            }
        }
        Log.i(TAG, "-->test queryByName:" + map.toString());
    }
    
    public void queryListStudent(){
        List<Map<String, String>> list = new ArrayList<Map<String,String>>();
        ContentResolver resolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
        Cursor cursor = resolver.query(uri, null, null, null, null);
        int count = cursor.getColumnCount();
        while(cursor.moveToNext()){
            Map<String, String> map = new HashMap<String, String>();
            for(int i=0; i<count; i++){
                String cols_name = cursor.getColumnName(i);
                String cols_value = cursor.getString(cursor.getColumnIndex(cols_name));
                map.put(cols_name, cols_value);
            }
            list.add(map);
        }
        Log.i(TAG, "-->test queryListStudent:" + list.toString());
    }
    
    public void testGetType(){
        ContentResolver resolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/1");
        Log.i(TAG, "-->testGetType plus id:" + resolver.getType(uri));
        
        uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
        Log.i(TAG, "-->testGetType:" + resolver.getType(uri));
    }
}
View Code

 八、监听内容提供者数据变化

?   在内容提供者中可以通知其他程序数据发生变化,通过Context的getContentResolver()方法获取ContentResolver,调用其notifyChange()方法发送数据修改通知;

?   在其他程序中可以通过ContentObserver监听数据变化

     通过Context的getContentResolver()方法获取ContentResolver

     调用其registerContentObserver()方法指定对某个Uri注册ContentObserver

     自定义ContentObserver,重写onChange()方法获取数据

 

发送修改通知:

Android ContentProvider 内容提供者
public Uri insert(Uri uri, ContentValues values) {
        Uri resultUri = null;
        switch (matcher.match(uri)) {
        case STUDENTS:
            SQLiteDatabase database = helper.getWritableDatabase();
            long id = database.insert("student", null,values);
            
            // Notify registered observers that a row was updated. 注册 observer 
            // @param observer The observer that originated the change, may be null            
            // 产生改变的Observer. 此处为Provider带来的改变,传 null
            this.getContext().getContentResolver().notifyChange(uri, null);// 发送修改通知
            
            //resultUri = Uri.parse("content://com.bruce.contentprovider.demo/student" + id);
            resultUri = ContentUris.withAppendedId(uri, id);
            break;

        default:
            throw new IllegalArgumentException("No match uri:" + uri);
        }
        
        return resultUri;
    }
View Code

 

 

也可以在其他应用中定义一个ContentObserver,监听Uri所对应的内容提供者的变化

Android ContentProvider 内容提供者
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //定义一个ContentObserver
        ContentObserver observer = new ContentObserver(new Handler()) {
        
             /**            
              * Returns true if this observer is interested in notifications for
              * changes made through the cursor the observer is registered with.            
              */           
            // 是否传递自己的改变
            @Override
            public boolean deliverSelfNotifications() {
                return super.deliverSelfNotifications();
            }

            // 当被监听的内容发生了改变时,调用该方法
            @Override
            public void onChange(boolean selfChange) {
                Log.i("MainActivity", "监听到了变化!!");
                //打印最后插入的信息
                ContentResolver resolver = getContentResolver();
                Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
                //select * from student order by id desc limit 1
                Cursor c = resolver.query(uri, null, null, null, " id desc limit 1");
                if(c.moveToNext()){
                    String string = "id="+ c.getInt(0) + ",name=" + c.getString(1) + ",address=" + c.getString(2);
                    Log.i("MainActivity", string);
                    Toast.makeText(MainActivity.this, string, 1).show();
                }
                //父类未做任何操作
                super.onChange(selfChange);
            }
            
        };
        Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
        getContentResolver().registerContentObserver(uri, true, observer);
    }
View Code

Android ContentProvider 内容提供者

上一篇:android项目各个文件详解


下一篇:Dapper基础用法