《Android开发艺术探索》阅读笔记(七)
程序员文章站
2024-03-26 11:40:59
...
4.5 使用ContentProvider:
本篇是介绍如何使用ContentProvider的案例,客户端通过访问ContentProvider,对数据库进行操作。
第一步,创建数据库:
在构造函数
里创建数据库,在onCreate()
中创建表(使用SQL语句)
public class DbOpenHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "book_provider.db";
public static final String BOOK_TABLE_NAME = "book";
public static final String USER_TABLE_NAME = "user";
private static final int DB_VERSION = 2;
//创建表的语句,包括表的名称、表内的数据项
private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS "
+ BOOK_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT)";
private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS "
+ USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT," + "sex INT)";
//构造函数,创建database
public DbOpenHelper(Context context){
super(context,DB_NAME,null,DB_VERSION);
}
//执行语句创建book表、user表
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK_TABLE);
db.execSQL(CREATE_USER_TABLE);
}
//更新数据库
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//TODO ignored
}
}
第二步,创建ContentProvider:
在ContentProvider
里,用new DbOpenHelper(Context).getWritableDatabase()
向DbOpenHelper
类获取SQLiteDatabase
实例,然后对此SQLiteDatabase
实例进行操作。
重写的六个抽象方法:onCreate
代表ContentProvider的创建,getType
用来返回一个Uri请求所对应的MIME类型(媒体类型,图片,视频等),query
、update
、insert
、delete
实现数据表的增删改查功能。
(onCreate运行在主线程里,其余五个运行在Binder线程池中)
public class BookProvider extends ContentProvider {
//Log标签
private static final String TAG = "aa20190131";
//ContentProvider的唯一标识符
public static final String AUTHORITY = "com.example.a20190130.BookProvider11";
//Uri_Code,用于帮助getTableName()识别
public static final int BOOK_URI_CODE = 0;
public static final int USER_URI_CODE = 1;
//UriMatcher很重要,它将客户端传过来的Uri转换为其他可识别的标志
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private Context mContext;
private SQLiteDatabase mDb;
//将Uri和的Uri_Code相关联
static {
sUriMatcher.addURI(AUTHORITY,"book",BOOK_URI_CODE);
sUriMatcher.addURI(AUTHORITY,"user",USER_URI_CODE);
}
//初始化
@Override
public boolean onCreate() {
Log.d(TAG,"onCreate, current thread:" + Thread.currentThread().getName());
mContext = getContext();
//onCreate()在主线程中运行,实际使用中不推荐进行耗时的数据库操作
initProviderData();//初始化数据表
return true;
}
//客户端执行query时会跳到这里
@Override
public Cursor query(Uri uri,String[] projection,String selection, String[] selectionArgs, String sortOrder) {
Log.d(TAG,"query, current thread:" + Thread.currentThread().getName());
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("Unsupported URI:" + uri);
}
return mDb.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
}
@Override
public String getType(Uri uri) {
Log.d(TAG,"getType");
return null;
}
//客户端执行insert时会跳到这里
@Override
public Uri insert(Uri uri,ContentValues values) {
Log.d(TAG,"insert");
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("Unsupport URI:" + uri);
}
mDb.insert(table,null,values);
//通知外界,当前ContentProvider中的数据已经发生改变,不设置观察者
mContext.getContentResolver().notifyChange(uri,null);
return uri;
}
//客户端执行delete时会跳到这里
@Override
public int delete(Uri uri,String selection, String[] selectionArgs) {
Log.d(TAG,"delete");
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("Unsupport URI:" + uri);
}
int count = mDb.delete(table,selection,selectionArgs);
if (count > 0){
getContext().getContentResolver().notifyChange(uri,null);
}
return count;
}
//客户端执行update时会跳到这里
@Override
public int update(Uri uri, ContentValues values,String selection,String[] selectionArgs) {
Log.d(TAG,"update");
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("Unsupport URI:" + uri);
}
int row = mDb.update(table,values,selection,selectionArgs);
if (row > 0){
getContext().getContentResolver().notifyChange(uri,null);
}
return row;
}
//执行SQL语句,添加数据
private void initProviderData(){
mDb = new DbOpenHelper(mContext).getWritableDatabase();//向DbOpenHelper类获取SQLiteDatabase!
mDb.execSQL("delete from " + DbOpenHelper.BOOK_TABLE_NAME);//清空这张表
mDb.execSQL("delete from " + DbOpenHelper.USER_TABLE_NAME);
mDb.execSQL("insert into book values(3,'Android');");
mDb.execSQL("insert into book values(4,'IOS');");
mDb.execSQL("insert into book values(5,'Html5');");
mDb.execSQL("insert into user(_id,name,sex) values(1,'jake',1);");
mDb.execSQL("insert into user(_id,name,sex) values(2,'jasmine',0);");
}
//把客户端传来的Uri转为数据库中表的名称
private String getTableName(Uri uri){
String tableName = null;
switch (sUriMatcher.match(uri)){//将Uri转换为对应的Uri_Code
case BOOK_URI_CODE:
tableName = DbOpenHelper.BOOK_TABLE_NAME;
break;
case USER_URI_CODE:
tableName = DbOpenHelper.USER_TABLE_NAME;
break;
default:
break;
}
return tableName;
}
}
在AndroidManifest.xml文件要对ContentProvider进行设置:
<provider
android:authorities="com.example.a20190130.BookProvider11"
android:name=".BookProvider"
android:permission="com.example.a20190130.PROVIDER"
android:process=":provider"/>
-
android:authorities
是ContentProvider的唯一标识; -
android:permission
指定了外界应用如果要访问ContentProvider,必须声明这个权限; -
android:name
与自己创建的ContentProvider对应; -
android:process
为ContentProvider开辟独立运行的进程;
第三步,在客户端访问ContentProvider:
用Uri bookUri = Uri.parse("content://" + AUTHORITY + "/book")
获取ContentProvider里的表,通过getContentResolver().insert()
等对此表进行操作。
insert、query、delete、update等在ContentProvider中进行了重写。客户端对表的操作会对应到ContentProvider里重写的四大方法。
public class MainActivity extends AppCompatActivity {
//ContentProvider的唯一标识符
public static final String AUTHORITY = "com.example.a20190130.BookProvider11";
private static final String TAG = "aa20190131";
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// //BookProvider中的query被调用了三次,这三次调用不在同一个线程中,它们运行在一个Binder线程中
// Uri uri = Uri.parse("content://com.example.a20190130.BookProvider");
// getContentResolver().query(uri,null,null,null,null);
// getContentResolver().query(uri,null,null,null,null);
// getContentResolver().query(uri,null,null,null,null);
//要访问的是ContentProvider中的book表
Uri bookUri = Uri.parse("content://" + AUTHORITY + "/book");
ContentValues values = new ContentValues();
values.put("_id",6);
values.put("name","程序设计的艺术");
getContentResolver().insert(bookUri,values);
Cursor bookCursor = getContentResolver().query(bookUri,new String[]{"_id","name"},
null,null,null);
while (bookCursor.moveToNext()){
Book book = new Book();
book.bookId = bookCursor.getInt(0);
book.bookName = bookCursor.getString(1);
Log.d(TAG, "query book: " + "bookId:" + book.bookId + " bookName:" + book.bookName);
}
bookCursor.close();
Uri userUri = Uri.parse("content://" + AUTHORITY + "/user");
Cursor userCursor = getContentResolver().query(userUri,new String[]{"_id","name","sex"},
null,null,null);
while (userCursor.moveToNext()){
User user = new User();
user.userId = userCursor.getInt(0);
user.userName = userCursor.getString(1);
user.isMale = userCursor.getInt(2) == 1;
Log.d(TAG, "query user: " + "userId:" + user.userId + " userName:" + user.userName + " isMale:" + user.isMale);
}
userCursor.close();
}
}
上一篇: Hive --自定义函数