初学_Android4高级编程-10 Content Provider
※Content Provider提供一个接口用来发布数据,通过Content Resolver来使用该数据。
扩展ContentProvider抽象类来创建一个新的ContentProvider,最好包含静态数据库常量,尤其是处理和查询数据库所需要的列名和ContentProvider授权。
public class ToDoContentProvider extends ContentProvider
·重写onCreate,getType,query,update,delete,insert方法
·使用一个公有的静态的CONTENT_URL属性来公开授权
public static final Uri CONTENT_URI = Uri.parse("content://com.wyk.todoprovider/todoitem");
·在AndroidManifest文件中注册
·定义一个UriMatcher来分析URI的形式——并明确地确定这个URI时请求所有数据还是单行数据
private static final int ALLROWS = 1;
private static final int SINGLE_ROW = 2;
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.wyk.todoprovider", "todoitems", ALLROWS);
uriMatcher.addURI("com.wyk.todoprovider", "todoitems/#", SINGLE_ROW);
}
·创建Content Provider的数据库
※使用Content Resolver来查询和操作Content Provider
·每个应用都有一个ContentResolver实例,可以用getContentResolver方法访问
ContentResolver contentResolver = getContentResolver();
·使用Cursor Loader异步查询内容,数据库查询操作非常耗时,最好不要在主线程中执行
1.实现LoaderCallbacks
2.在Activity和Fragment中调用getLoadManager()方法来访问LoaderManager并初始化
getLoaderManager().initLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks
3.重启来更新数据
getLoaderManager().restartLoader(0, null, this);
4.使用insert,delete,update在Content Provider上执行事务操作
※修改To-Do-List程序,使用Content Provider、数据库持久化task item。
Content Provider类的代码:
public class ToDoContentProvider extends ContentProvider {
public static final String KEY_ID = "_id";
public static final String KEY_TASK = "task";
public static final String KEY_CREATION_DATE = "creation_date";
public static final Uri CONTENT_URI = Uri.parse("content://com.wyk.todoprovider/todoitem");
private MySQLiteOpenHelper sqliteHelper;
private static final int ALLROWS = 1;
private static final int SINGLE_ROW = 2;
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.wyk.todoprovider", "todoitems", ALLROWS);
uriMatcher.addURI("com.wyk.todoprovider", "todoitems/#", SINGLE_ROW);
}
@Override
public boolean onCreate() {
sqliteHelper = new MySQLiteOpenHelper(getContext(), MySQLiteOpenHelper.DATABASE_NAME, null, MySQLiteOpenHelper.DATABASE_VERSION);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = sqliteHelper.getWritableDatabase();
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(MySQLiteOpenHelper.DATABASE_TABLE);
switch (uriMatcher.match(uri)) {
case SINGLE_ROW:
String rowID = uri.getPathSegments().get(1);
queryBuilder.appendWhere(KEY_ID + "=" + rowID);
break;
default:
break;
}
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
return cursor;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case ALLROWS:
return "vnd.android.cursor.dir/vnd.wyk.todos";
case SINGLE_ROW:
return "vnd.android.cursor.item/vnd.wyk.todos";
default:
throw new IllegalArgumentException("Unsupported URI" + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = sqliteHelper.getWritableDatabase();
String nullColumnHack = null;
long id = db.insert(MySQLiteOpenHelper.DATABASE_TABLE, nullColumnHack, values);
if (id > -1) {
Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id);
//通知所有观察者,数据集已经改变
getContext().getContentResolver().notifyChange(insertedId, null);
return insertedId;
} else
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = sqliteHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case SINGLE_ROW:
String rowID = uri.getPathSegments().get(1);
selection = KEY_ID + "=" + rowID + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
break;
default:
break;
}
if (selection == null)
selection = "1";
int deleteCount = db.delete(MySQLiteOpenHelper.DATABASE_TABLE, selection, selectionArgs);
//通知所有观察者,数据集已经改变
getContext().getContentResolver().notifyChange(uri, null);
return deleteCount;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = sqliteHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case SINGLE_ROW:
String rowID = uri.getPathSegments().get(1);
selection = KEY_ID + "=" + rowID + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
break;
default:
break;
}
int updateCount = db.update(MySQLiteOpenHelper.DATABASE_TABLE, values, selection, selectionArgs);
//通知所有观察者,数据集已经改变
getContext().getContentResolver().notifyChange(uri, null);
return updateCount;
}
private static class MySQLiteOpenHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "todoDatabase.db";
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_TABLE = "todoItemTable";
private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " + KEY_TASK + " text not null, " + KEY_CREATION_DATE + " long);";
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}
}
在AndroidManifest中注册provider
在MainActivity中实现一个LoaderCallbacks
@Override
public Loader
CursorLoader loader = new CursorLoader(this,ToDoContentProvider.CONTENT_URI,null,null,null,null);
return loader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
int keyTaskIndex = data.getColumnIndexOrThrow(ToDoContentProvider.KEY_TASK);
todoItems.clear();
while(data.moveToNext()){
ToDoItem newItem = new ToDoItem(data.getString(keyTaskIndex));
todoItems.add(newItem);
}
toDoItemAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
重写添加item的方法
@Override
public void onNewItemAdd(String newItem) {
ContentResolver contentResolver = getContentResolver();
ContentValues values = new ContentValues();
values.put(ToDoContentProvider.KEY_TASK,newItem);
contentResolver.insert(ToDoContentProvider.CONTENT_URI, values);
getLoaderManager().restartLoader(0, null, this);
}
在onCreate()方法初始化LoadManager,在onResume()重启LoadManager
※本地Android Content Provider
·MediaStore 访问设备上的多媒体信息,包括音频,视频,图像
·Browser 读取或修改浏览器和浏览器搜索记录
·Contact Contract 检索、修改或者存储联系人的详细信息
·Calendar 创建新事件,删除或更新现有的日历项
·Call Log 查看或者更新通话记录
使用Contacts Contract Content Provider 读取联系人数据库,它使用一个三层模型来存储数据,通常使用Data表添加、删除或修改为已有的联系人账户存储的数据,使用RawContacts表来创建和管理账户,并使用Contact和Data表来查询数据库以提取联系人详情
要访问联系人详情,要添加READ_CONTACTS权限
浙公网安备 33010602011771号