ContentProvider 是如何向外界提供数据的?
Android提供了ContentProvider,一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去,而且ContentProviders是以类似数据库中表的方式将数据暴露,也就是说ContentProvider就像一个“数据库”。那么外界获取其提供的数据,也就应该与从数据库中获取数据的操作基本一样,只不过是采用URI来表示外界需要访问的“数据库”。至于如何从URI中识别出外界需要的是哪个“数据库”,这就是Android底层需要做的事情了,不在此详细说。简要分析下ContentProvider向外界提供数据操作的接口:
query(Uri, String[], String, String[], String) insert(Uri, ContentValues) update(Uri, ContentValues, String, String[]) delete(Uri, String, String[])这些操作与数据库的操作基本上完全一样,在此不详细说,具体的解析可以参考Android Sqlite解析篇中的详细说明。需要特殊说明的地方是URI:
以下是一个例子的简单说明:
Xml代码 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" android:installLocation="internalOnly" package="com.calendarwidget"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!-- 告诉系统,你的应用程序有provider组件 --> <provider android:name=".CalendarProvider" android:authorities="com.calendarwidget.provider" /> </application> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" /> </manifest>Java代码:
public class CalendarProvider extends ContentProvider { private static final String URI_AUTHORITY = "com.calendarwidget.provider"; public static final String URI_PATH = "RecordSet"; //只是填充,没有作用 public static final String URI_PATH2 = "RecordSet/#";//只是填充,没有作用 public static final Uri CONTENT_URI = Uri.parse("content://" + URI_AUTHORITY + "/" + URI_PATH); private static final UriMatcher sMatcher; public static final int ALL_EVENT_RECORDS = 0; static { sMatcher = new UriMatcher(UriMatcher.NO_MATCH); sMatcher.addURI(URI_AUTHORITY, URI_PATH, ALL_EVENT_RECORDS); sMatcher.addURI(URI_AUTHORITY, URI_PATH2, ALL_EVENT_RECORDS); } private Context mContext; @Override public boolean onCreate() { if (mContext == null) { mContext = getContext(); } return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //匹配码 int match = sMatcher.match(uri); Cursor cur = null; switch (match) { case ALL_EVENT_RECORDS: cur = loadAllCalendarEvent(this); break; default: break; } return cur; } private MatrixCursor loadAllCalendarEvent(CalendarProvider calendarProvider) { MatrixCursor mc = new MatrixCursor(CalendarConstants.PROJECTION); Cursor calendarCursor = null; try { calendarCursor = calendarProvider .getContext() .getContentResolver().query("content://com.android.calendar/calendars", null, null, null, null); / while (calendarCursor.moveToNext()) { //TODO ..... mc.addRow(rowObject); } return mc; } finally { calendarCursor.close(); } } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } }关于getType使用提示:
<intent-filter android:label="@string/resolve_edit"> <action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.EDIT" /> <action android:name="com.android.notepad.action.EDIT_NOTE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter>我們很容易看出action和category是很容易匹配的,而我們傳的Uri的數據怎麼匹配呢,這時系統就會去調用你定義的ContentProvider中的getType,取得相關的返回值來和上面的data串進行匹配,當然getType的返回結果你是需要自己去定義的。但在程序中你也可以自己知道data的類型,就直接匹配了:intent.setType(type);