【android学习之十一】——数据存储3:数据共享ContentProvider,ContentResolver
来源:互联网 发布:蓝牙耳机行业 知乎 编辑:程序博客网 时间:2024/06/06 06:30
声明:学习的书籍《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>
这样实例运行效果:
对应的后台数据库内容:
到这里就完成本次数据共享的整理。
- 【android学习之十一】——数据存储3:数据共享ContentProvider,ContentResolver
- Android数据存储—ContentProvider共享数据
- 数据共享ContentProvider,ContentResolver
- android数据存储ContentProvider数据获取ContentResolver
- 数据存储之SqliteOpenHelper、ContentProvider、ContentResolver详解
- 数据共享ContentProvider和ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- Android 应用程序之间数据共享—ContentResolver
- JSTL使用3
- 带宽的理解
- SimpleCursorAdapter类与数据绑定
- pow(double a,int b) [No. 41]
- 百万数据查询优化技巧三十则
- 【android学习之十一】——数据存储3:数据共享ContentProvider,ContentResolver
- vim中三类文本对象 句,段落,节的区别
- Flex中ByteArray与BitmapData互相转换实现图片的二进制保存与复原
- JS中document对象详解
- java 堆溢出的解决方法
- BitmapData的整理
- 我的第一篇博客
- VMFS简介:数据组织,锁和写时拷贝
- Flex中ByteArray与BitmapData互相转换实现图片的二进制保存与复原 .