您的位置:首页 > 数据库

ViewContactActivity的基本流程

2012-09-06 17:28 204 查看
这是我对ViewContactActivity的大体流程的理解,希望对此熟悉的大虾们帮忙指正。

进入通讯录,会显示一个联系人的列表,点击其中一个item,会进入某个具体联系人的详情界面,这个界面就是ViewContactActivity,对于sim卡上的联系人只有手机号码这一项,对于本地联系人来说,包括手机号码、email、公司等等条目。

1. 在onCreate中会从intent中获取到一个URI: content://com.android.contacts/contacts/lookupId/contact_id

2. 在onResume中startEntityQuery就是具体来进行数据库访问操作了, 第一个数据库访问是在UI线程中直接调用query(),这里要把最初的URI转换一下,转换成URI=content://com.android.contacts/contacts/contact_id/data, PROJECTION={name_raw_contact_id, display_name_source, lookup} ,在跟踪数据库操作的过程中,发现这个访问实际是从view_data中获取数据,最终拼接成的SQL执行语句是:SELECT
name_raw_contact_id, display_name_source, lookup FROM view_data data WHERE (1 AND contact_id=?)  selectionArgs=13。  说到这个view_data,它可是有一堆的column,感觉把所有相关的数据项都包括了,而且联接了一堆的table,既有内部联接 join, 也有外部联接 left join,比如data,mimetypes,raw_contacts,contacts把这些表都联接起来了,以data的记录条目为主记录。
这里我也顺带复习了一下JOIN和AS的用法, 当第二次联接(JOIN)同一个table时,要记得给这个table其一个别名(AS),否则无法和前面的table区分开来,会报错。另外,sqlite只支持LEFT JOIN,不支持RIGHT JOIN和FULL JOIN。view_data的数据项虽多,不过URI 携带的PROJECTION只有3个字段,所以最后也就返回了3个值, query返回cursor后, 校验一下得到lookup_id和我们最初已知的lookup_id是否一致,如果不一致,则返回出错NULL。

3. 第二个数据库访问时通过AsyncQueryHandler来调用的,这是个异步操作,会建立一个子线程来负责进行数据访问,得到数据后返回给UI线程。函数调用startQuery()URI=content://com.android.contacts/raw_contact_entities,selection = contact_id, selectionArgs=13。 这个数据项就多了,在数据库中跟踪得到SQL最终访问语句为:SELECT data_version, contact_id, version,
data12, data11, data10, mimetype, res_package, _id, data15, data14, data13, name_verified, is_restricted, is_super_primary, data_sync1, dirty, data_sync3, data_sync2, data_sync4, account_type, data1, sync4, sync3, data4, sync2, data5, sync1, data2, data3,
data8, data9, deleted, group_sourceid, data6, data7, account_name, data_id, starred, sourceid, is_primary FROM contact_entities_view WHERE (1) AND (contact_id=?)  SELECTIONARGS=13

子线程访问得到数据后,会通知UI线程调用onQueryComplete()来处理数据。

4. 在onQueryComplete()中启动一个AsyncTask.execute( ),AsyncTask也是一个异步操作,也建立了一个子线程,doInBackground()是在子线程中执行的,它将cursor数据存储到一个ArrayList<Entity>中,以便后续UI线程来显示VIEW。按照我的理解和对contact_entities_view这个view的查看,cursor得到的数据条目不止一个,因为一个联系人要包含name/number等若干条信息,所以至少有两个,name和number,不过在doInBackground的处理中,把cursor的数据都存到了一个entity,在这个ArrayList<Entity>集合中,一个联系人只对应一个entity。entity生成后,
UI线程调用onPostExecute来得到处理后的entity,注意这个函数的入口参数就是doInBackground的返回结果。在onPostExecute中把entity再转存到mSections中,mSections也是一个数据集合,ArrayList<ArrayList<ViewEntry>>,它的每一个数据单元仍旧是一个集合,包括mPhoneEntries/mSmsEntries/mEmailEntries等9个子集合,关联起来说,就是从ArrayList<Entity>中拿出一个entity来,这个entity对应一个联系人的所有信息,其中把号码存储到mSections.mPhoneEntries中,把email存储到mSections./mEmailEntries中,以此类推。
同时注意由于每个联系人可能不只一个号码或者email,所以mPhoneEntries/mEmailEntries等也是一个集合。mSections生成后,建立adapter,设置到listview中。

            mAdapter = new ViewAdapter(this, mSections);

            mListView.setAdapter(mAdapter);

 5. 第三个数据库操作也是通过AsyncQueryHandler来调用startQuery,URI=content://com.android.contacts/contacts/13/data,PROJECTION=[_id, status, status_res_package, status_icon, status_label, status_ts, mode],SELECTION=mode IS NOT NULL OR status IS NOT NULL。 在数据库中得到最终的SQL语句是:SELECT
_id, status_updates.status AS status, status_updates.status_res_package AS status_res_package, status_updates.status_icon AS status_icon, status_updates.status_label AS status_label, status_updates.status_ts AS status_ts, presence.mode AS mode FROM view_data
data LEFT OUTER JOIN presence ON (presence_data_id=data._id) LEFT OUTER JOIN status_updates ON (status_updates.status_update_data_id=data._id) WHERE (1 AND contact_id=?) AND (mode IS NOT NULL OR status IS NOT NULL)  selectionARgs=13

这里都是些状态位,估计是用作状态检查吧,大概知道这些。

6.  接下来就是listview的显示了, listview设置了adapter,就要看adapter中的getview实现了,getview()就是从mSections中取数据,从它的9个子集合中把数据依次取出来,比如mPhoneEntries这个子集合中存储了2个号码,mEmailEntries这个子集合中存储了一个email,那么getview()就会执行3次,第一次取第一个号码,生成一个item条目显示在listview中,第二次再取第2个号码,生成一个item条目显示在listview中,第三次取email,生成一个item条目显示在listview中,这样总共有3个item条目在listview中,我们看到的界面详情上就有3行数据了。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息