我想要实现的是直截了当。当我输入时,它应列出我手机中的联系人及其缩略图(照片)。起初我能够让应用程序只列出联系人姓名。但添加以下代码后,自动完成功能无效。没有错误。
以下是一些代码:
这就是我设置我的适配器的方式
AsyncTask.execute(new Runnable() {
@Override
public void run() {
adapter = new ContactsAdapter(getApplicationContext(),
getAllContactNamesAndThumbs());
mNameEditText.setAdapter(adapter);
}
});
getAllContactNamesAndThumbs方法:
private List<Map<String, Object>> getAllContactNamesAndThumbs() {
List<Map<String, Object>> namesAndThumbs;
// Check the SDK version and whether the permission is already granted or not.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
namesAndThumbs = new ArrayList<Map<String, Object>>();
//After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
} else {
//The permissions are granted so Get all contacts
namesAndThumbs = new ArrayList<Map<String, Object>>();
try {
Cursor contactCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[]{ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER},
null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
if (contactCursor != null) {
while (contactCursor.moveToNext()) {
long id = contactCursor.getLong(contactCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
InputStream inputStream = openThumbnail(id);
Bitmap thumbnail;
if (inputStream != null) {
thumbnail = BitmapFactory.decodeStream(inputStream);
} else {
thumbnail = BitmapFactory.decodeResource(getResources(), R.drawable.ic_person_black_24dp);
}
//Add contact name into the list
Map<String, Object> datum = new HashMap<String, Object>(2);
datum.put("name", contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
datum.put("thumbnail", thumbnail);
namesAndThumbs.add(datum);
}
}
} catch (NullPointerException e) {
Log.e("ContactNamesAndThumbs", e.getMessage());
}
}
return namesAndThumbs;
}
我使用了带有AutoCompleteTextView的ArrayAdapter。这是代码
public ContactsAdapter(Context context, List<Map<String, Object>> data) {
super(context, -1);
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.single_contact, parent, false);
TextView cName = (TextView) rowView.findViewById(R.id.tv_ContactName);
ImageView cThumb = (ImageView) rowView.findViewById(R.id.iv_contact_thumbnail);
cName.setText(data.get(position).get("name").toString());
cThumb.setImageBitmap((Bitmap) data.get(position).get("thumbnail"));
return rowView;
}
答案 0 :(得分:0)
在AsyncTask
执行类似
AsyncTask.execute(new Runnable() {
@Override
public void run() {
adapter = new ContactsAdapter(Activity.this, getAllContactNamesAndThumbs());
mNameEditText.setAdapter(adapter);
}
});
修改强>
在适配器中创建一个静态类
private static class ViewHolder {
TextView titleTextView;
ImageView image;
}
并在getView
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = layoutInflater.inflate(R.layout.single_contact, parent, false);
// textview and imageview initialization using view holder
// eg holder.titleTextView = (TextView) rowView.findViewById(R.id.titleTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// now set data using
// holder.image.set..
// holder.textView.setText
答案 1 :(得分:0)
终于想通了!我不得不扩展ContactsAdapter表单BaseAdapter
而不是ArrayAdapter
并实现Filterable
接口。而不是使用AsycTask
设置适配器,我必须在活动的oncreate方法的ui线程上运行它。
以下是我在没有AsyncTask
的情况下将我的适配器设置在oncreate中的方法:
adapter = new ContactsAdapter(getApplicationContext(), getAllContactNamesAndThumbs());
autoCompleteTextView.setAdapter(adapter);
getAllContactNamesAndThumbs()
方法
private List<Map<String, Object>> getAllContactNamesAndThumbs() {
List<Map<String, Object>> namesAndThumbs;
// Check the SDK version and whether the permission is already granted or not.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
namesAndThumbs = new ArrayList<Map<String, Object>>();
//After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
} else {
//The permissions are granted so Get all contacts
namesAndThumbs = new ArrayList<Map<String, Object>>();
try {
Cursor contactCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[]{ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER},
null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
if (contactCursor != null) {
while (contactCursor.moveToNext()) {
long id = contactCursor.getLong(contactCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
InputStream inputStream = openThumbnail(id);
Bitmap thumbnail;
if (inputStream != null) {
thumbnail = BitmapFactory.decodeStream(inputStream);
} else {
thumbnail = BitmapFactory.decodeResource(getResources(), R.drawable.ic_person_black_24dp);
}
//Add contact name into the list
Map<String, Object> datum = new HashMap<String, Object>(2);
datum.put("name", contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
datum.put("thumbnail", thumbnail);
namesAndThumbs.add(datum);
}
}
} catch (NullPointerException e) {
Log.e("ContactNamesAndThumbs", e.getMessage());
}
}
return namesAndThumbs;
}
我的ContactsAdapter类:
public class ContactsAdapter extends BaseAdapter implements Filterable{
private Context context;
private List<Map<String, Object>> originalData;
private List<Map<String, Object>> suggestionData = new ArrayList<>();
private Filter filter = new CustomFilter();
public ContactsAdapter(Context context, List<Map<String, Object>> data) {
super();
this.context = context;
this.originalData = data;
}
@Override
public int getCount() {
return suggestionData.size();
}
@Override
public Object getItem(int position) {
return suggestionData.get(position).get("name").toString();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.single_contact, parent, false);
holder = new ViewHolder();
holder.cName = (TextView) convertView.findViewById(R.id.tv_ContactName);
holder.cThumb = (ImageView) convertView.findViewById(R.id.iv_contact_thumbnail);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.cName.setText(suggestionData.get(position).get("name").toString());
holder.cThumb.setImageBitmap((Bitmap) suggestionData.get(position).get("thumbnail"));
return convertView;
}
@Override
public Filter getFilter() {
return filter;
}
private static class ViewHolder {
TextView cName;
ImageView cThumb;
}
/**
* Our Custom Filter Class.
*/
private class CustomFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
suggestionData.clear();
if (originalData != null && constraint != null) { // Check if the Original List and Constraint aren't null.
for (int i = 0; i < originalData.size(); i++) {
if (Pattern.compile(Pattern.quote(constraint.toString()),
Pattern.CASE_INSENSITIVE).matcher
(originalData.get(i).get("name").toString()).find()) { // Compare item in original list if it contains constraints.
suggestionData.add(originalData.get(i)); // If TRUE add item in Suggestions.
}
}
}
FilterResults results = new FilterResults(); // Create new Filter Results and return this to publishResults;
results.values = suggestionData;
results.count = suggestionData.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
<强> P.S 强>
即使这段代码按照应有的方式工作,也会有一些小问题。一个是如果你有很多像1000这样的联系人那么它是一个很大的过程,所以应用程序可能会挂起并显示I/Choreographer: Skipped xxx frames! The application may be doing too much work on its main thread.
第二个是如果你键入一些名字并按住退格键以快速擦除,那么会出现错误:
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.
我仍然认为这是一个答案,因为我的主要问题已经解决了。