今天记录一下用AsyncTask和AsyncQueryHandler结合获取手机联系人信息的实例。代码都是老师的教导,首先简要介绍一下AsyncTask和AsyncQueryHandler。
AsyncTask
相对来说AsyncTask是轻量级的,适用于简单的异步处理,不需要借助线程和Handler即可实现。AsyncTask是抽象类,所以需要将其子类化,然后实现其回掉方法, AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。
四个主要的回掉方法:
onPreExecute() 当任务执行之前开始调用此方法,可以在这里显示进度对话框。
doInParams... ) 此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress...)来更新任务的进度。
onProgressUpdate(Progress...) 此方法在主线程执行,用于显示任务执行的进度。
onPostExecute(Result) 此方法在主线程执行,任务执行的结果作为此方法的参数返回。
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。
AsyncQueryHandler
在一般的应用中可以使用ContentProvider去操作数据库。这在数据量很小的时候是没有问题的,但是如果数据量大了,可能导致UI线程发生ANR异常(超过5秒)。当然你也可以写个Handler去做这些操作,只是你每次使用ContentProvider时都要再写个Handler,必然降低了效率,使用AsyncQueryHandler就可解决上述问题。
AsyncQueryHandler提供四种方法startInsert,startDelete,startUpdate,startQuery这四个操作,并提供相对应的onXXXComplete方法,以供操作完数据库后进行其它的操作,这四个onXXXComplete方法都是空实现,以便我们只需要去实现我们关注的操作。AsyncQueryHandler的使用只需要继承AsyncQueryHandler类,并提供onXXXComplete方法的实现(可以实现任何一个或多个,当然你也可以一个也不实现,如果你不关注操作数据库的結果),在你的实现中做一些对数据库操作完成的处理。
使用时直接调用startXXX方法即可。传入的通用参数如下:
int token,一个令牌,需要跟onXXXComplete方法传入的一致。(当然你也可以不一致,同样在数据库的操作结束后会调用对应的onXXXComplete方法 )
Object cookie,你想传给onXXXComplete方法使用的一个对象。(没有的话传递null即可。基本发现这个变量没太大作用)
Uri uri
下面上实例的代码:
第一步毫无疑问当然是加权限:android.permission.READ_CONTACTS
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" tools:ignore="HardcodedText" > <Button android:id="@+id/bt_getCantacts" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="获取联系人信息" /> </LinearLayout>
ContactBean.java
package com.anjoyo.cantact; public class ContactBean { private int contactId;//联系人ID private String displayName;//联系人姓名 private String phoneNum;//联系人手机号 private String sortKey;//排序Key private Long photoId;//头像ID private String lookUpKey; private int selected = 0;//被选中的行号 private String formattedNumber;//被格式化的号码 private String pinyin;//姓名对应的汉语拼音 public int getContactId() { return contactId; } public void setContactId(int contactId) { this.contactId = contactId; } public String getDisplayName() { return displayName; } public void setDisplayName(String displayName) { this.displayName = displayName; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getSortKey() { return sortKey; } public void setSortKey(String sortKey) { this.sortKey = sortKey; } public Long getPhotoId() { return photoId; } public void setPhotoId(Long photoId) { this.photoId = photoId; } public String getLookUpKey() { return lookUpKey; } public void setLookUpKey(String lookUpKey) { this.lookUpKey = lookUpKey; } public int getSelected() { return selected; } public void setSelected(int selected) { this.selected = selected; } public String getFormattedNumber() { return formattedNumber; } public void setFormattedNumber(String formattedNumber) { this.formattedNumber = formattedNumber; } public String getPinyin() { return pinyin; } public void setPinyin(String pinyin) { this.pinyin = pinyin; } }
CantactsDemoActivity.java
package com.anjoyo.cantact; import java.util.ArrayList; import android.app.Activity; import android.content.AsyncQueryHandler; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.ContactsContract; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class CantactsDemoActivity extends Activity { private Button myCantacts; private AsyncQueryHandler asyncQuery; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myCantacts = (Button) this.findViewById(R.id.bt_getCantacts); myCantacts.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { asyncQuery = new MyAsyncQueryHandler(getContentResolver()); initSQL(); } }); } protected void initSQL() { // 联系人URI Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; // 联系人ID,联系人NAME, String[] projection = { ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.DATA1, "sort_key", ContactsContract.CommonDataKinds.Phone.CONTACT_ID, }; asyncQuery.startQuery(0, null, uri, projection, null, null, "sort_key COLLATE LOCALIZED asc"); } private class MyAsyncQueryHandler extends AsyncQueryHandler { public MyAsyncQueryHandler(ContentResolver cr) { super(cr); } protected void onQueryComplete(int token, Object cookie, Cursor cursor) { querying(cursor); } } private void querying(final Cursor cursor) { Handler handlerInsertOrder = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case MyAsyncTask.DOWNLOADING_START_MESSAGE: System.out.println("begin to sort out t9"); break; case MyAsyncTask.DOWNLOAD_END_MESSAGE: Bundle bundle1 = msg.getData(); ArrayList<ContactBean> list = (ArrayList<ContactBean>) bundle1 .get("完成"); for (ContactBean ci : list) { System.out.println(ci.getDisplayName()); System.out.println(ci.getPhoneNum()); System.out.println("--------------------------------"); } break; default: break; } super.handleMessage(msg); } }; MyAsyncTask.startRequestServerData(this, handlerInsertOrder, cursor); } }
MyAsyncTask.java
package com.anjoyo.cantact; import java.util.ArrayList; import android.content.Context; import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; public class MyAsyncTask extends AsyncTask<Cursor, Void, ArrayList<ContactBean>> { /** 开始整理 */ public static final int DOWNLOADING_START_MESSAGE = 7; /** 整理结束 */ public static final int DOWNLOAD_END_MESSAGE = 17; private Context mContext = null; private Handler mHandler = null; protected MyAsyncTask(Context context, Handler handler) { this.mContext = context; this.mHandler = handler; } @Override protected void onPreExecute() { sendStartMessage(DOWNLOADING_START_MESSAGE); } @Override protected ArrayList<ContactBean> doInCursor... params) { // 只需要把原来放在子线程的代码放到这个方法就行 Cursor cursor = params[0]; ArrayList<ContactBean> ciList = new ArrayList<ContactBean>(); if (cursor != null && cursor.getCount() > 0) { try { cursor.moveToFirst(); for (int i = 0; i < cursor.getCount(); i++) { cursor.moveToPosition(i); String name = cursor.getString(1); String number = cursor.getString(2); int contactId = cursor.getInt(4); ContactBean contactInfo = new ContactBean(); contactInfo.setContactId(contactId); contactInfo.setPhoneNum(number); contactInfo.setDisplayName(name); if (contactInfo.getDisplayName() == null) { contactInfo.setDisplayName(contactInfo.getPhoneNum()); } ciList.add(contactInfo); } } catch (Exception e) { e.printStackTrace(); } } return ciList; } @Override protected void onPostExecute(ArrayList<ContactBean> result) { sendEndMessage(DOWNLOAD_END_MESSAGE, result); } public static void startRequestServerData(Context context, Handler handler, Cursor cursor) { new MyAsyncTask(context, handler).execute(cursor); } /** * 发送开始整理消息 * * @param messageWhat */ private void sendStartMessage(int messageWhat) { Message message = new Message(); message.what = messageWhat; if (mHandler != null) { mHandler.sendMessage(message); } } /** * 发送整理结束消息 * * @param messageWhat */ private void sendEndMessage(int messageWhat, ArrayList<ContactBean> result) { Message message = new Message(); message.what = messageWhat; Bundle bundle = new Bundle(); bundle.putSerializable("完成", result); message.setData(bundle); if (mHandler != null) { mHandler.sendMessage(message); } } }
这样一个获取电话联系人信息的demo就完成了,主要是整理下张老师讲的东西,供大家学习。