该文总结下工作当中维护的联系人模块中的数据查询流程。该流程在很多系统APP上都类似,了解这个过程还是很有必要的。
在Android应用框架中一般都会划分为三层:数据层、数据访问层和业务层。数据层基本都是用sqlite来存储数据,数据访问层是借用四大组件中的内容提供器来实现,业务层就是各个应用,比如电话本。三层结构如下图所示:
这里将详细总结下电话本对数据库的查询流程。
1、创建数据库
当系统启动,所有服务都准备好之后,ContactsUpgradeReceiver类将接受到重启广播,在广播接受类中会去获取联系人数据的实例,在获取实例当中会去创建数据库和表,如下图所示:
2、内容提供器的创建
联系人当中用到最多的数据访问接口都是在ContactsProvider2中创建的。它提供了一些增删改查的接口,这些接口其实就是借用前面创建的数据库进行操作。
3、业务层数据查询流程
当数据层和数据访问层都准备好之后,业务层才可以调用接口。下面给出一个联系人主界面查询数据的大致流程。
联系人的主界面一般会分为几个碎片,每个碎片代表一个界面,在碎片的父类当中会实现数据的异步查询。
举例:DefaultContactBrowseListFragment
它的父类ContactEntryListFragment封装了大部分的工作。包括创建适配器、加载页面、创建查询加载器和查询结束。
子类一般会根据业务的需求来进行各种定制。它的工作有创建适配器、加载页面、创建查询加载器。其实就是对父类实现类的覆盖。在适配器中还会对查询加载器进行查询配置。适配器也有跟碎片一样的实现模式,大部分操作都在父类DefaultContactListAdapter中实现,用户也可以继承它来进行各种查询定制。比如联系人对SIM卡的过滤、对没有分组成员的过滤等等。具体的流程图如下所示:
查询完会返回一个Cursor对象,适配器会用这个对象进行数据和页面控件的绑定。
在业务层中会根据loader机制,最后会调用内容提供器注册的uri,进行异步查询,如下:
final Cursor cursor = getActivity().getContentResolver().query(Contacts.CONTENT_URI,
LOOKUP_PROJECTION, Contacts.IN_VISIBLE_GROUP + "!=0", null, null);
接着会根据binder机制走到ContactsProvider2中的查询接口进行查询。在queryLocal方法中会匹配不同的uri进行表的映射和查询配置。