【Android基础笔记16】自定义ContentProvider

来源:互联网 发布:在线数据挖掘平台 编辑:程序博客网 时间:2024/06/09 20:26

一、自定义ContentProvider:
(一)、操作步骤:

1、编写一个类,必须继承自ContentProvider类;

2、实现ContentProvider类中所有的抽象方法;

    需要实现:onCreate() 、getType() 、query() 、insert() 、update()、delete() 等方法。


【备注:】

ContentProvider暴露出来的数据和方法并不是给自身调用的,而是给其他应用程序来调用。其他应用程序通过其ContentResolver对象调用的query() 、insert() 、update()、delete() 等方法就是我们在这里暴露出来的ContentProvider类中的重写后的query() 、insert() 、update()、delete() 方法。

3、定义ContentProvider的Uri。这个Uri是ContentResolver对象执行CRUD操作时重要的参数;

4、使用UriMatcher对象映射Uri返回代码;

5、在AndroidMainfest.xml文件中使用<provider>标签注册ContentProvider。


(二)、ContentProvider类中的六个抽象方法:

1、boolean onCreate() 

2、Uri insert(Uri uri, ContentValues values)

3、int delete(Uri uri, String selection, String[] selectionArgs)

4、int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

5、Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 

6、String getType(Uri uri) 


(三)、ContentProvider类中六个抽象方法的说明:

1、onCreate()   初始化provider

2、query()         返回数据给调用者

3、insert()         插入新数据到ContentProvider

4、update()       更新ContentProvider已经存在的数据

5、delete()        从ContentProvider中删除数据

6、getType()    返回ContentProvider数据的Mime类型


(四)、在清单文件中声明注册ContentProvider:


<provider android:name=".MyWordsProvider"
android:authorities="com.steven.wordscontentprovider"
android:exported="true"
/>

//android:name属性的值是:ContentProvider类的子类的完整路径;
//android:authorities属性的值是:content:URI中authority部分。一般就是将name属性的值全小写。
//android:exported属性是否允许其他应用调用。如果是false,则该ContentProvider不允许其他应用调用。

(五)、UriMatcher:
        继承ContentProvider类后发现,ContentProvider类中只有一个onCreate()生命周期方法——当其他应用程序通过ContentResolver第一次访问该ContentProvider时,onCreate()会被回调。
        其他应用在通过ContentResolver对象执行CRUD操作时,都需要一个重要的参数Uri。为了能顺利提供这个Uri参数,Android系统提供了一个UriMatcher工具类。

UriMatcher工具类提供了两个方法:
1、void addURI(String authority , String path , int code)  :  该方法用于向UriMatcher对象注册Uri。其中authority和path是Uri中的重要部分。而code代表该Uri对应的标示符。
2、int match(Uri uri) : 根据注册的Uri来判断指定的Uri对应的标示符。如果找不到匹配的标示符,该方法返回-1。

private static UriMatcher matcher = null;
static {
// 定义一个Uri匹配器。将UriMatcher.NO_MATCH,即-1作为参数。
matcher = new UriMatcher(UriMatcher.NO_MATCH);
// 定义一组匹配规则
matcher.addURI(AUTHORITY, "words", 1);
matcher.addURI(AUTHORITY, "newwords", 2);
}

【备注:】
        ContentProvider是单例模式的,当多个应用程序通过使用ContentResolver 来操作使用ContentProvider 提供的数据时,ContentResolver 调用的数据操作会委托给同一个ContentProvider 来处理。这样就能保证数据的一致性。


二、UriMatcher对象的addURI方法的#*问题:

(一)、#和*的含义:

1、UriMatcher.addURI(String authority, String path, int code)


Parameters:

authority the authority to match

path the path to match. * may be used as a wild card for any text, and # may be used as a wild card for numbers.

code the code that is returned when a URI is matched against the given components. Must be positive.


*和#是两个通配符,它们用在uri地址中,*可以匹配任何文本#匹配任何数字


(二)、截取Uri地址和拼接Uri地址的方法:【重点】

1、Uri对象的截取方法:

  • public abstract String getLastPathSegment ()
  • public abstract String getPath ()
  • public abstract List<String> getPathSegments ()


2、Uri对象的拼接方法:

  • public static Uri withAppendedPath (Uri baseUri, String pathSegment)


3、ContentUris对象的截取id的方法:

  • public static long parseId (Uri contentUri)


4、ContentUris对象的拼接id的方法:

  • public static Uri withAppendedId (Uri contentUri, long id)


备注:】Content URIs 的语法规则:content://authority/path/id 



(三)、创建ContentProvider的示例代码:

1、MyProvider.java中的核心代码:


public class MyContentProvider extends ContentProvider {

private SqliteHelper helper;

//创建urimatcher对象  次对象主要用来匹配client的uri是否正确

private static final UriMatcher uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);

private static final int QUERY=1;

private static final int INSERT=2;

private static final int UPDATE=3;

private static final int DELETE=4;

static{

/*addURI 参数说明

* 第一个参数表示 当前contentprovicer的权限设置

* 第二个参数表示 当前访问的uri对象的地址

* 第三个参数表示 如果client的uri地址与当前的地址匹配后返回的code

*/

uriMatcher.addURI("com.qianfeng.contentproviderserver","query", QUERY);//查询数据的uri

uriMatcher.addURI("com.qianfeng.contentproviderserver","insert", INSERT);//插入数据的uri

uriMatcher.addURI("com.qianfeng.contentproviderserver","update", UPDATE);//修改数据的uri

uriMatcher.addURI("com.qianfeng.contentproviderserver","delete", DELETE);//删除数据的uri

}

/**

* 提供给当前程序使用

* 表示contentProvider创建时系统回调的方法

*/

@Override

public boolean onCreate() {

helper=new SqliteHelper(getContext());

return false;

}

/**

* 提供给客户端应用程序使用

* 作用:访问当前应用程序中的数据 返回cursor对象

*/

@Override

public Cursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder) {

Cursor cursor=null;

if(uriMatcher.match(uri)==QUERY){//判断client传递的uri对象是否与指定的uri匹配

SQLiteDatabase db=helper.getWritableDatabase();

cursor=db.query("person", projection, selection, selectionArgs, null, null, sortOrder);

}

return cursor;

}

/**

* 返回contenturi的类型

*/

@Override

public String getType(Uri uri) {

// TODO Auto-generated method stub

return null;

}

/**

* 提供给客户端的应用程序使用

* 作用:向当前应用程序中指定的表中插入数据 返回的是当前新插入的数据row的uri对象

*/

@Override

public Uri insert(Uri uri, ContentValues values) {

if(uriMatcher.match(uri)==INSERT){

SQLiteDatabase db=helper.getWritableDatabase();

db.insert("person", null, values);

}

return null;

}

/**

* 提供给客户端的应用程序使用

* 作用:根据指定的条件删除指定表中的数据  返回删除的row的个数

*/

@Override

public int delete(Uri uri, String selection, String[] selectionArgs) {

int count=0;

if(uriMatcher.match(uri)==DELETE){

SQLiteDatabase db=helper.getWritableDatabase();

count=db.delete("person", selection, selectionArgs);

}

return count;

}

/**

* 提供给客户端的应用程序使用

* 作用:根据指定的参数修改当前应用程序中的表中的数据  返回的是修改成功的row的个数

*/

@Override

public int update(Uri uri, ContentValues values, String selection,

String[] selectionArgs) {

int count=0;

if(uriMatcher.match(uri)==UPDATE){

SQLiteDatabase db=helper.getWritableDatabase();

count=db.update("person", values, selection, selectionArgs);

}

return count;

}


}



(四)、ContentResolver中验证ContentProvider的示例代码

public class MainActivity extends Activity {

private ListView listView;

private ContentResolver contentResolver;

private String queryPath="content://com.qianfeng.contentproviderserver/query";//查询的path   content://权限/path

private String insertPath="content://com.qianfeng.contentproviderserver/insert";//插入的path 

private String updatePath="content://com.qianfeng.contentproviderserver/update";//修改的path 

private String deletePath="content://com.qianfeng.contentproviderserver/delete";//删除的path 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

listView=(ListView) findViewById(R.id.listview);

contentResolver=getContentResolver();

Cursor cursor=contentResolver.query(Uri.parse(queryPath),nullnullnullnull);

SimpleCursorAdapter adapter=new SimpleCursorAdapter(MainActivity.this

R.layout.activity_item, cursor, 

new String[]{"name","age"}, 

new int[]{R.id.textView_name,R.id.textView_age}, 

SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

listView.setAdapter(adapter);

}

/**

 * 操作contentprovider提供的数据

 * @param view

 */

public void click(View view){

switch (view.getId()) {

case R.id.button_add:

insertPerson();

break;

case R.id.button_update:

updatePerson();

break;

case R.id.button_delete:

deletePerson();

break;

}

}

/**

 * 删除数据的方法

 */

 public void deletePerson(){

 int count=contentResolver.delete(Uri.parse(deletePath), "_id=?"new String[]{2+""});

 if(count>0){

Toast.makeText(MainActivity.this"删除成功", Toast.LENGTH_SHORT).show();

 }else{

Toast.makeText(MainActivity.this"删除失败", Toast.LENGTH_SHORT).show();

 }

 }

/**

 * 修改数据的方法

 */

public void updatePerson(){

ContentValues values=new ContentValues();

values.put("name","赵四");

int count=contentResolver.update(Uri.parse(updatePath), values, "_id=?"new String[]{1+""});

if(count>0){

Toast.makeText(MainActivity.this"修改成功", Toast.LENGTH_SHORT).show();

}else{

Toast.makeText(MainActivity.this"修改失败", Toast.LENGTH_SHORT).show();

}

}

/**

 * 插入数据方法

 */

public void insertPerson(){

ContentValues values=new ContentValues();

values.put("_id", 1);

values.put("name","张三");

values.put("age", 20);

contentResolver.insert(Uri.parse(insertPath), values);

values=new ContentValues();

values.put("_id", 2);

values.put("name","小明");

values.put("age", 23);

contentResolver.insert(Uri.parse(insertPath), values);

}


}


0 0