編輯:關於Android編程
自定義一個ContentProvider
,需要繼承ContentProvider類
重新創建一個類,並實現其中的一些方法; 在應用的AndroidManifest.xml
文件中,聲明這個新添加的組件;
但在這之前,我們要來設計一下外部訪問它采用的地址。
Uri
的scheme
字段是固定的,使用content:
。
authority
定義成程序的包名com.anddle.mycontentprovider
。
path
就像是網站內部的分類,依據網站的邏輯進行劃分。
假設我們的ContentProvider
提供書籍book和文件file兩種內容的查詢操作。而每種類型都可以進行單一數據的操作和多條數據的操作。
例如,
操作所有書的信息:content://com.anddle.mycontentprovider/books
; 操作某本特定書的信息:content://com.anddle.mycontentprovider/books/8
操作所有文件的信息:content://com.anddle.mycontentprovider/files
操作某個特定文件的信息:content://com.anddle.mycontentprovider/files/3
所以,在對這些地址代表的對象進行增刪改查的時候,就需要分析出它們針對的對象。
繼承ContentProvider類
,會要求我們實現getType()
insert()
delete()
update()
query()
onCreate()
等接口,
public class MyContentProvider extends ContentProvider {
@Override
public boolean onCreate() {
return true;
}
@Override
public String getType(Uri uri) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Uri insert(Uri uri, ContentValues values) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
定義提供給其他組件使用的“網絡地址”URI,這裡我們把它們定義成content://com.anddle.mycontentprovider/books
content://com.anddle.mycontentprovider/files
,
private static final String SCHEME = "content://";
private static final String PATH_BOOKS = "/books";
private static final String PATH_FILES = "/files";
public static final String AUTHORITY = "com.anddle.mycontentprovider";
//"content://com.anddle.mycontentprovider/books"
public static final Uri CONTENT_BOOKS_URI = Uri.parse(SCHEME + AUTHORITY + PATH_BOOKS);
//"content://com.anddle.mycontentprovider/files"
public static final Uri CONTENT_FILES_URI = Uri.parse(SCHEME + AUTHORITY + PATH_FILES);
定義解析地址的匹配器,
private static final int BOOKS = 0;
private static final int BOOK = 1;
private static final int FILES = 2;
private static final int FILE = 3;
private static final UriMatcher sUriMatcher;
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITY, PATH_BOOKS, BOOKS);
sUriMatcher.addURI(AUTHORITY, PATH_BOOKS+"/#", BOOK);
sUriMatcher.addURI(AUTHORITY, PATH_FILES, FILES);
sUriMatcher.addURI(AUTHORITY, PATH_FILES+"/#", FILE);
}
UriMatcher
可以對傳入的字符串進行匹配檢測,如果匹配成功,會返回一個對應的值,例如,
int type = sUriMatcher.match("content://com.anddle.mycontentprovider/files");
//type就等於FILES的值2
type就等於FILES的值2。利用這個方法,我們就可以區分出Uri訪問ContentProvider
時,到底希望操作什麼樣的數據。
創建匹配器的時候,加入sUriMatcher.addURI("content://com.anddle.mycontentprovider","files/#", FILE);
這種帶有”#”的關鍵字段,表示如下這種匹配方式,即匹配任何數字
content://com.anddle.mycontentprovider/files/0
content://com.anddle.mycontentprovider/files/1
content://com.anddle.mycontentprovider/files/3
創建匹配器的時候,加入sUriMatcher.addURI("content://com.anddle.mycontentprovider","files/*", FILE);
這種帶有”#”的關鍵字段,表示如下這種匹配方式,即匹配任何字符
content://com.anddle.mycontentprovider/files/how-to-program
content://com.anddle.mycontentprovider/files/bible
content://com.anddle.mycontentprovider/files/101story
在回調函數中,根據Uri,做對應的操作,
@Override
public Uri insert(Uri uri, ContentValues values) {
Uri result = null;?
switch (sUriMatcher.match(uri)) {
case BOOKS: {
//從ContentValues中取出數據,保存起來;返回保存數據的Uri地址,例如
//content://com.anddle.mycontentprovider/books
}
break;
case BOOK: {
//從ContentValues中取出數據,保存起來;返回保存數據的Uri地址,例如
//content://com.anddle.mycontentprovider/books/8
}
break;
case FILES: {
//從ContentValues中取出數據,保存起來;返回保存數據的Uri地址,例如
//content://com.anddle.mycontentprovider/files
}
break;
case FILE: {
//從ContentValues中取出數據,保存起來;返回保存數據的Uri地址,例如
//content://com.anddle.mycontentprovider/files/8
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return result;
}
這裡就要實現對數據增刪改查的真正操作。
在ContentProvider
中,可以使用很多方式對數據進行保存、修改,例如SQL數據庫。不過我們暫時不去實現,把它放到下一個章節專門介紹。
其他delete()
update()
query()
實現的函數做類似處理。
對於getType()
, 需要為每一種類型的Uri
返回一種數據類型-MIME type
,告訴調用者,當前這種Uri可以處理什麼類型的數據。
它的格式型如type\subtype
,有很多知名的MIME type
類型,例如application/pdf
image/jpeg
等等,可以在網上查找到公開的MIME type
類型有哪些。也可以自定義自己應用支持的特殊MIME type
類型。
這裡我們就返回一個空值,
@Override
public String getType(Uri uri) {
return null;
}
至此,一個ContentProvider
的就完成了。不過它現在還沒有添加上真正可以存儲數據的功能。
/*******************************************************************/
版權聲明
本教程只在CSDN和安豆網發布,其他網站出現本教程均為盜鏈。
/*******************************************************************/
3.3 聲明ContentProvider
千萬不要忘記,在應用的AndroidManifest.xml
文件中,聲明新添加的ContentProvider
,
這裡的android:authorities
屬性值,就要填寫定義MyContentProvider
時,代碼中的那個,
public static final String AUTHORITY = "com.anddle.mycontentprovider";
android:exported
屬性如何設置成true
,說明這個ContentProvider
可以被其他應用使用(就像一個公共網站,可以被任何人訪問),如果設置成false
,說明它只能被自己所在的應用使用(就像一個內部網站,只能在公司內部訪問)。
無論是使用應用自己的ContentProvider
還是使用其他應用提供的,它們的使用方式都和使用系統提供的ContentProvider
一樣,
添加一條數據數據:通過ContentResolver
獲取訪問ContentProvider
的入口,使用ContentValues
添加要插入的數據;
ContentResolver cr = getContentResolver();
ContentValues cv = new ContentValues();
cv.put("數據字段名稱", "數據內容");
Uri uri = cr.insert("content://com.anddle.mycontentprovider/books", cv)
通常會返回指向剛成功插入的這條數據的Uri
(內容就如content://com.anddle.mycontentprovider/books/8
)。
刪除一條數據:通過ContentResolver
獲取訪問ContentProvider
的入口,使用Uri
刪除指定的數據;
String where = null;
String [] keywords = null;
ContentResolver cr = getContentResolver();
cr.delete("content://com.anddle.mycontentprovider/books/8", where, keywords);
修改一條數據:通過ContentResolver
獲取訪問ContentProvider
的入口,使用Uri
更新指定的數據,要修改的數據放在ContentValues
當中;
String where = null;
String [] keywords = null;
ContentResolver cr = getContentResolver();
ContentValues cv = new ContentValues();
cv.put("數據字段名稱", "新數據內容",where,keywords);
cr.update("content://com.anddle.mycontentprovider/books", cv, where, keywords)
查詢某一類的數據(或者特定某條數據),
Uri uri = MyContentProvider.CONTENT_BOOKS_URI;
String[] searchKey = null;
String where = null;
String [] keywords = null;
String sortOrder = null;
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(
uri,
searchKey,
where,
keywords,
sortOrder);
if(cursor != null)
{
while(cursor.moveToNext())
{
......
}
cursor.close();
}
注意,在刪改查的操作中,還會使用諸如where
sortOrder
keywords
searcgKey
這樣的參數,它們是輔助ContentProvider
查詢特定數據時用的。
雖然Uri
已經能定位到某條具體的數據了,但是大部分的ContentProvider
都是通過SQL數據庫來實現的真正存儲,因此,在設計這些接口的時候就保留了SQL語言的一些用法,讓使用者也能像直接操作SQL數據庫那樣靈活方便的使用ContentProvider
。
假如ContentProvider
不用SQL實現數據存儲功能,而采用別的存儲機制,那麼這些額外的參數就可以派上別的用場或者完全用不著。
前面我們簡單的介紹過CoordinatorLayout這個控件,這一篇我們詳細地介紹這個ASD庫中最重要的控件。概述我們在NestedScrollView這個控件中有設置
SlidingMenu簡介: SlidingMenu的是一種比較新的設置界面或配置界面效果,在主界面左滑或者右滑出現設置界面,能方便的進行各種操作.目前有大量的應用都在使
本篇文章繼續介紹以下類型的操作符Observable Utility Operators(Observable的功能性操作符) Conditional and Boole
activity的啟動流程加載一個Activity肯定不會像加載一般的類那樣,因為activity作為系統的組件有自己的生命周期,有系統的很多回調控制,所以自定義一個De