【android學習之十一】——資料存放區3:資料共用ContentProvider,ContentResolver

來源:互聯網
上載者:User

 聲明:學習的書籍《Android應用開發揭秘》,這裡記錄學習該書籍的日誌,引用的相關代碼與總結描述,沒有商業的用途,完全是自我學習的一個記錄,剛剛學習不可避免會出現很多問題,若是有錯誤還請大家多多批評。

三、資料存放區3:資料共用ContentProvider,ContentResolver

         把這篇部落格補一下,之前學習一直想整理一下,但是總不知道如何下手,因為這塊內容與之前web開發中的思路有一定的差異,自己所以就稍微晚了1周來補充這篇部落格。

         之前介紹過了資料存放區操作的方式可知,每個程式都是線程式控制制,並且資料無法共用,而ContentProvider來解決這個問題,ContentProvider是所有應用程式之間資料存放區與檢索的一個橋樑,他的作用就是使得各個程式之間實現資料共用。

         可以把ContentProvider理解為一種特殊的儲存資料的類型,因為ContentProvider是個抽象類別,繼承自該類必須實現:getType,insert,delete,update,query方法,所以它提供了一套上述介面來擷取,操作資料。

 

         就像我們學習web開發剛接觸Model1的MVC時,資料層方面實現了針對實體的增刪改查,但是在業務層方面最好封裝一個資料操作的Service,這樣的話就避免了業務層直接操作資料層,而把這個工作交給對應的Service的實現,更好的管理。這裡就引出了ContentResolver,它的作用就可以理解為對應Service的實現來操作對應ContentProvider。

ContentResolver對象的擷取可以通過getContentResolver()方法來取得

      

         這裡需要說明的是,每個ContentProvider都會對外提供一個公用的URI(封裝成Uri對象),如果應用程式有資料需要共用,就需要使用ContentProvider為這些資料定義一個URI,然後其他應用程式就可以通過ContentProvider傳入這個URI來對資料進行操作。URI由3個部分組成:“content://”、資料的路徑、標示ID(可選)。如:

        content://media/internal/images   這個URI返回裝置上儲存的所有圖片

        content://contacts/people/5       連絡人資訊中ID為5的連絡人記錄

        content://contacts:/people/       這個URI返回裝置上得所有連絡人資訊。

 

當然android.provider包下也提供了一些輔助類來達到上述效果如:

Uri person = ContentUris.withAppendedId(People.CONTENT_URI , 5);

 

       這裡個人認為有點像OSGI中,Serivice的註冊,用一個標示Id(這裡是URI)來標示當前系統提供了哪些服務(這裡是共用資料),通過Id擷取了對應Service然後進行操作。而ContentResolver都把URI作為其參數,用來表明該ContentResolver在操作哪個ContentProvider。

getContentResolver().insert(NotePad.Notes.CONTENT_URI, values);

      如上面這行代碼就是ContentResolver操作了對應Notes的URI,後面參數values就是資料值。

 

【擴充學習】:如果要是自己建立自己的Contentprovider,並且資料類型是當前不存在的,則需要定義自己的返回列,同時也要定義對應的一種新的MIME類型,可以這樣理解:當前共用資料中沒有的類型需要進行配置與定義,才能使用,不然無法識別。

        

 而這裡我們用SDK改寫的的執行個體Notes進行測試,上述所有MIME類型以及返回列的定義都在NotePad類:

public class NotePad {public static final String AUTHORITY = "com.google.provider.NotePad";//ContentProvider的uripublic NotePad(){}//定義基本欄位public static final class Notes implements BaseColumns{public Notes(){}public static final Uri CONTENT_URI= Uri.parse("content://" + AUTHORITY + "/notes");//新的MIME類型-多個public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";// 新的MIME類型-單個public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";public static final StringDEFAULT_SORT_ORDER= "modified DESC";//欄位public static final StringTITLE= "title";public static final StringNOTE= "note";public static final StringCREATEDDATE= "created";public static final StringMODIFIEDDATE= "modified";}}

同時對應的AndroidManifest.xml檔案中需要配置provider

<provider android:name="NotePadProvider" android:authorities="com.google.provider.NotePad"/>

 

而NotePadProvider類:

public class NotePadProvider extends ContentProvider{private static final StringTAG         = "NotePadProvider";// 資料庫名private static final StringDATABASE_NAME= "note_pad.db";private static final intDATABASE_VERSION= 2;// 表名private static final StringNOTES_TABLE_NAME= "notes";private static HashMap<String, String>sNotesProjectionMap;private static final intNOTES= 1;private static final intNOTE_ID= 2;private static final UriMatchersUriMatcher;private DatabaseHelpermOpenHelper;//建立表SQL語句private static final StringCREATE_TABLE="CREATE TABLE " + NOTES_TABLE_NAME + " (" + Notes._ID + " INTEGER PRIMARY KEY," + Notes.TITLE + " TEXT," + Notes.NOTE + " TEXT,"+ Notes.CREATEDDATE + " INTEGER," + Notes.MODIFIEDDATE + " INTEGER" + ");";static{sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);sNotesProjectionMap = new HashMap<String, String>();sNotesProjectionMap.put(Notes._ID, Notes._ID);sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE);sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE);sNotesProjectionMap.put(Notes.CREATEDDATE, Notes.CREATEDDATE);sNotesProjectionMap.put(Notes.MODIFIEDDATE, Notes.MODIFIEDDATE);}private static class DatabaseHelper extends SQLiteOpenHelper{//建構函式-建立資料庫DatabaseHelper(Context context){super(context, DATABASE_NAME, null, DATABASE_VERSION);}//建立表@Overridepublic void onCreate(SQLiteDatabase db){db.execSQL(CREATE_TABLE);}//更新資料庫@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){db.execSQL("DROP TABLE IF EXISTS notes");onCreate(db);}}@Overridepublic boolean onCreate(){mOpenHelper = new DatabaseHelper(getContext());return true;}@Override//查詢操作public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){SQLiteQueryBuilder qb = new SQLiteQueryBuilder();switch (sUriMatcher.match(uri)){case NOTES:qb.setTables(NOTES_TABLE_NAME);qb.setProjectionMap(sNotesProjectionMap);break;case NOTE_ID:qb.setTables(NOTES_TABLE_NAME);qb.setProjectionMap(sNotesProjectionMap);qb.appendWhere(Notes._ID + "=" + uri.getPathSegments().get(1));break;default:throw new IllegalArgumentException("Unknown URI " + uri);}String orderBy;if (TextUtils.isEmpty(sortOrder)){orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;}else{orderBy = sortOrder;}SQLiteDatabase db = mOpenHelper.getReadableDatabase();Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);c.setNotificationUri(getContext().getContentResolver(), uri);return c;}@Override// 如果有自訂類型,必須實現該方法public String getType(Uri uri){switch (sUriMatcher.match(uri)){case NOTES:return Notes.CONTENT_TYPE;case NOTE_ID:return Notes.CONTENT_ITEM_TYPE;default:throw new IllegalArgumentException("Unknown URI " + uri);}}@Override//插入資料庫public Uri insert(Uri uri, ContentValues initialValues){if (sUriMatcher.match(uri) != NOTES){throw new IllegalArgumentException("Unknown URI " + uri);}ContentValues values;if (initialValues != null){values = new ContentValues(initialValues);}else{values = new ContentValues();}Long now = Long.valueOf(System.currentTimeMillis());if (values.containsKey(NotePad.Notes.CREATEDDATE) == false){values.put(NotePad.Notes.CREATEDDATE, now);}if (values.containsKey(NotePad.Notes.MODIFIEDDATE) == false){values.put(NotePad.Notes.MODIFIEDDATE, now);}if (values.containsKey(NotePad.Notes.TITLE) == false){Resources r = Resources.getSystem();values.put(NotePad.Notes.TITLE, r.getString(android.R.string.untitled));}if (values.containsKey(NotePad.Notes.NOTE) == false){values.put(NotePad.Notes.NOTE, "");}SQLiteDatabase db = mOpenHelper.getWritableDatabase();long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, values);if (rowId > 0){Uri noteUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);getContext().getContentResolver().notifyChange(noteUri, null);return noteUri;}throw new SQLException("Failed to insert row into " + uri);}@Override//刪除資料public int delete(Uri uri, String where, String[] whereArgs){SQLiteDatabase db = mOpenHelper.getWritableDatabase();int count;switch (sUriMatcher.match(uri)){case NOTES:count = db.delete(NOTES_TABLE_NAME, where, whereArgs);break;case NOTE_ID:String noteId = uri.getPathSegments().get(1);count = db.delete(NOTES_TABLE_NAME, Notes._ID + "=" + noteId + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);break;default:throw new IllegalArgumentException("Unknown URI " + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}@Override//更新資料public int update(Uri uri, ContentValues values, String where, String[] whereArgs){SQLiteDatabase db = mOpenHelper.getWritableDatabase();int count;switch (sUriMatcher.match(uri)){case NOTES:count = db.update(NOTES_TABLE_NAME, values, where, whereArgs);break;case NOTE_ID:String noteId = uri.getPathSegments().get(1);count = db.update(NOTES_TABLE_NAME, values, Notes._ID + "=" + noteId + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);break;default:throw new IllegalArgumentException("Unknown URI " + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}}

 

最終操作的Activity類為:

 

public class DataProviderActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                //插入資料        ContentValues values = new ContentValues();        values.put(NotePad.Notes.TITLE, "title1");        values.put(NotePad.Notes.NOTE, "NoteNote1");        getContentResolver().insert(NotePad.Notes.CONTENT_URI, values);                values.clear();        values.put(NotePad.Notes.TITLE, "title2");        values.put(NotePad.Notes.NOTE, "NoteNote2");        getContentResolver().insert(NotePad.Notes.CONTENT_URI, values);                /* 顯示 */displayNote();    }private void displayNote() {// TODO Auto-generated method stubString columns[] = new String[]{NotePad.Notes._ID,NotePad.Notes.TITLE, NotePad.Notes.NOTE, NotePad.Notes.CREATEDDATE, NotePad.Notes.MODIFIEDDATE};Uri myUri = NotePad.Notes.CONTENT_URI;Cursor cursor = this.managedQuery(myUri, columns, null, null, null);if (cursor.moveToFirst()) {String id = null;String title = null;do{id = cursor.getString(cursor.getColumnIndex(NotePad.Notes._ID));title = cursor.getString(cursor.getColumnIndex(NotePad.Notes.TITLE));Toast toast=Toast.makeText(this, "TITLE:"+id + "NOTE:" + title, Toast.LENGTH_LONG);toast.setGravity(Gravity.TOP|Gravity.CENTER, 0, 40);toast.show();}while(cursor.moveToNext());}}}

當然對應Activity類需要在設定檔裡註冊:

<activity            android:label="@string/app_name"            android:name=".DataProviderActivity" >            <intent-filter >                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>            <intent-filter><data android:mimeType="vnd.android.cursor.dir/vnd.google.note"/></intent-filter><intent-filter><data android:mimeType="vnd.android.cursor.item/vnd.google.note"/></intent-filter>        </activity>

這樣執行個體運行效果:

 

對應的後台資料庫內容:


到這裡就完成本次資料共用的整理。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.