今天记录一下用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"?>
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
tools:ignore="HardcodedText" >
android:id="@+id/bt_getCantacts"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="获取联系人信息" />
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 list = (ArrayList) 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> {
/** 开始整理 */
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 doInCursor... params) {
// 只需要把原来放在子线程的代码放到这个方法就行
Cursor cursor = params[0];
ArrayList ciList = new ArrayList();
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 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 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就完成了,主要是整理下张老师讲的东西,供大家学习。