您的位置:首页 > 移动开发 > Android开发

Android-ContentProvider

2016-07-13 11:11 489 查看
一、概述

      当某个应用需要提供数据给其他应用时,它就要继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享它的数据了。
虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同(如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据)。而使用ContentProvider共享数据的好处是统一了数据访问方式。
 
      补充:要了解ContentProvider,需要从提供者和解析者两方面进行探究。
 
二、提供者的应用
     
关键点1、继承ContentProvider内容提供者对象
关键点2、实现ContentProvider的如下方法(供内容解析者应用调用):
(1)public int delete(Uri uri, String selection, String[] selectionArgs)
解释:该方法在ContentProvider创建后就会被调用, Android开机后, ContentProvider在其它应用第一次访问它时才会被创建。
 
(2)public String getType(Uri uri)
解释:该方法用于供外部应用往ContentProvider添加数据。
 
(3)public Uri insert(Uri uri, ContentValues values)
解释:该方法用于供外部应用从ContentProvider删除数据。
 
(4)public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)
解释:该方法用于供外部应用更新ContentProvider中的数据。
 
(5)public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs)
解释:该方法用于供外部应用从ContentProvider中获取数据。

关键点3、在AndroidMainfest.xml中对ContentProvider进行注册。
<provider
android:name = “包名.该类的名”
android:authorities = “域名路径” >
</provider>
例如:
<provider
android:name = “com.sqb.MyProvider”
android:authorities = “com.a.b” >
</provider>
 
关键点4、创建共享的数据(一般是SQLite数据库里的数据)
解释:这个应用应当创建一个数据库,获取到SQLiteOpenHelper对象,然后对数据库的增删改查操作分别放到ContentProvider的实现方法里面。
 
关键点5、Uri
解释:详细请看http://blog.csdn.net/dmk877/article/details/50387741
(1)用Uri的静态方法parse将路径字符串转化为内容解析者所识别的Uri,只有当内容解析者提供符合内容提供者定义的Uri调用增删改查的方法才有效。
例如:Uri uri = Uri.parse("content://" +”com.a.b”+ "/student")



关键点6、UriMatcher
解释:
UriMatcher 类主要用于匹配Uri.这里的匹配是发生在ContentProvider中的,假如我们向ContentProvider中插入一条数据,不可能为所欲为的想怎么干就怎么干,在ContentProvider肯定要做一个判断,只有在符合条件下才会去执行你想要执行的操作,这里的判断就是用UriMatch进行匹配,假如是系统的ContentProvider如联系人、图库、视频库等,这些系统都提供了Uri我们可以根据系统提供的Uri来操作相应的数据。查阅谷歌官方文档你会发现有这么几个方法:
(1)public Uri Matcher(int code)

//它的作用就是创建一个UriMatch对象
(2)public void addURI(String authority,String path, int code)
//它的作用是在ContentProvider添加一个用于匹配的Uri,当匹配成功时返回code。Uri可以是精确的字符串,Uri中带有*表示可匹配任意text,#表示只能匹配数字。
(3)public int match(Uri uri)

//这里的Uri就是传过来的要进行验证,匹配的Uri假如传过来的是:content://com.example.test/student/#,则content://com.example.test/student/10可以匹配成功,这里的10可以使任意的数字。
 
例如:
//UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher uriMatcher= new UriMatcher(UriMatcher.NO_MATCH);
//往UriMatcher类里面添加一个拼凑的Uri
uriMatcher.addURI(“com.a.b”, "student", 100);//
匹配记录集合,100表示code
uriMatcher.addURI(“com.a.b”, "student/#", 101);//
匹配单条记录
 
三、解析者的应用
关键点1、ContentResolver内容解析者
解释:当其他应用想要获取内容提供的数据时并不直接调用内容提供者对外开放的统一接口方法,而是使用一个
ContentResolver 对象,调用ContentResolver
的方法作为替代。ContentResolver可以与任意内容提供者进行会话,与其合作来对所有相关交互通讯进行管理。当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Context提供的getContentResolver()方法。
例如:ContentResolver contentResolver = getContentResolver();
 
ContentResolver
类也提供了与ContentProvider类相对应的四个方法:
(1)public Uri insert(Uri uri, ContentValues values)    
//该方法用于往ContentProvider添加数据。
 
(2)public int delete(Uri uri, String selection, String[] selectionArgs)
  
//该方法用于从ContentProvider删除数据。
 
(3)public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs)   
//该方法用于更新ContentProvider中的数据。
 
(4)public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)   
//该方法用于从ContentProvider中获取数据。
 
关键点2、ContentObserver内容观察者
解释1:观察指定的Uri引起的数据库的变化,然后通知主线程,根据需求做我们想要做的处理。这样说大家可能理解的不是特别透彻,这样跟大家说它可以实现类似于Adapter的notifyDataSetChanged()这个方法的作用,比方说当观察到ContentProvider的数据变化时会自动调用谷歌工程师给我们提供的好的方法,可以在此方法中通知主线程数据改变等等。那么问题来了,应该怎样实现这样的功能呢?首先要做的就是注册这个观察者,这里的注册是在需要监测ContentProvider的应用中进行注册并不是在ContentProvider中而在ContentProvider中要做的就是当数据变化时进行通知,这里的通知的方法谷歌已经帮我们写好,直接调用就行了。
这里还要注册一个观察者实例,当指定的Uri发生改变时,这个实例会回调实例对象做相应处理。通过ContentResolver(注意这个不是观察者)调用如下方法:
public final void registerContentObserver (Uri uri, boolean notifyForDescendents, ContentObserver observer)
//参数uri:需要观察的Uri,也就是某个内容提供者定义的Uri.
//参数
notifyForDescendents:如果为true表示以这个Uri为开头的所有Uri都会被匹配到,如果为false表示精确匹配,即只会匹配这个给定的Uri。
//参数
observer:内容观察者
 
解释2:内容观察者创建说明。需要创建一个类,继承ContentObserver,注意的是这里必须要实现它的构造方法
public ContentObserver(Handler handler)
这里传进去的是一个Handler对象,这个Handler对象的作用一般要依赖于ContentObserver的另一个方法即
public void onChange(boolean selfChange)
这个方法的作用就是当指定的Uri的数据发生变化时会回调该方法,此时可以借助构造方法中的Handler对象将这个变化的消息发送给主线程,当主线程接收到这个消息之后就可以按照我们的需求来完成相应的操作,比如上面提到的类似于Adapter的notifyDataSetChanged()的作用。
 
关键点3、CursorAdapter
解释:1:CursorAdapter是继承了BaseAdapter后覆盖它的getView方法在getView方法中调用了newView和bindView方法,我们在写CursorAdapter时必须实现它的两个方法
public void bindView(View view, Context context, Cursor cursor)

public View newView(Context context, Cursor cursor, ViewGroup parent)

(1)newView:并不是每次都被调用的,它只在实例化的时候调用,数据增加的时候也会调用,但是在重绘(比如修改条目里的TextView的内容)的时候不会被调用
(2)bindView:从代码中可以看出在绘制Item之前一定会调用bindView方法它在重绘的时候也同样被调用
解释2:CursorAdapter还有一个重要的方法

public void changeCursor (Cursor cursor)
该方法的功能类似于adapter.notifyDataSetChanged()方法
 
参考资料:
1、参考博客:http://blog.csdn.net/dmk877/article/details/50387741(这篇博客有源码)
2、CursorAdapter详解:http://blog.csdn.net/dmk877/article/details/44983491
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息