Content Provider 属于Android应用程序的组件之一,作为应用程序之间惟一的共享数据的路径,Content Provider 次要的性能就是存储并检索数据以及向其余应用程序提供拜访数据的借口。
Android 零碎为一些常见的数据类型(如音乐、视频、图像、手机通信录联系人信息等)内置了一系列的 Content Provider, 这些都位于android.provider包下。持有特定的许可,能够在本人开发的应用程序中拜访这些Content Provider。
让本人的数据和其余应用程序共享有两种形式:创立本人的Content Provier(即继承自ContentProvider的子类) 或者是将本人的数据增加到已有的Content Provider中去,后者须要保障现有的Content Provider和本人的数据类型雷同且具备该 Content Provider的写入权限。对于Content Provider,最重要的就是数据模型(data model) 和 URI。
1.数据模型
Content Provider 将其存储的数据以数据表的模式提供给访问者,在数据表中每一行为一条记录,每一列为具备特定类型和意义的数据。每一条数据记录都包含一个 "_ID" 数值字段,改字段惟一标识一条数据。
2.URI
URI,每一个Content Provider 都对外提供一个可能惟一标识本人数据集(data set)的公开URI, 如果一个Content Provider治理多个数据集,其将会为每个数据集调配一个独立的URI。所有的Content Provider 的URI 都以"content://" 结尾,其中"content:"是用来标识数据是由Content Provider治理的 schema。
在简直所有的Content Provider 的操作中都会用到URI,因而一般来讲,如果是本人开发的Content Provider,最好将URI定义为常量,这样在简化开发的同时也进步了代码的可维护性。
首先来介绍如何拜访Content Provider中的数据,拜访 Content Provider中的数据次要通过ContentResolver对象,ContentResolver类提供了成员办法能够用来对Content Provider 中的数据进行查问、插入、批改和删除等操作。 以查问为例,查问一个 Content Provider 须要把握如下的信息。
惟一标识Content Provider 的URI
须要拜访的数据字段名称。
该数据字段的数据类型
提醒: 如果须要拜访特定的某条数据记录,只需该记录的ID 即可。
查问Content Provider的办法有两个:ContentResolver的query() 和 Activity 对象的 managedQuery(),二者接管的参数均雷同,返回的都是Cursor 对象,惟一不同的是 应用managedQuery 办法能够让Activity 来治理 Cursor 的生命周期。
被治理的Cursor 会在 Activity进入暂停状态的时候调用本人的 deactivate 办法自行卸载,而在Activity回到运行状态时会调用本人的requery 办法从新查问生成的Cursor对象。如果一个未被治理的Cursor对象想被Activity治理,能够调用Activity的 startManagingCursor办法来实现。
Android应用程序能够应用文件或SqlLite数据库来存储数据。Content Provider提供了一种多利用间数据共享的形式,比方:联系人信息能够被多个应用程序拜访。Content Provider是个实现了一组用于提供其余应用程序存取数据的规范办法的类。
应用程序能够在Content Provider中执行如下操作:
查问数据
批改数据
增加数据
删除数据
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/MainActivity.java
package com.amaker.ch10.app;
import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import com.amaker.ch10.app.Employees.Employee;
public class MainActivity extends Activity {
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 增加 insert(); // 查问 query(); // 更新 update(); // 查问 query(); // 删除 del(); // 查问 query(); } // 删除办法 private void del(){ // 删除ID为1的记录 Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1); // 取得ContentResolver,并删除 getContentResolver().delete(uri, null, null); } // 更新 private void update(){ // 更新ID为1的记录 Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1); ContentValues values = new ContentValues(); // 增加员工信息 values.put(Employee.NAME, "hz.guo"); values.put(Employee.GENDER, "male"); values.put(Employee.AGE,31); // 取得ContentResolver,并更新 getContentResolver().update(uri, values, null, null); } // 查问 private void query(){ // 查问列数组 String[] PROJECTION = new String[] { Employee._ID, // 0 Employee.NAME, // 1 Employee.GENDER, // 2 Employee.AGE // 3 }; // 查问所有备忘录信息 Cursor c = managedQuery(Employee.CONTENT_URI, PROJECTION, null, null, Employee.DEFAULT_SORT_ORDER); // 判断游标是否为空 if (c.moveToFirst()) { // 遍历游标 for (int i = 0; i < c.getCount(); i++) { c.moveToPosition(i); // 取得姓名 String name = c.getString(1); String gender = c.getString(2); int age = c.getInt(3); // 输入日志 Log.i("emp", name+":"+gender+":"+age); } } } // 插入 private void insert(){ // 申明Uri Uri uri = Employee.CONTENT_URI; // 实例化ContentValues ContentValues values = new ContentValues(); // 增加员工信息 values.put(Employee.NAME, "amaker"); values.put(Employee.GENDER, "male"); values.put(Employee.AGE,30); // 取得ContentResolver,并插入 getContentResolver().insert(uri, values); }
}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/Employees.java
package com.amaker.ch10.app;
import android.net.Uri;
import android.provider.BaseColumns;
/**
- 通讯录常量类
*/
public final class Employees {
// 受权常量 public static final String AUTHORITY = "com.amaker.provider.Employees"; private Employees() {} // 外部类 public static final class Employee implements BaseColumns { // 构造方法 private Employee() {} // 拜访Uri public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/employee"); // 内容类型 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.amaker.employees"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.amaker.employees"; // 默认排序常量 public static final String DEFAULT_SORT_ORDER = "name DESC";// 按姓名排序 // 表字段常量 public static final String NAME = "name"; // 姓名 public static final String GENDER= "gender"; // 性别 public static final String AGE = "age"; // 年龄 }
}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/EmployeeProvider.java
package com.amaker.ch10.app;
import java.util.HashMap;
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;
import com.amaker.ch10.app.Employees.Employee;
public class EmployeeProvider extends ContentProvider{
// 数据库帮忙类 private DBHelper dbHelper; // Uri工具类 private static final UriMatcher sUriMatcher; // 查问、更新条件 private static final int EMPLOYEE = 1; private static final int EMPLOYEE_ID = 2; // 查问列汇合 private static HashMap<String, String> empProjectionMap; static { // Uri匹配工具类 sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(Employees.AUTHORITY, "employee", EMPLOYEE); sUriMatcher.addURI(Employees.AUTHORITY, "employee/#", EMPLOYEE_ID); // 实例化查问列汇合 empProjectionMap = new HashMap<String, String>(); // 增加查问列 empProjectionMap.put(Employee._ID, Employee._ID); empProjectionMap.put(Employee.NAME, Employee.NAME); empProjectionMap.put(Employee.GENDER, Employee.GENDER); empProjectionMap.put(Employee.AGE, Employee.AGE); } // 创立是调用 public boolean onCreate() { // 实例化数据库帮忙类 dbHelper = new DBHelper(getContext()); return true; } // 增加办法 public Uri insert(Uri uri, ContentValues values) { // 取得数据库实例 SQLiteDatabase db = dbHelper.getWritableDatabase(); // 插入数据,返回行ID long rowId = db.insert(DBHelper.EMPLOYEES_TABLE_NAME, Employee.NAME, values); // 如果插入胜利返回uri if (rowId > 0) { Uri empUri = ContentUris.withAppendedId(Employee.CONTENT_URI, rowId); getContext().getContentResolver().notifyChange(empUri, null); return empUri; } return null; } // 删除办法 public int delete(Uri uri, String selection, String[] selectionArgs) { // 取得数据库实例 SQLiteDatabase db = dbHelper.getWritableDatabase(); // 取得数据库实例 int count; switch (sUriMatcher.match(uri)) { // 依据指定条件删除 case EMPLOYEE: count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, selection, selectionArgs); break; // 依据指定条件和ID删除 case EMPLOYEE_ID: String noteId = uri.getPathSegments().get(1); count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, Employee._ID + "=" + noteId + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs); break; default: throw new IllegalArgumentException("谬误的 URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } // 取得类型 public String getType(Uri uri) { return null; } // 查询方法 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); switch (sUriMatcher.match(uri)) { // 查问所有 case EMPLOYEE: qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME); qb.setProjectionMap(empProjectionMap); break; // 依据ID查问 case EMPLOYEE_ID: qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME); qb.setProjectionMap(empProjectionMap); qb.appendWhere(Employee._ID + "=" + uri.getPathSegments().get(1)); break; default: throw new IllegalArgumentException("Uri谬误! " + uri); } // 应用默认排序 String orderBy; if (TextUtils.isEmpty(sortOrder)) { orderBy = Employee.DEFAULT_SORT_ORDER; } else { orderBy = sortOrder; } // 取得数据库实例 SQLiteDatabase db = dbHelper.getReadableDatabase(); // 返回游标汇合 Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } // 更新办法 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // 取得数据库实例 SQLiteDatabase db = dbHelper.getWritableDatabase(); int count; switch (sUriMatcher.match(uri)) { // 依据指定条件更新 case EMPLOYEE: count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, selection, selectionArgs); break; // 依据指定条件和ID更新 case EMPLOYEE_ID: String noteId = uri.getPathSegments().get(1); count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, Employee._ID + "=" + noteId + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs); break; default: throw new IllegalArgumentException("谬误的 URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; }
}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/DBHelper.java
package com.amaker.ch10.app;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.amaker.ch10.app.Employees.Employee;
/**
- 数据库工具类
*/
public class DBHelper extends SQLiteOpenHelper{
// 数据库名称常量 private static final String DATABASE_NAME = "Employees.db"; // 数据库版本常量 private static final int DATABASE_VERSION = 1; // 表名称常量 public static final String EMPLOYEES_TABLE_NAME = "employee"; // 构造方法 public DBHelper(Context context) { // 创立数据库 super(context, DATABASE_NAME,null, DATABASE_VERSION); } // 创立时调用 public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + EMPLOYEES_TABLE_NAME + " (" + Employee._ID + " INTEGER PRIMARY KEY," + Employee.NAME + " TEXT," + Employee.GENDER + " TEXT," + Employee.AGE + " INTEGER" + ");"); } // 版本更新时调用 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 删除表 db.execSQL("DROP TABLE IF EXISTS employee"); onCreate(db); }
}
/Chapter10_ContentProvider_01_Test02/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amaker.ch10.app" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <provider android:name="EmployeeProvider" android:authorities="com.amaker.provider.Employees"/> <activity android:name=".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> </application> <uses-sdk android:minSdkVersion="3" />
</manifest>