




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
【移動應用開發技術】還沒弄懂四大組件?帶你全面解析ContentProvider篇
喜歡的小伙伴歡迎關注,我會定期分享Android知識點及解析,還會不斷更新的BATJ面試專題,歡迎大家前來探討交流,如有好的文章也歡迎投稿。1.什么是ContentProviderContentProvider,是自身APP開放給第三方APP的,用于訪問自身數據庫數據的接口。第三方APP可以通過該接口,對指定的數據進行增刪改查。那么如何定義自身的ContentProvider接口呢?在回答問題之前,先來關注一下Uri。2.什么是Uri原因在于,uri是ContentProvider解析外部請求(或者說是,第三方訪問自身數據庫)的關鍵參數。Uri的字符串格式如下content://package/table/idcontent://package/table/id例如content://com.breakloop.sqlitehelperdemo/hero/1content://com.breakloop.sqlitehelperdemo/hero/1從上方Uri示例中,可以獲取到以下信息。第三方APP想要訪問com.breakloop.sqlitehelperdemo的數據庫。至于哪個,由contentProvider內部映射指定。訪問表hero。至于表名是不是真為hero,也由contentProvider說了算。訪問id為1的數據。至于是不是id代表的具體含義,解釋權也歸contentProvider。那么,第三方APP將Uri傳入后,ContentProvider如何將其map為具體的數據庫操作呢?這便有了UriMatcher工具類的引入。3.UriMatcher該工具類,可以將Uri映射為int類型的行為代碼。行為代碼,可以看做是ContentProvider自定義的枚舉類型。而不同的行為代碼,綁定不同的數據庫操作。我們先來看一下,Uri與行為代碼的映射關系
public
final
static
String
AUTHORITY="com.breakloop.contentproviderdemo1";
public
final
static
int
BY_NAME=1;
public
final
static
int
BY_AGE=2;
public
final
static
int
BY_SEX=3;
public
final
static
int
BY_NONE=0;
public
final
static
String
PATH_BY_NAME=DBConst.TABLE_PERSON+"/ByName/*";
public
final
static
String
PATH_BY_AGE=DBConst.TABLE_PERSON+"/ByAge/#";
public
final
static
String
PATH_BY_SEX=DBConst.TABLE_PERSON+"/BySex/*";
}static
{
matcher=new
UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI(MatcherConst.AUTHORITY,MatcherConst.PATH_BY_NAME,MatcherConst.BY_NAME);
matcher.addURI(MatcherConst.AUTHORITY,MatcherConst.PATH_BY_AGE,MatcherConst.BY_AGE);
matcher.addURI(MatcherConst.AUTHORITY,MatcherConst.PATH_BY_SEX,MatcherConst.BY_SEX);
matcher.addURI(MatcherConst.AUTHORITY,DBConst.TABLE_PERSON,MatcherConst.BY_NONE);
}在上面的示例中,UriMatch綁定了四個Uri,并將各個Uri映射為四個行為代碼。其中,用到了轉義符。#代表任意數字,*代表任意字母。那么如何將行為代碼映射為具體的數據庫操作呢?,換句話說,在哪兒使用UriMatcher呢?當然是ContentProvider中!!!在ContentProvider中的增刪改查方法中,完成操作映射。我們來看一下,ContentProvider的創建。4.ContentProvider的創建先用AndroidStudio創建一個ContentProvider.創建過程中,需要提供AUTHORITY,ContentProvider生成后,AndroidStudio將自動幫助ContentProvider在Manifest中進行注冊。接下來,我們看看ContentProvider的結構。5.ContentProvider的結構import
android.content.ContentProvider;import
android.content.ContentValues;import
android.content.UriMatcher;import
android.database.Cursor;import
.Uri;public
class
MyContentProvider
extends
ContentProvider
{
public
MyContentProvider()
{
}
@Override
public
int
delete(Uri
uri,
String
selection,
String[]
selectionArgs)
{
//
Implement
this
to
handle
requests
to
delete
one
or
more
rows.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
String
getType(Uri
uri)
{
//
TODO:
Implement
this
to
handle
requests
for
the
MIME
type
of
the
data
//
at
the
given
URI.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
Uri
insert(Uri
uri,
ContentValues
values)
{
//
TODO:
Implement
this
to
handle
requests
to
insert
a
new
row.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
boolean
onCreate()
{
//
TODO:
Implement
this
to
initialize
your
content
provider
on
startup.
return
false;
}
@Override
public
Cursor
query(Uri
uri,
String[]
projection,
String
selection,
String[]
selectionArgs,
String
sortOrder)
{
//
TODO:
Implement
this
to
handle
query
requests
from
clients.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
int
update(Uri
uri,
ContentValues
values,
String
selection,
String[]
selectionArgs)
{
//
TODO:
Implement
this
to
handle
requests
to
update
one
or
more
rows.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
}一共七個方法。包括一個構造方法,四個數據庫方法(增刪改查),一個初始化方法(onCreate),還有一個getType。關于getType,我們之后解釋。關于構造方法,沒什么可解釋的。關于初始化方法,當返回true時,表明初始化成功,否則,失敗。由于我們要對數據庫進行操作,因此,需要獲取sqlite數據庫對象。public
boolean
onCreate()
{
helper=new
mySqliteHelper(getContext(),DBConst.DB_NAME,null,1);
return
true;
}關于數據庫方法,我們看到傳參中存在Uri,因此,這里需要用到UirMatcher了。我們將剛才的UriMatcher代碼段,加入MyContentProvider.這樣,我們就可以在各個數據庫方法中,解析Uri了。同時,由于sqlite數據庫對象的存在,進而可以對數據庫進行相應操作。6.行為代碼Mapping數據庫操作我們先看一下最簡單的插入操作。
public
Uri
insert(Uri
uri,
ContentValues
values)
{
Uri
returnUri=null;
SQLiteDatabase
db=helper.getWritableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
long
recordID=db.insert(DBConst.TABLE_PERSON,null,values);
returnUri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/"+recordID);
break;
default:
break;
}
return
returnUri;
}再來看一下稍微復雜的查詢。
public
Cursor
query(Uri
uri,
String[]
projection,
String
selection,
String[]
selectionArgs,
String
sortOrder)
{
Cursor
cursor=null;
SQLiteDatabase
db=helper.getReadableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
cursor=db.query(DBConst.TABLE_PERSON,projection,selection,selectionArgs,null,null,sortOrder);
break;
case
MatcherConst.BY_AGE:
cursor=db.query(DBConst.TABLE_PERSON,projection,DBConst.COLUMN_AGE+"=?",new
String[]{uri.getPathSegments().get(2)},null,null,sortOrder);
break;
case
MatcherConst.BY_SEX:
cursor=db.query(DBConst.TABLE_PERSON,projection,DBConst.COLUMN_SEX+"=?",new
String[]{uri.getPathSegments().get(2)},null,null,sortOrder);
break;
case
MatcherConst.BY_NAME:
cursor=db.query(DBConst.TABLE_PERSON,projection,DBConst.COLUMN_NAME+"=?",new
String[]{uri.getPathSegments().get(2)},null,null,sortOrder);
break;
default:
break;
}
return
cursor;
}這里需要注意的是,如何取Uri中的傳入數據。使用的獲取方法是uri.getPathSegments().get(index)。該方法獲取的是AUTHORITY后面的String部分。然后,以”/”為分隔符,生成String[]。接著是更新操作。
@Override
public
int
update(Uri
uri,
ContentValues
values,
String
selection,
String[]
selectionArgs)
{
int
recordID=0;
SQLiteDatabase
db=helper.getWritableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
recordID=db.update(DBConst.TABLE_PERSON,values,null,null);
break;
case
MatcherConst.BY_AGE:
recordID=db.update(DBConst.TABLE_PERSON,values,DBConst.COLUMN_AGE+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_SEX:
recordID=db.update(DBConst.TABLE_PERSON,values,DBConst.COLUMN_SEX+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_NAME:
recordID=db.update(DBConst.TABLE_PERSON,values,DBConst.COLUMN_NAME+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
default:
break;
}
return
recordID;
}還有刪除。
public
int
delete(Uri
uri,
String
selection,
String[]
selectionArgs)
{
int
recordID=0;
SQLiteDatabase
db=helper.getWritableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
recordID=db.delete(DBConst.TABLE_PERSON,null,null);
break;
case
MatcherConst.BY_AGE:
recordID=db.delete(DBConst.TABLE_PERSON,DBConst.COLUMN_AGE+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_SEX:
recordID=db.delete(DBConst.TABLE_PERSON,DBConst.COLUMN_SEX+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_NAME:
recordID=db.delete(DBConst.TABLE_PERSON,DBConst.COLUMN_NAME+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
default:
break;
}
return
recordID;
}那么,第三方如何調用ContentProvider呢?7.ContentProvider的使用這里,我們新建一個工程contentproviderdemo2,在必要的位置使用方法publicContentResolvergetContentResolver()publicContentResolvergetContentResolver()獲取ContentProvider實例,之后便可傳入Uri,調用數據庫相關方法了。例如,我們插入四條記錄。
Uri
returnUri=null;
ContentResolver
resolver=getContentResolver();
Uri
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
ContentValues
values=new
ContentValues();
values.put(DBConst.COLUMN_NAME,"A");
values.put(DBConst.COLUMN_AGE,10);
values.put(DBConst.COLUMN_SEX,"Male");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());
values.put(DBConst.COLUMN_NAME,"B");
values.put(DBConst.COLUMN_AGE,11);
values.put(DBConst.COLUMN_SEX,"Male");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());
values.put(DBConst.COLUMN_NAME,"C");
values.put(DBConst.COLUMN_AGE,12);
values.put(DBConst.COLUMN_SEX,"Female");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());
values.put(DBConst.COLUMN_NAME,"D");
values.put(DBConst.COLUMN_AGE,13);
values.put(DBConst.COLUMN_SEX,"Female");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());我們看一下輸出結果。I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/1I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/2I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/3I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/4既然,寫入成功,那我們查詢一下。
public
void
selectRecord(){
Uri
uri;
String
name="A";
int
age=11;
String
sex="Male";
Log.i(TAG,
"Select
by
Name");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByName/"+name);
selectRecord(uri);
Log.i(TAG,
"Select
by
Age");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByAge/"+age);
selectRecord(uri);
Log.i(TAG,
"Select
by
Sex");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/BySex/"+sex);
selectRecord(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
}
private
void
selectRecord(Uri
uri){
Cursor
cursor;
cursor=resolver.query(uri,new
String[]{DBConst.COLUMN_AGE,
DBConst.COLUMN_NAME,
DBConst.COLUMN_SEX},null,null,null);
if(cursor!=null){
while(cursor.moveToNext()){
Log.i(TAG,
"name
=
"+cursor.getString(1)+
"
age
=
"+cursor.getInt(0)
+"
"+cursor.getString(2));
}
}
}輸出結果如下I/com.breakloop.contentproviderdemo2.MainActivity:
Select
by
Name
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
A
age
=
10
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
by
Age
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
by
Sex
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
A
age
=
10
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
A
age
=
10
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
12
Female
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
D
age
=
13
Female我們再來更新一下。
public
void
updateRecord(){
Uri
uri;
String
name="A";
int
age=11;
String
sex="Female";
ContentValues
values=new
ContentValues();
Log.i(TAG,
"Update
by
Name");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByName/"+name);
values.put(DBConst.COLUMN_NAME,name+name);
update(uri,values);
Log.i(TAG,
"Update
by
Age");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByAge/"+age);
values.clear();
values.put(DBConst.COLUMN_AGE,14);
update(uri,values);
Log.i(TAG,
"Update
by
Sex");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/BySex/"+sex);
values.clear();
values.put(DBConst.COLUMN_AGE,15);
update(uri,values);
Log.i(TAG,
"Update
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
values.put(DBConst.COLUMN_SEX,"Male");
update(uri,values);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
}
private
void
update(Uri
uri,ContentValues
values){
int
count;
count=resolver.update(uri,values,null,null);
Log.i(TAG,
"update
"+count+"
record");
}結果如下I/com.breakloop.contentproviderdemo2.MainActivity:
Update
by
Name
I/com.breakloop.contentproviderdemo2.MainActivity:
update
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Update
by
Age
I/com.breakloop.contentproviderdemo2.MainActivity:
update
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Update
by
Sex
I/com.breakloop.contentproviderdemo2.MainActivity:
update
2
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Update
All
I/com.breakloop.contentproviderdemo2.MainActivity:
update
4
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
AA
age
=
15
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
15
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
15
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
D
age
=
15
Male都不要了,刪除!(這里是對更新前的數據庫進行的操作)
public
void
deleteRecord(){
Uri
uri;
String
name="A";
int
age=11;
String
sex="Female";
Log.i(TAG,
"Delete
by
Name");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByName/"+name);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
Log.i(TAG,
"Delete
by
Age");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByAge/"+age);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
Log.i(TAG,
"Delete
by
Sex");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/BySex/"+sex);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
Log.i(TAG,
"Delete
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
}
private
void
delete(Uri
uri){
int
count;
count=resolver.delete(uri,null,null);
Log.i(TAG,
"delete
"+count+"
record");
}結果如下I/com.breakloop.contentproviderdemo2.MainActivity:
delete
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
12
Female
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
D
age
=
13
Female
I/com.breakloop.contentproviderdemo2.MainActivity:
Delete
by
Age
I/com.breakloop.contentproviderdemo2.MainActivity:
delete
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
12
Female
I/com.breakloop.contentproviderdemo2.
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論