1.ContentProvider是个什么?
ContentProvider——内容提供者。它是一个类,这个类主要是对Android系统中进行共享的数据进行包装,并提供了一组统一的访问接口供其他程序调用。这些被共享的数据,可以使系统自己的也可以使我们个人应用程序中的数据。
2.ContentProvider有什么作用?
在Android中,数据的存储有很多种方式,最常用的就是SQLite和XML文件方式。在不同的应用程序间,其实数据是不能直接被相互访问和操作的,在这种情况下,ContentProvider很好的被用来解决了不同应用程序间数据共享的问题。
其实在Android系统中,已经为我们提供了许多ContentProvider,如:Contacts、Browser、CallLog、Settings等等。那么,Android系统中提供了这么多的ContentProvider,另外还有我们自己公开的共享数据,我们在写程序的时候,怎么才能让我们的应用程序知道去哪儿取、如何取这些数据呢?我们自然的会想到URI。
3.URI中的方法
URI(Uniform Resource Identifier)——统一资源定位符,URI在ContentProvider中代表了要操做的数据。
在Android系统中通常的URI格式为:content://LiB.cprovider.myprovider.Users/User/21
在万维网访问时通常用的URI格式为:http://www.cccc.com/xx/zz
content://——schema,这个是Android中已经定义好的一个标准。
LiB.cprovider.myprovider.Users——authority(主机名),用于唯一标识这个ContentProvider,外部调用者通过这个authority来找到它。相当于www.cccc.com,代表的是我们ContentProvider所在的”域名”,这个”域名”在我们Android中一定要是唯一的,否则系统怎么能知道该找哪一个Provider呢?所以一般情况下,建议采用完整的包名加类名来标识这个ContentProvider的authority。
/User/21——路径,用来标识我们要操作的数据。/user/21表示的意思是——找到User中id为21的记录。其实这个相当于/xxx/zzz。
综上所述,content://LiB.cprovider.myprovider.Users/User/21所代表的URI的意思为:标识LiB.cprovider.myprovider中Users表中_ID为21的User项。
4.ContentProvider中公开的几个方法
public boolean onCreate():该方法在ContentProvider创建后就会被调用,Android系统运行后,ContentProvider只有在被第一次使用它时才会被创建。
public Uri insert(Uri uri, ContentValues values):外部应用程序通过这个方法向 ContentProvider添加数据。
uri——标识操作数据的URI
values——需要添加数据的键值对
public int delete(Uri uri, String selection, String[] selectionArgs):外部应用程序通过这个方法从 ContentProvider中删除数据。
uri——标识操作数据的URI
selection——构成筛选添加的语句,如”id=1” 或者 “id=?”
selectionArgs——对应selection的两种情况可以传入null 或者 new String[]{“1”}
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):外部应用程序通过这个方法对 ContentProvider中的数据进行更新。
values——对应需要更新的键值对,键为对应共享数据中的字段,值为对应的修改值
其余参数同delete方法
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):外部应用程序通过这个方法从ContentProvider中获取数据,并返回一个Cursor对象。
projection——需要从Contentprovider中选择的字段,如果为空,则返回的Cursor将包含所有的字段。
sortOrder——默认的排序规则
其余参数同delete方法
public String getType(Uri uri):该方法用于返回当前Url所代表数据的MIME类型。
如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,例如:要得到所有user记录的Uri为content:// LiB.cprovider.myprovider.Users /User,那么返回的MIME类型字符串应该为:”vnd.android.cursor.dir/user”。
如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,例如:得到id为21的user记录,Uri为content:// LiB.cprovider.myprovider.Users /User/21,那么返回的MIME类型字符串为:”vnd.android.cursor.item/user”。
5.如何公开数据?
首先,继承ContentProvider并重写它的几个抽象方法
package LiB.cprovider;
import java.util.HashMap;
import LiB.cprovider.Users.User;
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.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
public class myprovider extends ContentProvider {
private DBHelper dbHelper;
private static final UriMatcher uriMatcher;
private static final int USER = 1;
private static final int USER_ID = 2;
private static HashMap<String, String> maps;
static {
// 当没有匹配成功是时,返回NO_MATCH的值
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 匹配Users表中的所有User,匹配成功后返回USER整数值
// content://LiB.cprovider.myprovider.Users/User
uriMatcher.addURI(Users.AUTHORITY, “User”, USER);
// 匹配Users表中指定ID的User项,匹配成功后返回USER_ID整数值
// content://LiB.cprovider.myprovider.Users/User/21
uriMatcher.addURI(Users.AUTHORITY, “User/#”, USER_ID);
maps = new HashMap<String, String>();
maps.put(User._ID, User._ID);
maps.put(User.NAME, User.NAME);
maps.put(User.SEX, User.SEX);
maps.put(User.AGE, User.AGE);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count = 0;
switch (uriMatcher.match(uri)) {
case USER:
count = db.delete(DBHelper.DATATABLE_NAME, selection, selectionArgs);
break;
case USER_ID:
String noteId = uri.getPathSegments().get(1);
count = db.delete(DBHelper.DATATABLE_NAME, User._ID
+ "="
+ noteId
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException();
}
this.getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
// User.NAME不能为空
long _id = db.insert(DBHelper.DATATABLE_NAME, User.NAME, values);
if (_id > 0) {
Uri uri1 = ContentUris.withAppendedId(User.CONTENT_URI, _id);
this.getContext().getContentResolver().notifyChange(uri1, null);
return uri1;
}
return null;
}
@Override
public boolean onCreate() {
dbHelper = new DBHelper(this.getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder sqb = new SQLiteQueryBuilder();
switch (uriMatcher.match(uri)) {
case USER:
sqb.setTables(DBHelper.DATATABLE_NAME);
sqb.setProjectionMap(maps);
break;
case USER_ID:
sqb.setTables(DBHelper.DATATABLE_NAME);
sqb.setProjectionMap(maps);
sqb.appendWhere(User._ID + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException();
}
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = sqb.query(db, projection, selection, selectionArgs,
null, null, null);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count;
switch (uriMatcher.match(uri)) {
case USER:
count = db.update(DBHelper.DATATABLE_NAME, values, selection,
selectionArgs);
break;
case USER_ID:
String noteId = uri.getPathSegments().get(1);
count = db.update(DBHelper.DATATABLE_NAME, values, User._ID
+ "="
+ noteId
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection+ ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException();
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
6.怎么操作我自己的数据呢?
为了方便我们操作ContentProvider,Android系统为我们提供了ContentResolver类。我们可以使用getContentResolver()方法返回一个ContentResolver对象,并使用它与ContentProvider对应的方法来进行操作。
总结
其实在Android中,系统已经为我们提供了许多的ContentProvider了,我们通常情况下是不需要去自定义ContentProvider的。但是,为了更好的理解ContentProvider,自己来实现一个ContentProvider是非常必要的。