這次範例從Google Sample改寫。
這次會比較複雜一點
結合了如何寫一個電話簿(Phone book) (ContentResolver)以及如何使用RecylerView+CardView
public class MainActivity extends AppCompatActivity {
private AsyncQueryHandler queryHandler;
private List<Map<String, String>> contactsArrayList;
private static final int NAME_TOKEN = 0;
private static final int NUMBER_TOKEN = 1;
private static final String NAME = "name";
private static final String NUMBER = "number";
private static final String[] NAME_PROJECTION = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME
};
private static final String[] PHONE_NUMBER_PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
private RecyclerView list;
private RecyclerView.Adapter<MyAdapter.ViewHolder> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initView(){
list = (RecyclerView) findViewById(R.id.list_view);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
list.setLayoutManager(layoutManager);
adapter = new MyAdapter(contactsArrayList);
list.setAdapter(adapter);
}
private void initData(){
contactsArrayList = new ArrayList<>();
queryHandler = new MyAsyncQueryHandler(this);
queryHandler.startQuery(NAME_TOKEN, null,
ContactsContract.Contacts.CONTENT_URI,
NAME_PROJECTION,
ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1",
null,
null);
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Map<String, String>> mData;
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView phone;
public ViewHolder(View v) {
super(v);
name = (TextView) v.findViewById(R.id.name);
phone = (TextView) v.findViewById(R.id.phone);
}
}
public MyAdapter(List<Map<String, String>> data) {
mData = data;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.name.setText(mData.get(position).get(NAME));
holder.phone.setText(mData.get(position).get(NUMBER));
}
@Override
public int getItemCount() {
return mData.size();
}
}
class MyAsyncQueryHandler extends AsyncQueryHandler {
public MyAsyncQueryHandler(Context context) {
super(context.getContentResolver());
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
switch(token){
case NAME_TOKEN:
while (cursor.moveToNext()) {
Map<String, String> map = new HashMap<>();
String name = cursor.getString(cursor
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Uri.Builder builder = ContactsContract.Contacts.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, cursor.getLong(0));
builder.appendEncodedPath(ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
Uri phoneNumbersUri = builder.build();
queryHandler.startQuery(NUMBER_TOKEN, cursor.getPosition(), phoneNumbersUri,
PHONE_NUMBER_PROJECTION, ContactsContract.CommonDataKinds.Phone.MIMETYPE + "=?",
new String[] { ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE }, null);
map.put(NAME, name);
contactsArrayList.add(map);
}
break;
case NUMBER_TOKEN:
while (cursor.moveToNext()) {
String phoneNumber = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
int index = (Integer)cookie;
Map<String, String> map = contactsArrayList.get(index);
map.put(NUMBER, phoneNumber);
contactsArrayList.set(index, map);
}
adapter.notifyDataSetChanged();
break;
}
}
}
}
MainActivity xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="personal.givemepass.asyncqueryhandlerdemo.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
RecyclerView item xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="100dp"
card_view:cardCornerRadius="4dp"
android:layout_margin="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2"
android:orientation="vertical">
<TextView
android:layout_weight="1"
android:id="@+id/name"
android:textColor="#000000"
android:textSize="24sp"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"/>
<TextView
android:layout_weight="1"
android:id="@+id/phone"
android:textColor="#000000"
android:textSize="24sp"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"/>
</LinearLayout>
</android.support.v7.widget.CardView>
記得加入Gradle
compile 'com.android.support:recyclerview-v7:23.0.1'
compile 'com.android.support:cardview-v7:+'
權限也要加
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.CALL_PHONE" />