黑马程序员_android笔记4

来源:互联网 发布:mysql client for mac 编辑:程序博客网 时间:2024/06/03 22:46

---------------------- android培训、java培训、期待与您交流! ----------------------


4. 使用内容提供者(ContentProvider)在程序中共享数据:

 使用内容提供者需继承继承ContentProvider类,使用ContentProvider共享数据的好处是统一了数据访问方式。

当应用需要通过ContentProvider对外共享数据时(对于组件类的类必须放在应用包或者其子包下),第一步需要新建一个类继承ContentProvider并重写下面方法(可以实现空方法已屏蔽某些功能):

public class PersonContentProvider extends ContentProvider{

   public boolean onCreate()// Called when the provider is being started.

   public Uri insert(Uri uri, ContentValues values)

   public int delete(Uri uri, String selection, String[] selectionArgs)

   public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

   public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

   public String getType(Uri uri)}

public String getType(Uri uri)

该方法用于返回当前Url所代表数据的MIME类型。如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,例如:要得到所有person记录的Uri为content://cn.itcast.provider.personprovider/person,那么返回的MIME类型字符串应该为:“vnd.android.cursor.dir/person”。如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,例如:得到id为10的person记录,Uri为content://cn.itcast.provider.personprovider/person/10,那么返回的MIME类型字符串应该为:“vnd.android.cursor.item/person”。

第二步需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配置,为了能让其他应用找到该ContentProvider , ContentProvider 采用了authorities(主机名/域名)对它进行唯一标识,你可以把 ContentProvider看作是一个网站(想想,网站也是提供数据者),authorities 就是他的域名:

<manifest .... >

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <provider android:name=".PersonContentProvider" android:authorities="cn.itcast.providers.personprovider"/>

    </application>

</manifest>

注意:一旦应用继承了ContentProvider类,后面我们就会把这个应用称为ContentProvider(内容提供者)。

示例:

person代表数据库表。

import cn.itcast.service.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 PersonProvider extends ContentProvider {

private DBOpenHelper dbOpenHelper;

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("cn.itcast.providers.personprovider", "person", PERSONS);

MATCHER.addURI("cn.itcast.providers.personprovider", "person/#", PERSON); }

//删除person表中的所有记录   /person

//删除person表中指定id的记录 /person/10

public int delete(Uri uri, String selection, String[] selectionArgs) {

SQLiteDatabase db = dbOpenHelper.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 = "personid="+ 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()); }}

public String getType(Uri uri) {//返回当前操作的数据的mimeType

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()); }

}

public Uri insert(Uri uri, ContentValues values) {// /person

SQLiteDatabase db = dbOpenHelper.getWritableDatabase();

switch (MATCHER.match(uri)) {

case PERSONS:

long rowid = db.insert("person", "name", values); 

Uri insertUri = ContentUris.withAppendedId(uri, rowid);

//当person表中得数据发送变化时,发出通知,这个通知只能被监听uri的应用捕获,下

//有专门的应用程式代码

            this.getContext().getContentResolver().notifyChange(uri, null);

return insertUri;

default:

throw new IllegalArgumentException("Unkwon Uri:"+ uri.toString()); }}

public boolean onCreate() {

this.dbOpenHelper = new DBOpenHelper(this.getContext());

return false; }

//查询person表中的所有记录   /person

//查询person表中指定id的记录 /person/10

public Cursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder) {

SQLiteDatabase db = dbOpenHelper.getReadableDatabase();

switch (MATCHER.match(uri)) {

case PERSONS:

return db.query("person", projection, selection, selectionArgs, null, null, sortOrder);

case PERSON:

long id = ContentUris.parseId(uri);

String where = "personid="+ id;

if(selection!=null && !"".equals(selection)){

where = selection + " and " + where; }

return db.query("person", projection, where, selectionArgs, null, null, sortOrder);

default:

throw new IllegalArgumentException("Unkwon Uri:"+ uri.toString()); }}

//更新person表中的所有记录   /person

//更新person表中指定id的记录 /person/10

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

SQLiteDatabase db = dbOpenHelper.getWritableDatabase();

int count = 0;

switch (MATCHER.match(uri)) {

case PERSONS:

count = db.update("person", values, selection, selectionArgs);

return count;

case PERSON:

long id = ContentUris.parseId(uri);

String where = "personid="+ id;

if(selection!=null && !"".equals(selection)){

where = selection + " and " + where; }

count = db.update("person", values, where, selectionArgs);

return count;

default:

throw new IllegalArgumentException("Unkwon Uri:"+ uri.toString());

}}}

测试:

先部署运行内容提供者所在应用,再在其他应用中编写测试类,并运行。

当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver 类提供了与ContentProvider类相同签名的方法:

public Uri insert(Uri uri, ContentValues values)

public int delete(Uri uri, String selection, String[] selectionArgs)

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

public String getType(Uri uri)

这些方法的第一个参数为Uri,代表要操作的ContentProvider和对其中的什么数据进行操作,假设给定的是: Uri.parse(“content://cn.itcast.providers.personprovider/person/10”),那么将会对名为cn.itcast.providers.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。

测试类如下:

import android.content.ContentResolver;

import android.content.ContentValues;

import android.database.Cursor;

import android.net.Uri;

import android.test.AndroidTestCase;

public class AccessContentProviderTest extends AndroidTestCase {

private static final String TAG = "AccessContentProviderTest";

public void testInsert() throws Throwable{

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri insertUri = Uri.parse("content://cn.itcast.providers.personprovider/person");

ContentValues values = new ContentValues();

values.put("name", "zhangxiaoxiao");

values.put("amount", 90);

Uri uri = contentResolver.insert(insertUri, values);

Log.i(TAG, uri.toString());}

public void testUpdate() throws Throwable{

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri updateUri = Uri.parse("content://cn.itcast.providers.personprovider/person/1");

ContentValues values = new ContentValues();

values.put("name", "lili");

contentResolver.update(updateUri, values, null, null); }

public void testDelete() throws Throwable{

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri deleteUri = Uri.parse("content://cn.itcast.providers.personprovider/person/1");

contentResolver.delete(deleteUri, null, null); }

public void testFind() throws Throwable{

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri selectUri = Uri.parse("content://cn.itcast.providers.personprovider/person");

Cursor cursor = contentResolver.query(selectUri, null, null, null, "personid desc");

while(cursor.moveToNext()){

int id = cursor.getInt(cursor.getColumnIndex("personid"));

String name = cursor.getString(cursor.getColumnIndex("name"));

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

Log.i(TAG, "id="+ id + ",name="+ name+ ",amount="+ amount);}}}

内容提供者数据改变监听应用:

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);        

        Uri insertUri = Uri.parse("content://cn.itcast.providers.personprovider/person");

        ContentResolver contentResolver = this.getContentResolver();

        //对指定uri进行监听,如果该uri代表的数据发生变化,就会调用PersonObserver中的//onChange(),将重新获得的数据输出到日志上

        contentResolver.registerContentObserver(insertUri, true, new PersonObserver(new Handler()));    }    

    private final class PersonObserver extends ContentObserver{

public PersonObserver(Handler handler) {

super(handler);

}

public void onChange(boolean selfChange) {

ContentResolver contentResolver = getContentResolver();

Uri selectUri = Uri.parse("content://cn.itcast.providers.personprovider/person");

Cursor cursor = contentResolver.query(selectUri, null, null, null, "personid desc");

while(cursor.moveToNext()){

int id = cursor.getInt(cursor.getColumnIndex("personid"));

String name = cursor.getString(cursor.getColumnIndex("name"));

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

Log.i(TAG, "id="+ id + ",name="+ name+ ",amount="+ amount);

} }    }

5、内容提供者Uri知识

Uri代表了要操作的数据,Uri主要包含了两部分信息:1》需要操作的ContentProvider ,2》对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:

ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://

主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。

路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:

要操作person表中id为10的记录,可以构建这样的路径:/person/10

要操作person表中id为10的记录的name字段, person/10/name

要操作person表中的所有记录,可以构建这样的路径:/person

要操作xxx表中的记录,可以构建这样的路径:/xxx

当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:

要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name

如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:

Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")

因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。

UriMatcher类用于匹配Uri,它的用法如下:

首先第一步把你需要匹配Uri路径全部给注册上,如下:

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码

UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

//如果match()方法匹配content://cn.itcast.provider.personprovider/person路径,返回匹配码为1

sMatcher.addURI(“cn.itcast.provider.personprovider”, “person”, 1);//添加需要匹配uri,如果匹配就会返回匹配码

//如果match()方法匹配content://cn.itcast.provider.personprovider/person/230路径,返回匹配码为2

sMatcher.addURI(“cn.itcast.provider.personprovider”, “person/#”, 2);//#号为通配符

switch (sMatcher.match(Uri.parse("content://cn.itcast.provider.personprovider/person/10"))) { 

   case 1

    break;

   case 2

    break;

   default://不匹配

    break;}

注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数。

ContentUris类用于获取Uri路径后面的ID部分,它有两个比较实用的方法:

withAppendedId(uri, id)用于为路径加上ID部分:

Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")

Uri resultUri = ContentUris.withAppendedId(uri, 10); 

//生成后的Uri为:content://cn.itcast.provider.personprovider/person/10

parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person/10")

long personid = ContentUris.parseId(uri);//获取的结果为:10




---------------------- android培训、java培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net/heima

原创粉丝点击