ContentProvider使用场景解读
发布日期:2021-05-06 23:33:01 浏览次数:23 分类:精选文章

本文共 3523 字,大约阅读时间需要 11 分钟。

在这里插入图片描述

为什么需要ContentProvider?

我们知道,一个软件系统的架构通常是这样的:

在这里插入图片描述
为了降低上层业务对底层数据的依赖,需要增加一个数据访问层来解耦,我们今天要说的ContentProvider充当的就是数据访问层的角色。ContentProvider提供了一些通用的接口来实现对底层数据(其实是数据库中的表结构数据)进行操作。

ContentProvider是什么?

ContentProvider是Android提供给上层的一个组件,主要用于实现数据访问的统一管理和数据共享。这里的数据管理是通过定义统一的访问接口来完成,如增删改查。同时,它采用了类似Internet的URL机制,将数据以URI的形式来标识,这样其他App就可以采用一套标准的URI规范来访问同一处数据,而不用关心具体的实现细节。我们知道在Android系统中可能会涉及到一个App的数据被其他App使用的情况,比如通讯录,日历,短信等,这时就需要一套能实现数据共享的机制,这里的ContentProvider就可以提供该功能,其底层使用了binder来完成App进程之间的通信,同时使用匿名共享内存来作为共享数据的载体。当然为了保证数据访问的安全性,ContentProvider还对每处的数据URI增加了权限管理机制,以控制该数据的访问者及访问方式。

如何使用ContentProvider?

ContentProvider提供了一套通用的数据访问接口,示例代码如下:

public class MyContentProvider extends ContentProvider {       public MyContentProvider() {       }    @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 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 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 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");    }}

咋一看,这些接口貌似跟数据库的访问接口类似。没错,ContentProvider就是专门来管理数据库中的数据的。那么既然作为通用的数据访问接口,ContentProvider为什么没有提供对普通文件的访问接口呢?我猜测是因为普通文件的数据是非结构化的,无法抽象出一套统一的访问接口,而数据库中的数据都是结构化数据,就相对比较容易了。

此外一般我们不会直接使用ContentProvider来访问,而是会通过ContentResolver来访问ContentProvider,为什么?因为ContentProvider作为一个数据源处理中心,不止给App内部使用,还会被其他App访问。所以这里的ContentProvider就好比一个server,其他的App在访问这个ContentProvider的时候都必须先获得一个Server的Client才行,这里的ContentResolver就是Android提供给开发者使用来得到一个ContentProvider Client的管理工具类。示例代码如下:

//根据号码获取联系人的姓名public void getContactNameByNumber() throws Exception {       ContentResolver resolver = getContentResolver();    Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, new String[]{   ContactsContract.Data.DISPLAY_NAME}, null, null, null);    if(cursor.moveToFirst()){           String name = cursor.getString(0);        Log.i(TAG, name);    }    cursor.close();}

此外我们在创建一个ContentProvider组件的时候,必须要声明一个authorities,并且必须保证系统内该字段不重名,它就好比URL中的主机地址。示例如下:

最后再说下为何ContentProvider在我们平时开发App中使用的不多?其实,虽然ContentProvider具有数据管理和数据共享的功能,但是多半的优势还是集中在数据共享上,在数据共享的前提下,这个数据管理的优势也才能更加明显。像一些系统内置应用,联系人,日历和短信,就比较适合使用ContentProvider,因为他们经常需要给其他App提供数据。而对于像普通App,一般出于安全原因,不会把数据提供给第三方App使用,而在App内部访问数据库的话,完全可以自己实现一套数据库访问框架,因为ContentProvider为了屏蔽数据库的访问细节,实质上是在其基础上再封装了一层接口而已,而对于App内部的数据库访问来说,没有这个必要,而且ContentProvider作为一个组件与系统依赖性较强,相比自己实现一套数据库管理框架,扩展性和灵活性肯定没那么好。当然也有很多第三方开源的数据库框架可用,比如greenDao,ormlite,realm等。

上一篇:ElasticSearch知识汇总
下一篇:Zookeeper知识汇总

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月28日 07时36分58秒