ContentProvider
ContentProvider是Andorid的四大组件之一,它封装了数据库的底层实现,暴露接口和ContentResolver一起组成的Andorid系统中通用数据存储 查询 修改 删除 方式。同时支持应用间数据交换是它最大的优势。
下面就用一个简答的例子来展示一下ContentProvider的简单实用。
- DbHelper.java
数据库帮助类,创建 更新数据库的最佳实践、
package com.view.loaders.db;
import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class DbHelper extends SQLiteOpenHelper {
// 數據庫的名字,sqlite基於文件,所以要帶後綴名.db
private static final String name = "myDb.db";
// 數據庫的版本號
private static int version = 1;
// person 表的表名 public 暴露
public static final String DATABASE_PERSON_TABLE = "person";
public DbHelper(Context context) {
super(context, name, null, version);
// TODO Auto-generated constructor stub
}
/**
* 创建数据库,执行建表语句
*/
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table person (id integer primary key autoincrement,name varchar(64),password varchar(16));";
db.execSQL(sql);
}
/**
* 當版本號改變是,會條用此方法
*/
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
}
2.PersonContentProvider.java
ContentProvider类,实现以下几个方法
The primary methods that need to be implemented are:
- onCreate() which is called to initialize the provider
- query(Uri, String[], String, String[], String) which returns data to the caller
- insert(Uri, ContentValues) which inserts new data into the content provider
- update(Uri, ContentValues, String, String[]) which updates existing data in the content provider
- delete(Uri, String, String[]) which deletes data from the content provider
- getType(Uri) which returns the MIME type of data in the content provider
package com.view.loaders.provider;
import com.view.loaders.db.DbHelper;
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.util.Log;
import android.widget.SeekBar;
public class PersonContentProvider extends ContentProvider {
// 公开的 内容uri
// uri 通常只有两种格式,即请求全数据的 还有 withAppendId (/#)形式的
public static final Uri Content_URI = Uri
.parse("content://com.view.loaders.provider.PersonContentProvider/person");
// 列名很重要 ,公开查询的ID 和其他列的列名
public static final String KEY_ID = "id";
public static final String COLUMN_1_NAME = "name";
public static final String COLUMN_2_NAME = "password";
// 数据库帮助类
private DbHelper helper;
// 单行操作 还是多行操作
private static final int SINGLE_ROW = 2;
private static final int ALLROWS = 1;
private static final UriMatcher URI_MATCHER = new UriMatcher(
UriMatcher.NO_MATCH);
static {
// 匹配
// 单行操作 多行操作授权相同,主要是路径不同
URI_MATCHER.addURI("com.view.loaders.provider.PersonContentProvider",
"person/#", SINGLE_ROW);
URI_MATCHER.addURI("com.view.loaders.provider.PersonContentProvider",
"person", ALLROWS);
}
public PersonContentProvider() {
// TODO Auto-generated constructor stub
}
/**
* 初始化 在此实例化数据库帮助类
*/
@Override
public boolean onCreate() {
helper = new DbHelper(getContext());
return true;
}
/**
* 返回MIME信息
*/
@Override
public String getType(Uri uri) {
int flag = URI_MATCHER.match(uri);
Log.i("nikan", "11111------" + flag);
switch (flag) {
case SINGLE_ROW:
return "vnd.android.cursor.item/person";
case ALLROWS:
return " vnd.android.cursor.dir/person";
}
return null;
}
/**
* 插入
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
SQLiteDatabase db = helper.getWritableDatabase();
Uri newUri = null;
int flag = URI_MATCHER.match(uri);
Log.i("nikan", "insert ......." + flag);
// 插入的Uri不带id,id为自动增长
// 所以插入的Uri会匹配为ALLROWS,或者不需要匹配验证
switch (flag) {
case ALLROWS:
Log.i("nikan", "insert 0002 .......");
long id = db.insert("person", null, values);
newUri = ContentUris.withAppendedId(uri, id);
Log.i("nikan", newUri.toString());
return newUri;
default:
break;
}
return null;
}
/**
* 删除
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int flag = URI_MATCHER.match(uri);
SQLiteDatabase db = helper.getWritableDatabase();
switch (flag) {
case SINGLE_ROW:
// String rowID=uri.getPathSegments().get(1);
// 获取Uri里面的ID
long id = ContentUris.parseId(uri);
String whereValues = "id=" + id;
Log.i("nikan", "delete ......." + id);
// 如果selection不为空,添加where条件
if (selection != null && "".equals(selection.trim())) {
whereValues += "AND" + selection;
}
int count = db.delete("person", whereValues, selectionArgs);
// count 删除操作影响的行数
if (count > 0) {
Log.i("nikan", "delete success .......");
}
return count;
case ALLROWS:
int counts = db.delete("person", selection, selectionArgs);
return counts;
default:
return 0;
}
}
/**
* 更新数据
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int flag = URI_MATCHER.match(uri);
SQLiteDatabase db = helper.getWritableDatabase();
switch (flag) {
case SINGLE_ROW:
long id = ContentUris.parseId(uri);
String whereValues = "id=" + id;
if (selection != null && "".equals(selection.trim())) {
whereValues += "AND" + selection;
}
int count = db.update("person", values, whereValues, selectionArgs);
if (count > 0) {
Log.i("nikan", "update success....." + id);
return count;
}
default:
break;
}
return 0;
}
/**
* 查询
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = helper.getWritableDatabase();
// SQLiteQueryBuilder is a helper class that creates the
// proper SQL syntax for us.
SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
// Set the table we're querying.
qBuilder.setTables(DbHelper.DATABASE_PERSON_TABLE);
// If the query ends in a specific record number, we're
// being asked for a specific record, so set the
// WHERE clause in our query.
if ((URI_MATCHER.match(uri)) == SINGLE_ROW) {
qBuilder.appendWhere("id=" + ContentUris.parseId(uri));
}
// Make the query.
Cursor c = qBuilder.query(db, projection, selection, selectionArgs,
null, null, sortOrder);
// 通知所有觀察者 ,數據集以改變
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
}
3.在清单文件注册ContentProvider
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.view.loaders"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19" />
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.view.loaders"></instrumentation>
<!-- 添加读取联系人的权限-->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="android.test.runner" >
</uses-library>
<activity
android:name="com.view.loaders.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--看这里 看这里 看这里-->
<!-- 注册一个contentProvier -->
<provider
android:name="com.view.loaders.provider.PersonContentProvider"
android:authorities="com.view.loaders.provider.PersonContentProvider" >
</provider>
</application>
</manifest>
4.MyTest.java
测试类,测试增删改查
package com.view.loaders.test;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;
import com.view.loaders.db.DbHelper;
import com.view.loaders.provider.PersonContentProvider;
public class MyTest extends AndroidTestCase {
public MyTest() {
// TODO Auto-generated constructor stub
}
public void TestCreate() {
DbHelper helper = new DbHelper(getContext());
helper.getWritableDatabase();
}
public void TestInsert() {
ContentResolver contentResolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "ride on side");
values.put("password", "you are mine");
Uri uri = PersonContentProvider.Content_URI;
Log.i("nikan", uri.toString() + " ------>");
contentResolver.insert(uri, values);
}
public void TestDelete() {
ContentResolver contentResolver = getContext().getContentResolver();
Uri uri = ContentUris.withAppendedId(PersonContentProvider.Content_URI,
1);
contentResolver.delete(uri, null, null);
}
public void TestUpdate() {
ContentResolver contentResolver = getContext().getContentResolver();
Uri uri = ContentUris.withAppendedId(PersonContentProvider.Content_URI,
2);
ContentValues values = new ContentValues();
// values.put("name", "RainBow");
values.put("password", "22222");
contentResolver.update(uri, values, null, null);
}
public void TestQuery() {
ContentResolver contentResolver = getContext().getContentResolver();
// 指定ID,單行查詢
/*
* Uri uri=ContentUris.withAppendedId(PersonContentProvider.Content_URI,
* 2); Cursor cursor= contentResolver.query(uri, null, null, null,
* null);
*/
Cursor cursor = contentResolver.query(
PersonContentProvider.Content_URI, null, null, null, null);
while (cursor.moveToNext()) {
String name = cursor.getString(cursor
.getColumnIndex(PersonContentProvider.COLUMN_1_NAME));
String password = cursor.getString(cursor
.getColumnIndex(PersonContentProvider.COLUMN_2_NAME));
Log.i("nikan", "<<<-----" + name + "------>>" + password);
}
}
}