Android 4.0.3 联系人(通讯录)应用源码学习
来源:互联网 发布:ubuntu获取arm gcc 编辑:程序博客网 时间:2024/05/16 03:49
http://blog.csdn.net/zhu_apollo/article/details/8763055
Contacts应用入口类有2个:PeopleActivity.java和DialtactsActivity.java。PeopleActivity是联系人入口类,DialtactsActivity是拨号入口类,Contacts集成了联系人和拨号功能。Contacts主界面如图1所示:
每个Tab都和一个Fragment对应,当选择某个标签时,对应的Fragment就会被调用显示。三个Fragment是:
- GroupBrowseListFragment.java(群组)
- DefaultContactBrowseListFragment.java(所有联系人)
- ContactTileListFragment.java(常用、收藏联系人)。
在入口类PeopleActivity.java中,采用getFragmentManager()方法获得FragmentManager实例便于管理Fragment,比如将Fragment从后台堆栈中弹出等。FragmentTransaction可以用来隐藏、添加、移除Fragment等操作,使用FragmentManager的beginTransaction方法,代码:
- FragmentManager fragmentManager = getFragmentManager();
- FragmentTransaction transaction = fragmentManager.beginTransaction()
再用add方法将fragment生成的view添加到容器中,该容器嵌入在activity的布局中:
- transaction.add(R.id.tab_pager, mFavoritesFragment, FAVORITE_TAG);
- transaction.add(R.id.tab_pager, mAllFragment, ALL_TAG);
- transaction.add(R.id.tab_pager, mGroupsFragment, GROUPS_TAG);
要使得add、删除等方法生效,必须使用commit方法提交这些事务:
- transaction.commitAllowingStateLoss();
commitAllowingStateLoss和commit的区别是当退出activity时,防止提交后的状态丢失。
mAllFragment是DefaultContactBrowseListFragment的实例,是“所有联系人”的fragment,他是多继承类,其结构如下图所示:
从图看出,DefaultContactBrowseListFragment最终继承于Fragment,ContactListAdapter是与listview对应的自定义适配器,最终继承于CompositeCursorAdapter,而CompositeCursorAdapter实际上继承于BaseAdapter,系统采用了CompositeCursorAdapter方法的好处在于它已经实现了getView方法,并且采用了缓存技术,代码如下:
- public View getView(int position, View convertView, ViewGroup parent) {
- ensureCacheValid();
- int start = 0;
- for (int i = 0; i < mSize; i++) {
- int end = start + mPartitions[i].count;
- if (position >= start && position < end) {
- int offset = position - start;
- if (mPartitions[i].hasHeader) {
- offset--;
- }
- View view;
- if (offset == -1) {
- view = getHeaderView(i, mPartitions[i].cursor, convertView, parent);
- } else {
- if (!mPartitions[i].cursor.moveToPosition(offset)) {
- throw new IllegalStateException("Couldn't move cursor to position "
- + offset);
- }
- view = getView(i, mPartitions[i].cursor, offset, convertView, parent);
- }
- if (view == null) {
- throw new NullPointerException("View should not be null, partition: " + i
- + " position: " + offset);
- }
- return view;
- }
- start = end;
- }
- throw new ArrayIndexOutOfBoundsException(position);
- }
它包含一个getView,具体实现是:
- protected View getView(int partition, Cursor cursor, int position, View convertView,
- ViewGroup parent) {
- View view;
- if (convertView != null) {
- view = convertView;
- } else {
- view = newView(mContext, partition, cursor, position, parent);
- }
- bindView(view, partition, cursor, position);
- return view;
- }
它判断convertView是否为空,如果是,就用newView方法创建一个,如果不是,就采用已有的,这种方法无需每次都创建View对象,提高了效率。需要我们实现的只有2个:
bindView方法和newView方法。newView方法在ContactListAdapter中实现,bindView在DefaultContactListAdapter中实现。
newView是用来创建ListView的item布局的:
- protected View newView(Context context, int partition, Cursor cursor, int position,
- ViewGroup parent) {
- ContactListItemView view = new ContactListItemView(context, null);
- view.setUnknownNameText(mUnknownNameText);
- view.setQuickContactEnabled(isQuickContactEnabled());
- view.setActivatedStateSupported(isSelectionVisible());
- return view;
- }
ContactListItemView继承ViewGroup,是每个item的布局,在这个布局中添加TextView显示联系人姓名,添加ImageView显示头像,再使用一个TextView显示姓名大写首字母。在ContactListItemView中,主要的实现方法有三个:
onMeasure, onLayout, dispatchDraw. onMeasure用来测量视图的大小尺寸,onLayout给视图布局,确定其位置,dispatchDraw起到分发的作用,正在画图的方法还是draw。
如果说newView是用来创建每个Item的布局,那么bindView是用来创建布局上每个子视图。bindVIew的代码如下:
- protected void bindView(View itemView, int partition, Cursor cursor, int position) {
- final ContactListItemView view = (ContactListItemView)itemView;
- view.setHighlightedPrefix(isSearchMode() ? getUpperCaseQueryString() : null);
- if (isSelectionVisible()) {
- view.setActivated(isSelectedContact(partition, cursor));
- }
- bindSectionHeaderAndDivider(view, position, cursor);
- if (isQuickContactEnabled()) {
- bindQuickContact(view, partition, cursor, ContactQuery.CONTACT_PHOTO_ID,
- ContactQuery.CONTACT_ID, ContactQuery.CONTACT_LOOKUP_KEY);
- } else {
- bindPhoto(view, partition, cursor);
- }
- bindName(view, cursor);
- bindPresenceAndStatusMessage(view, cursor);
- if (isSearchMode()) {
- bindSearchSnippet(view, cursor);
- } else {
- view.setSnippet(null);
- }
- }
其中:bindSectionHeaderAndDivider是创建第一行首字母和首字母下面蓝色下划线以及首字母右边的计数器;bindName创建姓名TextView;
ContactEntryListFragment中实现了Fragment的onCreateView方法,该方法创建Fragment对应的视图,创建代码是:
- mView = inflateView(inflater, container);
inflateView的实现代码:
- protected View inflateView(LayoutInflater inflater, ViewGroup container) {
- return inflater.inflate(R.layout.contact_list_content, null);
- }
布局文件contact_list_content.xml即是所有联系人的根布局。创建完视图后,采用setAdapter将适配器添加到ListView中即可。
- Android 4.0.3 联系人(通讯录)应用源码学习
- Android 4.0.3 联系人(通讯录)应用源码学习
- Android contacts 联系人 通讯录 源码 完全解析
- Android contacts 联系人 通讯录 源码 完全解析
- Android contacts 联系人 通讯录 源码 完全解析
- Android学习之联系人PinnedHeaderListView(通讯录)
- Android 获取通讯录联系人
- android通讯录 添加联系人
- Android 获取通讯录联系人
- android 搜索通讯录联系人
- Android-通讯录:添加联系人
- Android通讯录联系人操作
- Android读取通讯录联系人
- Android读取通讯录联系人
- android通讯录之联系人
- Android源码——通讯录联系人(一):Contacts数据库初识
- android获取手机通讯录联系人
- android 获取通讯录联系人信息
- ZOJ 3865 - Superbot(BFS)
- 公告类型:可变的滚动视图,文字长度根据制定长度进行换行
- android中关闭所有activity方法
- BZOJ 3944 Sum 数论
- nk.bin和nk.nb0区别
- Android 4.0.3 联系人(通讯录)应用源码学习
- oracle dbms_session package
- InvalidateRect()与Invalidate()的用法
- IPv6 stack中的一些小小的surprise---(1)
- SIP相关的RFC文档
- apache 遇到 core 问题
- Mac OS 下 eclipse中文乱码解决方法(eclipse for mac 中文乱码)
- 字符集和字符编码(Charset & Encoding)
- spring配置自定义的PropertyEditor