Android开发之内容提供者——创建自己的ContentProvider(详解)
转载请注明出处:http://blog.csdn.net/dmk877/article/details/50387741
苦心人天不负卧薪尝胆三千越甲可吞吴,有志者天不负釜底抽薪百二秦川终属楚。这是一对非常励志的名言,每当读这句话都会被震撼一下,然后接着颓废,哈哈,最近的工作比较忙,也在这里提醒自己,一定要坚持下去,一定要坚持一件对自己有益的事情。
装逼到此进入正题,今天要讨论的主要内容是ContentProvider(内容提供者),ContentProvider也是android的四大组件之一,可见其在android中的重要性,可能大家用ContentProvider比其他三个组件用的少一点,但是ContentProvider同样的非常重要,有的人知道怎么使用ContentProvider,但是对于ContentProvider的原理等,并没有搞清楚,没关系,通过本篇博客相信你会对ContentProvider有一个全新的认识。
通过本篇博客你将学到以下知识
①什么是内容提供者
②为什么会有内容提供者
③怎样使用内容提供者
④ContentProvider中的Uri的详细介绍
⑤ContentResolver讲解
⑥UriMatch用法介绍
⑦ContentObserver用法详解
⑧通过一个案例来讲解自定义ContentProvider的执行过程(下一篇将给大家带来调用系统的ContentProvider)
1.什么是内容提供者?
首先我们必须要明白的是ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用比较少。ContentProvider为不同的软件之间数据共享,提供统一的接口。而且ContentProvider是以类似数据库中表的方式将数据暴露,也就是说ContentProvider就像一个“数据库”。那么外界获取其提供的数据,也就应该与从数据库中获取数据的操作基本一样,只不过是采用URI来表示外界需要访问的“数据库”。至于如何从URI中识别出外界需要的是哪个“数据库”这就是Android底层需要做的事情了,也就是说,如果我们想让其他的应用使用我们自己程序内的数据,就可以使用ContentProvider定义一个对外开放的接口,从而使得其他的应用可以使用我们自己应用中的文件、数据库内存储的信息。当然,自己开发的应用需要给其他应用共享信息的需求可能比较少见,但是在Android系统中,很多数据如:联系人信息、短信信息、图片库、音频库等,这些信息在开发中还是经常用到的,这些信息谷歌工程师已经帮我们封装好了,我们可以使用谷歌给我的Uri去直接访问这些数据。所以对于ContentProvider我们还是需要认真的学习的,在遇到获取联系人信息,图片库,音视频库等需求的时候,才能更好的实现功能。
关于怎样使用ContentProvider后面有实例帮助大家理解。
- getScheme() :获取Uri中的scheme字符串部分,在这里是http
- getSchemeSpecificPart():获取Uri中的scheme-specific-part:部分,这里是:http://www.baidu.com:8080/yourpath/fileName.html?
- getFragment():获取Uri中的fragment部分,即dmk
- getAuthority():获取Uri中Authority部分,即www.baidu.com:8080
- getPath():获取Uri中path部分,即/yourpath/fileName.html
- getQuery():获取Uri中的query部分,即id=15&name=du
- getHost():获取Authority中的Host字符串,即www.baidu.com
- getPost():获取Authority中的Port字符串,即8080
它的作用是在ContentProvider添加一个用于匹配的Uri,当匹配成功时返回code。Uri可以是精确的字符串,Uri中带有*表示可匹配任意text,#表示只能匹配数字。
③public int match(Uri uri) 这里的Uri就是传过来的要进行验证,匹配的Uri假如传过来的是:content://com.example.test/student/#,则content://com.example.test/student/10可以匹配成功,这里的10可以使任意的数字。
public final void registerContentObserver (Uri uri, boolean notifyForDescendents, ContentObserver observer)
注册一个观察者实例,当指定的Uri发生改变时,这个实例会回调实例对象做相应处理。
参数:uri:需要观察的Uri
notifyForDescendents:如果为true表示以这个Uri为开头的所有Uri都会被匹配到,
如果为false表示精确匹配,即只会匹配这个给定的Uri。
举个例子,假如有这么几个Uri:
①content://com.example.studentProvider/student
②content://com.example.studentProvider/student/#
③content://com.example.studentProvider/student/10
④content://com.example.studentProvider/student/teacher
假如观察的Uri为content://com.example.studentProvider/student,当notifyForDescendents为true时则以这个Uri开头的Uri的数据变化时都会被捕捉到,在这里也就是①②③④的Uri的数据的变化都能被捕捉到,当notifyForDescendents为false时则只有①中Uri变化时才能被捕捉到。
看到registerContentObserver 这个方法,根据语言基础我想大家能够想到ContentResolver中的另一个方法
public final voidunregisterContentObserver(ContentObserverobserver)它的作用就是取消对注册的那个Uri的观察,这里传进去的就是在registerContentObserver中传递进去的ContentObserver对象。到这关于注册和解除注册的ContentObserver可能大家都比较清楚了,那么问题来了,怎么去写一个ContentObserver呢?其实它的实现很简单,直接创建一个类继承ContentObserver需要注意的是这里必须要实现它的构造方法
public ContentObserver(Handlerhandler)
这里传进去的是一个Handler对象,这个Handler对象的作用一般要依赖于ContentObserver的另一个方法即
public void onChange(boolean selfChange)
这个方法的作用就是当指定的Uri的数据发生变化时会回调该方法,此时可以借助构造方法中的Handler对象将这个变化的消息发送给主线程,当主线程接收到这个消息之后就可以按照我们的需求来完成相应的操作,比如上面提到的类似于Adapter的notifyDataSetChanged()的作用,下面的案例也是完成了这个功能,准备工作完成之后来看一个案例,相信这个案例会让你对以上知识了解的更加深入。
8.案例(自定义ContentProvider)
在真正的开发中我们很少去自定义一个ContentProvider因为ContentProvider是为了更好的去共享数据,我们在开发中很少会遇到这种情况,而遇到更多的则是访问系统的ContentProvider,系统的ContentProvider谷歌工程师已经帮我们写好了,我们直接使用就可以了,这里为了让大家能够理解ContentProvider更加彻底,我们自定义一个ContentProvider然后在其它应用中来访问自定义的ContentProvider的数据这个案例的运行效果如下:
- package com.example.contentproviderpractice;
- import android.content.ContentProvider;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.UriMatcher;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.net.Uri;
- public class PeopleContentProvider extends ContentProvider {
- //这里的AUTHORITY就是我们在AndroidManifest.xml中配置的authorities,这里的authorities可以随便写
- private static final String AUTHORITY = “com.example.studentProvider”;
- //匹配成功后的匹配码
- private static final int MATCH_ALL_CODE = 100;
- private static final int MATCH_ONE_CODE = 101;
- private static UriMatcher uriMatcher;
- private SQLiteDatabase db;
- private DBOpenHelper openHelper;
- private Cursor cursor = null;
- //数据改变后指定通知的Uri
- private static final Uri NOTIFY_URI = Uri.parse(“content://” + AUTHORITY + “/student”);
- //在静态代码块中添加要匹配的 Uri
- static {
- //匹配不成功返回NO_MATCH(-1)
- uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- /**
- * uriMatcher.addURI(authority, path, code); 其中
- * authority:主机名(用于唯一标示一个ContentProvider,这个需要和清单文件中的authorities属性相同)
- * path:路径路径(可以用来表示我们要操作的数据,路径的构建应根据业务而定)
- * code:返回值(用于匹配uri的时候,作为匹配成功的返回值)
- */
- uriMatcher.addURI(AUTHORITY, ”student”, MATCH_ALL_CODE);// 匹配记录集合
- uriMatcher.addURI(AUTHORITY, ”student/#”, MATCH_ONE_CODE);// 匹配单条记录
- }
- @Override
- public boolean onCreate() {
- openHelper = new DBOpenHelper(getContext());
- db = openHelper.getWritableDatabase();
- return false;
- }
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- switch (uriMatcher.match(uri)) {
- /**
- * 这里如果匹配是uriMatcher.addURI(AUTHORITY, “student”,
- * MATCH_SUCCESS_CODE);中的Uri,则我们可以在这里对这个ContentProvider中的数据库
- * 进行删除等操作。这里如果匹配成功,我们将删除所有的数据
- */
- case MATCH_ALL_CODE:
- int count=db.delete(“personData”, null, null);
- if(count>0){
- notifyDataChanged();
- return count;
- }
- break;
- /**
- * 这里如果匹配是uriMatcher.addURI(AUTHORITY,
- * “student/#”,MATCH_ONE_CODE);中的Uri,则说明我们要操作单条记录
- */
- case MATCH_ONE_CODE:
- // 这里可以做删除单条数据的操作。
- break;
- default:
- throw new IllegalArgumentException(“Unkwon Uri:” + uri.toString());
- }
- return 0;
- }
- @Override
- public String getType(Uri uri) {
- return null;
- }
- /**
- * 插入 使用UriMatch的实例中的match方法对传过来的 Uri进行匹配。 这里通过ContentResolver传过来一个Uri,
- * 用这个传过来的Uri跟在ContentProvider中静态代码块中uriMatcher.addURI加入的Uri进行匹配
- * 根据匹配的是否成功会返回相应的值,在上述静态代码块中调用uriMatcher.addURI(AUTHORITY,
- * “student”,MATCH_CODE)这里的MATCH_CODE
- * 就是匹配成功的返回值,也就是说假如返回了MATCH_CODE就表示这个Uri匹配成功了
- * ,我们就可以按照我们的需求就行操作了,这里uriMatcher.addURI(AUTHORITY,
- * “person/data”,MATCH_CODE)加入的Uri为:
- * content://com.example.studentProvider/student
- * ,如果传过来的Uri跟这个Uri能够匹配成功,就会按照我们设定的步骤去执行相应的操作
- */
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- int match=uriMatcher.match(uri);
- if(match!=MATCH_ALL_CODE){
- throw new IllegalArgumentException(“Unkwon Uri:” + uri.toString());
- }
- long rawId = db.insert(“personData”, null, values);
- Uri insertUri = ContentUris.withAppendedId(uri, rawId);
- if(rawId>0){
- notifyDataChanged();
- return insertUri;
- }
- return null;
- }
- /**
- * 查询 如果uri为
- * content://com.example.studentProvider/student则能匹配成功,然后我们可以按照需求执行匹配成功的操作
- */
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- switch (uriMatcher.match(uri)) {
- /**
- * 如果匹配成功,就根据条件查询数据并将查询出的cursor返回
- */
- case MATCH_ALL_CODE:
- cursor = db.query(”personData”, null, null, null, null, null, null);
- break;
- case MATCH_ONE_CODE:
- // 根据条件查询一条数据。。。。
- break;
- default:
- throw new IllegalArgumentException(“Unkwon Uri:” + uri.toString());
- }
- return cursor;
- }
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- switch (uriMatcher.match(uri)) {
- case MATCH_ONE_CODE:
- long age = ContentUris.parseId(uri);
- selection = ”age = ?”;
- selectionArgs = new String[] { String.valueOf(age) };
- int count = db.update(“personData”, values, selection,selectionArgs);
- if(count>0){
- notifyDataChanged();
- }
- break;
- case MATCH_ALL_CODE:
- // 如果有需求的话,可以对整个表进行操作
- break;
- default:
- throw new IllegalArgumentException(“Unkwon Uri:” + uri.toString());
- }
- return 0;
- }
- //通知指定URI数据已改变
- private void notifyDataChanged() {
- getContext().getContentResolver().notifyChange(NOTIFY_URI, null);
- }
- }
package com.example.contentproviderpractice;import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;public class PeopleContentProvider extends ContentProvider {//这里的AUTHORITY就是我们在AndroidManifest.xml中配置的authorities,这里的authorities可以随便写private static final String AUTHORITY = "com.example.studentProvider";//匹配成功后的匹配码private static final int MATCH_ALL_CODE = 100;private static final int MATCH_ONE_CODE = 101;private static UriMatcher uriMatcher;private SQLiteDatabase db;private DBOpenHelper openHelper;private Cursor cursor = null;//数据改变后指定通知的Uriprivate static final Uri NOTIFY_URI = Uri.parse("content://" + AUTHORITY + "/student");//在静态代码块中添加要匹配的 Uristatic {//匹配不成功返回NO_MATCH(-1)uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);/*** uriMatcher.addURI(authority, path, code); 其中* authority:主机名(用于唯一标示一个ContentProvider,这个需要和清单文件中的authorities属性相同)* path:路径路径(可以用来表示我们要操作的数据,路径的构建应根据业务而定)* code:返回值(用于匹配uri的时候,作为匹配成功的返回值)*/uriMatcher.addURI(AUTHORITY, "student", MATCH_ALL_CODE);// 匹配记录集合uriMatcher.addURI(AUTHORITY, "student/#", MATCH_ONE_CODE);// 匹配单条记录}@Overridepublic boolean onCreate() {openHelper = new DBOpenHelper(getContext());db = openHelper.getWritableDatabase();return false;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {switch (uriMatcher.match(uri)) {/*** 这里如果匹配是uriMatcher.addURI(AUTHORITY, "student",* MATCH_SUCCESS_CODE);中的Uri,则我们可以在这里对这个ContentProvider中的数据库* 进行删除等操作。这里如果匹配成功,我们将删除所有的数据*/case MATCH_ALL_CODE:int count=db.delete("personData", null, null);if(count>0){notifyDataChanged();return count;}break;/*** 这里如果匹配是uriMatcher.addURI(AUTHORITY,* "student/#",MATCH_ONE_CODE);中的Uri,则说明我们要操作单条记录*/case MATCH_ONE_CODE:// 这里可以做删除单条数据的操作。break;default:throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());}return 0;}@Overridepublic String getType(Uri uri) {return null;}/*** 插入 使用UriMatch的实例中的match方法对传过来的 Uri进行匹配。 这里通过ContentResolver传过来一个Uri,* 用这个传过来的Uri跟在ContentProvider中静态代码块中uriMatcher.addURI加入的Uri进行匹配* 根据匹配的是否成功会返回相应的值,在上述静态代码块中调用uriMatcher.addURI(AUTHORITY,* "student",MATCH_CODE)这里的MATCH_CODE* 就是匹配成功的返回值,也就是说假如返回了MATCH_CODE就表示这个Uri匹配成功了* ,我们就可以按照我们的需求就行操作了,这里uriMatcher.addURI(AUTHORITY,* "person/data",MATCH_CODE)加入的Uri为:* content://com.example.studentProvider/student* ,如果传过来的Uri跟这个Uri能够匹配成功,就会按照我们设定的步骤去执行相应的操作*/@Overridepublic Uri insert(Uri uri, ContentValues values) {int match=uriMatcher.match(uri);if(match!=MATCH_ALL_CODE){throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());}long rawId = db.insert("personData", null, values);Uri insertUri = ContentUris.withAppendedId(uri, rawId);if(rawId>0){notifyDataChanged();return insertUri;}return null;}/*** 查询 如果uri为* content://com.example.studentProvider/student则能匹配成功,然后我们可以按照需求执行匹配成功的操作*/@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {switch (uriMatcher.match(uri)) {/*** 如果匹配成功,就根据条件查询数据并将查询出的cursor返回*/case MATCH_ALL_CODE:cursor = db.query("personData", null, null, null, null, null, null);break;case MATCH_ONE_CODE:// 根据条件查询一条数据。。。。break;default:throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());}return cursor;}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {switch (uriMatcher.match(uri)) {case MATCH_ONE_CODE:long age = ContentUris.parseId(uri);selection = "age = ?";selectionArgs = new String[] { String.valueOf(age) };int count = db.update("personData", values, selection,selectionArgs);if(count>0){notifyDataChanged();}break;case MATCH_ALL_CODE:// 如果有需求的话,可以对整个表进行操作break;default:throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());}return 0;}//通知指定URI数据已改变 private void notifyDataChanged() { getContext().getContentResolver().notifyChange(NOTIFY_URI, null); }}
可以看到在onCreate()方法中创建了一个数据库,关于数据库的操作大家可以看此博客http://blog.csdn.net/dmk877/article/details/44876805。这里就不多做介绍了。注意这个案例牵扯到两个项目,一个是包含我们自定义的ContentProvider,另一个项目是访问这个包含ContentProvider项目中的数据。
- <provider
- android:name=”com.example.contentproviderpractice.PeopleContentProvider”
- android:authorities=”com.example.student”
- android:exported=”true” >
- </provider>
<provider android:name="com.example.contentproviderpractice.PeopleContentProvider"android:authorities="com.example.student"android:exported="true" >
</provider>
- package com.example.otherapplication;
- import java.util.ArrayList;
- import com.example.otherapplication.adapter.MyAdapter;
- import com.example.otherapplication.bean.Student;
- import com.example.otherapplication.observer.PersonOberserver;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Handler;
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.database.Cursor;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ListView;
- public class MainActivity extends Activity implements OnClickListener {
- private ContentResolver contentResolver;
- private ListView lvShowInfo;
- private MyAdapter adapter;
- private Button btnInit;
- private Button btnInsert;
- private Button btnDelete;
- private Button btnUpdate;
- private Button btnQuery;
- private Cursor cursor;
- private static final String AUTHORITY = “com.example.studentProvider”;
- private static final Uri STUDENT_ALL_URI = Uri.parse(“content://” + AUTHORITY + “/student”);
- protected static final String TAG = “MainActivity”;
- private Handler handler=new Handler(){
- public void handleMessage(android.os.Message msg) {
- //在此我们可以针对数据改变后做一些操作,比方说Adapter.notifyDataSetChanged()等,根据业务需求来定。。
- cursor = contentResolver.query(STUDENT_ALL_URI, null, null, null,null);
- adapter.changeCursor(cursor);
- };
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- lvShowInfo=(ListView) findViewById(R.id.lv_show_info);
- initData();
- }
- private void initData() {
- btnInit=(Button) findViewById(R.id.btn_init);
- btnInsert=(Button) findViewById(R.id.btn_insert);
- btnDelete=(Button) findViewById(R.id.btn_delete);
- btnUpdate=(Button) findViewById(R.id.btn_update);
- btnQuery=(Button) findViewById(R.id.btn_query);
- btnInit.setOnClickListener(this);
- btnInsert.setOnClickListener(this);
- btnDelete.setOnClickListener(this);
- btnUpdate.setOnClickListener(this);
- btnQuery.setOnClickListener(this);
- contentResolver = getContentResolver();
- //注册内容观察者
- contentResolver.registerContentObserver(STUDENT_ALL_URI,true,new PersonOberserver(handler));
- adapter=new MyAdapter(MainActivity.this,cursor);
- lvShowInfo.setAdapter(adapter);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- //初始化
- case R.id.btn_init:
- ArrayList<Student> students = new ArrayList<Student>();
- Student student1 = new Student(“苍老师”,25,“一个会教学的好老师”);
- Student student2 = new Student(“柳岩”,26,“大方”);
- Student student3 = new Student(“杨幂”,27,“漂亮”);
- Student student4 = new Student(“张馨予”,28,“不知道怎么评价”);
- Student student5 = new Student(“范冰冰”,29,“。。。”);
- students.add(student1);
- students.add(student2);
- students.add(student3);
- students.add(student4);
- students.add(student5);
- for (Student Student : students) {
- ContentValues values = new ContentValues();
- values.put(”name”, Student.getName());
- values.put(”age”, Student.getAge());
- values.put(”introduce”, Student.getIntroduce());
- contentResolver.insert(STUDENT_ALL_URI, values);
- }
- break;
- //增
- case R.id.btn_insert:
- Student student = new Student(“小明”, 26, “帅气男人”);
- //实例化一个ContentValues对象
- ContentValues insertContentValues = new ContentValues();
- insertContentValues.put(”name”,student.getName());
- insertContentValues.put(”age”,student.getAge());
- insertContentValues.put(”introduce”,student.getIntroduce());
- //这里的uri和ContentValues对象经过一系列处理之后会传到ContentProvider中的insert方法中,
- //在我们自定义的ContentProvider中进行匹配操作
- contentResolver.insert(STUDENT_ALL_URI,insertContentValues);
- break;
- //删
- case R.id.btn_delete:
- //删除所有条目
- contentResolver.delete(STUDENT_ALL_URI, null, null);
- //删除_id为1的记录
- Uri delUri = ContentUris.withAppendedId(STUDENT_ALL_URI,1);
- contentResolver.delete(delUri, null, null);
- break;
- //改
- case R.id.btn_update:
- ContentValues contentValues = new ContentValues();
- contentValues.put(”introduce”,“性感”);
- //更新数据,将age=26的条目的introduce更新为”性感”,原来age=26的introduce为”大方”.
- //生成的Uri为:content://com.example.studentProvider/student/26
- Uri updateUri = ContentUris.withAppendedId(STUDENT_ALL_URI,26);
- contentResolver.update(updateUri,contentValues, null, null);
- break;
- //查
- case R.id.btn_query:
- //通过ContentResolver获得一个调用ContentProvider对象
- Cursor cursor = contentResolver.query(STUDENT_ALL_URI, null, null, null,null);
- //CursorAdapter的用法,参考此博客:http://blog.csdn.net/dmk877/article/details/44983491
- adapter=new MyAdapter(MainActivity.this,cursor);
- lvShowInfo.setAdapter(adapter);
- cursor = contentResolver.query(STUDENT_ALL_URI, null, null, null,null);
- adapter.changeCursor(cursor);
- break;
- }
- }
- }
package com.example.otherapplication;import java.util.ArrayList;import com.example.otherapplication.adapter.MyAdapter;
import com.example.otherapplication.bean.Student;
import com.example.otherapplication.observer.PersonOberserver;import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;public class MainActivity extends Activity implements OnClickListener {private ContentResolver contentResolver;private ListView lvShowInfo;private MyAdapter adapter;private Button btnInit;private Button btnInsert;private Button btnDelete;private Button btnUpdate;private Button btnQuery;private Cursor cursor;private static final String AUTHORITY = "com.example.studentProvider"; private static final Uri STUDENT_ALL_URI = Uri.parse("content://" + AUTHORITY + "/student");protected static final String TAG = "MainActivity"; private Handler handler=new Handler(){public void handleMessage(android.os.Message msg) {//在此我们可以针对数据改变后做一些操作,比方说Adapter.notifyDataSetChanged()等,根据业务需求来定。。cursor = contentResolver.query(STUDENT_ALL_URI, null, null, null,null);adapter.changeCursor(cursor);};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);lvShowInfo=(ListView) findViewById(R.id.lv_show_info);initData();}private void initData() {btnInit=(Button) findViewById(R.id.btn_init);btnInsert=(Button) findViewById(R.id.btn_insert);btnDelete=(Button) findViewById(R.id.btn_delete);btnUpdate=(Button) findViewById(R.id.btn_update);btnQuery=(Button) findViewById(R.id.btn_query);btnInit.setOnClickListener(this);btnInsert.setOnClickListener(this);btnDelete.setOnClickListener(this);btnUpdate.setOnClickListener(this);btnQuery.setOnClickListener(this);contentResolver = getContentResolver();//注册内容观察者contentResolver.registerContentObserver(STUDENT_ALL_URI,true,new PersonOberserver(handler));adapter=new MyAdapter(MainActivity.this,cursor);lvShowInfo.setAdapter(adapter);}@Overridepublic void onClick(View v) {switch (v.getId()) {//初始化case R.id.btn_init:ArrayList<Student> students = new ArrayList<Student>(); Student student1 = new Student("苍老师",25,"一个会教学的好老师"); Student student2 = new Student("柳岩",26,"大方"); Student student3 = new Student("杨幂",27,"漂亮"); Student student4 = new Student("张馨予",28,"不知道怎么评价"); Student student5 = new Student("范冰冰",29,"。。。");students.add(student1); students.add(student2); students.add(student3); students.add(student4); students.add(student5); for (Student Student : students) { ContentValues values = new ContentValues(); values.put("name", Student.getName()); values.put("age", Student.getAge()); values.put("introduce", Student.getIntroduce()); contentResolver.insert(STUDENT_ALL_URI, values); }break;//增case R.id.btn_insert:Student student = new Student("小明", 26, "帅气男人"); //实例化一个ContentValues对象ContentValues insertContentValues = new ContentValues(); insertContentValues.put("name",student.getName()); insertContentValues.put("age",student.getAge()); insertContentValues.put("introduce",student.getIntroduce()); //这里的uri和ContentValues对象经过一系列处理之后会传到ContentProvider中的insert方法中,//在我们自定义的ContentProvider中进行匹配操作contentResolver.insert(STUDENT_ALL_URI,insertContentValues);break;//删case R.id.btn_delete://删除所有条目contentResolver.delete(STUDENT_ALL_URI, null, null); //删除_id为1的记录 Uri delUri = ContentUris.withAppendedId(STUDENT_ALL_URI,1); contentResolver.delete(delUri, null, null);break;//改case R.id.btn_update:ContentValues contentValues = new ContentValues();contentValues.put("introduce","性感");//更新数据,将age=26的条目的introduce更新为"性感",原来age=26的introduce为"大方".//生成的Uri为:content://com.example.studentProvider/student/26Uri updateUri = ContentUris.withAppendedId(STUDENT_ALL_URI,26);contentResolver.update(updateUri,contentValues, null, null);break;//查case R.id.btn_query://通过ContentResolver获得一个调用ContentProvider对象Cursor cursor = contentResolver.query(STUDENT_ALL_URI, null, null, null,null);//CursorAdapter的用法,参考此博客:http://blog.csdn.net/dmk877/article/details/44983491adapter=new MyAdapter(MainActivity.this,cursor);lvShowInfo.setAdapter(adapter);cursor = contentResolver.query(STUDENT_ALL_URI, null, null, null,null);adapter.changeCursor(cursor);break;}}
}
- package com.example.otherapplication.observer;
- import android.database.ContentObserver;
- import android.os.Handler;
- import android.os.Message;
- public class PersonOberserver extends ContentObserver {
- private Handler handler;
- public PersonOberserver(Handler handler) {
- super(handler);
- this.handler=handler;
- }
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- //向handler发送消息,更新查询记录
- Message msg = new Message();
- handler.sendMessage(msg);
- }
- }
package com.example.otherapplication.observer;import android.database.ContentObserver;
import android.os.Handler;
import android.os.Message;public class PersonOberserver extends ContentObserver {private Handler handler;public PersonOberserver(Handler handler) {super(handler);this.handler=handler;}@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);//向handler发送消息,更新查询记录 Message msg = new Message(); handler.sendMessage(msg);}}
可以看到,在构造方法中接收了Handler然后当监听到指定的Uri的数据变化时就会通过Handler消息机制发送一条消息,然后的操作就由我们自行完成了。
好了,本篇关于ContentProvider的介绍主要是ContentProvider的基础知识,以及自定义一个ContentProvider并操作它的执行过程,如果大家发现博客中有错误的地方,欢迎批评指正,如有疑问欢迎留言,谢谢
转载请注明出处:http://blog.csdn.net/dmk877/article/details/50387741
Android开发之内容提供者——创建自己的ContentProvider(详解)相关推荐
- qt for android开发百度地图(一步步带图详解)
qt for android开发百度地图 前言:qt for android开发百度地图,其实找了很多资料,基本上没有,就自己折磨弄了出来,这个过程还是很曲折的,折磨了一两个星期,没有资料,就两个字' ...
- Android开发重点难点1:RelativeLayout(相对布局)详解
前言 啦啦啦~博主又推出了一个新的系列啦~ 之前的Android开发系列主要以完成实验的过程为主,经常会综合许多知识来写,所以难免会有知识点的交杂,给人一种混乱的感觉. 所以博主推出"重点难 ...
- Android开发效率提升利器-ButterKnife最全使用详解及ButterKnife插件的使用
本文目录 ButterKnife 概述 使用前准备 添加依赖 ButterKnife绑定 Activity绑定 Fragment绑定 RecyclerView Adapter绑定 基本用法 控件注解 ...
- Android开发--图形图像与动画(五)--详解LayoutAnimationController
首先需要先介绍下LayoutAnimationController: * 1.LayoutAnimationController用于为一个layout里面的控件,或者是一个ViewGroup * 里 ...
- android添加动画文件,Android开发之图形图像与动画(五)LayoutAnimationController详解
首先需要先介绍下LayoutAnimationController: * 1.LayoutAnimationController用于为一个layout里面的控件,或者是一个ViewGroup * 里面 ...
- 生成jni的android.mk,Android Studio 3.5版本JNI生成SO文件详解
学习在于记录,把自己不懂得容易忘记得记录下,才是最好得选择. 废话不多说,想要在Android开发中嵌入c/c++代码,直接开始如下步骤 1.创建需要调用的Java类 在你某个指定的包下创建如下类pa ...
- Android基础入门教程——8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash
Android基础入门教程--8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash 标签(空格分隔): Android基础入门教程 本节引言: 在Canva ...
- android启动页使用gif,android中使用react-native设置应用启动页过程详解
一.背景 在我们使用react-native进行编写代码的时候,当启动应用的时候,我们会看到如下界面 然而,这样的启动界面是非常的不又好,那么我们该怎么进行处理启动界面呢?有如下两种方案 二.方案 1 ...
- Android绘图Canvas十八般武器之Shader详解及实战篇(上)
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 前言 Android中绘图离不开的就是Canvas了,Canvas是一个庞大的知识体系,有java层的,也有jni层深入到Frame ...
- Android基础入门教程——2.5.3 AlertDialog(对话框)详解
Android基础入门教程--2.5.3 AlertDialog(对话框)详解 标签(空格分隔): Android基础入门教程 本节引言: 本节继续给大家带来是显示提示信息的第三个控件AlertDia ...
最新文章
- java-web——第十课 session
- MIT python 第二课第四十分钟 取最小值的例子
- Android Service的onStartCommand返回值用法
- 在react-router中进行代码拆分
- iOS开发必备指南合集之游戏接入GameCenter 指南
- linux7 无法连接网络,CentOS7无法连接网络怎么办
- Myesclipe+SSH+jsp+mysql+tomcate实现一个简单的CRM客户关系管理系统
- 浙江省二级计算机vfp,浙江省计算机2级vfp程序调试真题集.doc
- android开发学习——day3
- C语言逻辑运算符和||,一篇文章带你读懂逻辑表达式!
- hen Content must be served over https解决方案
- redis突然宕机数据会丢失吗
- 南清北复交北航哈工大中科院华科保研记
- JAVA实验3 学校教师类
- ThinkPHP 手册摘录之(跨模块)调用
- C# 模拟POST上传图片
- 手眼标定_全面细致的推导过程
- idea自动排版html,idea怎么格式化代码?
- 【Arduino+ESP32专题】PlatformIO串口监视器的默认波特率修改
- 电源适配器的作用有哪些
热门文章
- 2020年过去了,我很怀念它
- d3dx9_42.dll缺少
- 推荐系统-协同过滤在Spark中的实现
- 【SQL】实验十 数据库完整性实验
- 场外模拟 省选联考(B卷) 2020 游记
- CorelDRAW入门教程
- gmail更改个人信息_如何在不创建新电子邮件地址的情况下更改Gmail名称
- 制作3D实时交互影像产品,需要用到的技术和软件!
- [Contrastive Learning] Improving Contrastive Learning by Visualizing Feature Transformation
- Ubuntu 18.04 firefox浏览器装flash