1. 什么是content provider?
一个应用程序将自己的数据分享给其他程序。进程间的程序通信。Provider-resolver:服务器-客服端。Provider封装对相关数据的增删改查,resolver解析这些操作,访问provider。
2. Cursor:游标;CursorAdapter:游标适配器
(1) 需要在DBHelper(继承SqliteOpenHelper)中注意:
A.构造函数中需要调用父类的构造函数:super(context,name,null,version);
B.需要在onCreate函数中添加数据库创建语句:String sql ="create table person(_idinteger primary key autoincrement, name varchar(64),address varchar(64),ageinteger)";
(2) 在DBManager中利用DBHelper获取sqlitedatabase,利用sqlitedatabase的insert()、update()、delete()和query()函数进行增删查改。
(3) Adapter : SimpleCursorAdapter
adapter =newSimpleCursorAdapter(this, R.layout.activity_main,service.listPersonCursor(),newString[] { "name","address","age" },newint[] { R.id.textView1, R.id.textView2, R.id.textView3 });
from:和Cursor中字段相对应。To:和layout中相关text相对应。
3. LoaderManager:加载器管理器
(1) 需要用到2中(1)、(2)中相关数据,同时需要用到service的实现
(2) Activity需要实现LoaderCallBack<Cursor>接口,在该接口中,需要实现的函数:
A. public Loader<Cursor>onCreateLoader(intarg0, Bundle arg1);
B. publicvoidonLoadFinished(Loader<Cursor> arg0, Cursor arg1);
C. publicvoidonLoaderReset(Loader<Cursor> arg0);
(3) 在activity中的onCreate()函数中获取LoaderManager,并用LoaderManager创建加载器。代码:
manager = getLoaderManager();//获取加载器管理器
manager.initLoader(1001,null,this);//创建加载器:3个参数:id;bundle;loadercallback<cursor>;
(4) 调用了initLoader后,程序会自动调用第三个参数中的public Loader<Cursor>onCreateLoader(intarg0, Bundle arg1)方法,在该方法中可以创建一个异步任务去加载数据。
(5) 在继承的AsyncTaskLoader的异步加载器中public CursorloadInBackground()函数中进行数据获取。
(6) 在获取到数据后,会调用publicvoid onLoadFinished(Loader<Cursor> arg0,Cursor arg1)这个方法,可以将获取的Cursor赋值给adapter,同时将adapter传递给listView。
4. 创建一个content provider:
(1) 需要建立一个像2中(1)中的DBHelper来建立一个共享数据库表。(或者其他数据结构)
(2) 创建一个类继承ContentProvider,在该ContentProvider中会出现:
A. publicboolean onCreate();
B. public String getType(Uriarg0);
C. public Uri insert(Uri arg0,ContentValues arg1)
D. publicint update(Uri arg0,ContentValues arg1, String arg2, String[] arg3);
E. publicint delete(Uri arg0, Stringarg1, String[] arg2);
F. public Cursor query(Uri arg0,String[] arg1, String arg2, String[] arg3,String arg4);
(3) 在清单文件中声明:provider:
<providerandroid:name="com.example.one_contentprovider.PersonContentProvider"
android:authorities="com.example.android.PersonContentProvider">
</provider>
(Android:name):指向具体的ContentProvider;(android:authorities):为该ContentProvider指定权限,即访问路径。
(4) 在provider中创建一个UriMatcher,用于添加Uri的匹配规则:
privatestaticfinalUriMatcherURI_MATCHER=newUriMatcher(UriMatcher.NO_MATCH);
static{ URI_MATCHER.addURI("com.example.android.PersonContentProvider","person",PERSONS);URI_MATCHER.addURI("com.example.android.PersonContentProvider","person/#",PERSON);
}
(5) 在onCreate中创建可以获取sqlitedatabase的DBHelper。
(6) 重写provider中的函数
A. publicboolean onCreate():
dbHelper = new DBHelper(getContext());
return false;
B. public String getType(Uriarg0):
int flag = URI_MATCHER.match(arg0);//匹配URI规则,返回匹配的值
switch(flag){
case PERSONS:
return “vnd.android.cursor.dir/person”;
case PERSON:
return “vnd.android.cursor.item/person”;
}
Return null;
C. public Uri insert(Uri arg0,ContentValues arg1)
Uri uri = null;
Int flag = URI_MARCHER.match(arg0);//匹配URI规则
Swtich(flag){
Case PERSONS://插入不会提供具体的id,所以只用匹配persons
SQlitedatabase database =dbHelper.getWriteDatabase();
Long _id =database.insert(“person”,null,arg1);
Uri = ContentUris.withAppendedId(arg0,_id);
Break;
}
Return uri;
D. publicint update(Uri arg0,ContentValues arg1, String arg2, String[] arg3)
int flag = URI_MATCHER.match(arg0);
SQliteDatabase database = dbHelper.getWriteDatabase();
Int count=0;
Switch(flag){
Case PERSON:
Long _id = ContentUris.parseId(arg0);
String where_values = “ _id = ”+_id;
If(arg2!=null&&!arg2.equals(“”)){
Where_values+=arg2;
}
Count=Database.update(“person”,arg1,where_values,arg3);
Break;
}
Return count;
E. publicint delete(Uri arg0, Stringarg1, String[] arg2)
int flag = URI_MATCHER.match(arg0);
SQliteDatabase database = dbHelper.getWriteDatabase();
Int count = 0;
Switch(flag){
Case PERSON:
Long _id = ContentUris.parseId(arg0);
String where_values = “ _id = ”+_id;
If(arg1!=null&&!arg1.equals(“”)){
Where_values+=arg1;
}
Count=Database.delete(“person”,where_values,arg2);
Break;
}
Return count;
F. public Cursor query(Uri arg0,String[] arg1, String arg2, String[] arg3,String arg4)
int flag = URI_MATCHER.match(arg0);
SQliteDatabase database = dbHelper.getReadDatabase();
Cursor cursor = null;
Switch(flag){
Case PERSON:
Long _id = ContentUris.parseId(arg0);
String where_values = “ _id = ”+_id;
If(arg2!=null&&!arg2.equals(“”)){
Where_values+=arg2;
}
Cursor=Database.query(“person”,arg1,where_values,arg3,null,null,arg4);
Break;
Case PERSONS:
Cursor = database.query(“person”,arg1,arg2,arg3,null,null,arg4);
Break;
}
Return cursor;
5. ContentProvider和LoaderManager结合使用
(1) 利用4中创建的ContentProvider作为数据源
(2) Activity实现LoaderCallBack<Cursor>,同时,需要重写几个方法
A. public Loader<Cursor>onCreateLoader(intarg0, Bundle arg1);
B. publicvoidonLoadFinished(Loader<Cursor> arg0, Cursor arg1);
C. publicvoidonLoaderReset(Loader<Cursor> arg0);
(3) 在activity中的onCreate()函数中获取LoaderManager,并用LoaderManager创建加载器。代码:
manager = getLoaderManager();//获取加载器管理器
manager.initLoader(1001,null,this);//创建加载器:3个参数:id;bundle;loadercallback<cursor>;
(4) 在public Loader<Cursor>onCreateLoader(intarg0, Bundle arg1)中创建一个加载器:
CursorLoader cursorLoader = new CursorLoader(this);
Uri uri = Uri.parse("content://com.example.android.PersonContentProvider/person");
cursorLoader.setProjection(new String[]{"name"});
cursorLoader.setUri(uri);
return cursorLoader;
(5) 在加载完成后,将Cursor传递给adapter,并传给listView
List<String> list = new ArrayList<String>();
while(arg1.moveToNext()) {
String nameString= arg1.getString(arg1.getColumnIndex("name"));
list.add(nameString);
}
adapter =new Myadapter(list);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
6. 使用ContentProvider管理联系人:
(1) Uri:
A. 联系人Uri:ContactsContract.Contacts.CONTENT_URI
B. 电话和e-mail的Uri
C.
(2) 具体操作查看具体API