初学_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,重写onCreateLoader,onLoadFinished,onLoaderReset方法
2.在Activity和Fragment中调用getLoadManager()方法来访问LoaderManager并初始化
getLoaderManager().initLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks callback);
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 onCreateLoader(int id, Bundle args) {
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权限

posted on 2015-07-09 20:06  想做很多事  阅读(128)  评论(0)    收藏  举报

导航