联系人没有加载到我的列表视图android中
Posted
技术标签:
【中文标题】联系人没有加载到我的列表视图android中【英文标题】:contacts are not loading into my list view android 【发布时间】:2019-06-03 04:47:50 【问题描述】:我正在尝试将手机中的联系人加载到 android 应用程序的列表视图中,但它没有加载我的联系人。我有一个对话框来允许或拒绝权限,当我按下允许时,它向我显示一个空白屏幕
我使用联系人提取器类来检索联系人。当我拒绝权限时,它按预期显示吐司,但未将联系人显示为列表视图
public class ContactFetcher
private final Context context;
public ContactFetcher(Context c)
this.context = c;
public ArrayList<Contact> fetchAll()
String[] projectionFields = new String[]
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
;
ArrayList<Contact> listContacts = new ArrayList<>();
CursorLoader cursorLoader = new CursorLoader(context,
ContactsContract.Contacts.CONTENT_URI,
projectionFields, // the columns to retrieve
null, // the selection criteria (none)
null, // the selection args (none)
null // the sort order (default)
);
Cursor c = cursorLoader.loadInBackground();
final Map<String, Contact> contactsMap = new HashMap<>(c.getCount());
if (c.moveToFirst())
int idIndex = c.getColumnIndex(ContactsContract.Contacts._ID);
int nameIndex =
c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
do
String contactId = c.getString(idIndex);
String contactDisplayName = c.getString(nameIndex);
Contact contact = new Contact(contactId, contactDisplayName);
contactsMap.put(contactId, contact);
listContacts.add(contact);
while (c.moveToNext());
c.close();
matchContactNumbers(contactsMap);
return listContacts;
public void matchContactNumbers(Map<String, Contact> contactsMap)
// Get numbers
final String[] numberProjection = new String[]
Phone.NUMBER,
Phone.TYPE,
Phone.CONTACT_ID,
;
Cursor phone = new CursorLoader(context,
Phone.CONTENT_URI,
numberProjection,
null,
null,
null).loadInBackground();
if (phone.moveToFirst())
final int contactNumberColumnIndex =
phone.getColumnIndex(Phone.NUMBER);
final int contactTypeColumnIndex =
phone.getColumnIndex(Phone.TYPE);
final int contactIdColumnIndex = phone.getColumnIndex(Phone.CONTACT_ID);
while (!phone.isAfterLast())
final String number = phone.getString(contactNumberColumnIndex);
final String contactId = phone.getString(contactIdColumnIndex);
Contact contact = contactsMap.get(contactId);
if (contact == null)
continue;
final int type = phone.getInt(contactTypeColumnIndex);
String customLabel = "Custom";
CharSequence phoneType = ContactsContract.CommonDataKinds.Phone.getTypeLabel(context.getResources(), type, customLabel);
contact.addNumber(number, phoneType.toString());
phone.moveToNext();
phone.close();
这是我的 mainActivity...
private static final int PERMISSIONS_REQUEST_READ_CONTACTS=100;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvContacts = (ListView) findViewById(R.id.lvContacts);
showContacts();
private void showContacts()
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);
//After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
else
listContacts = new ContactFetcher(this).fetchAll();
ContactsAdapter adapterContacts = new ContactsAdapter(this, listContacts);
lvContacts.setAdapter(adapterContacts);
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults)
if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS)
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
// Permission is granted
listContacts = new ContactFetcher(this).fetchAll();
ContactsAdapter adapterContacts = new ContactsAdapter(this, listContacts);
lvContacts.setAdapter(adapterContacts);
else
Toast.makeText(this, "Until you grant the permission, we canot display the names", Toast.LENGTH_SHORT).show();
@Override
public boolean onCreateOptionsMenu(Menu menu)
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
【问题讨论】:
new String[]Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_READ_CONTACTS
有错字吗?它应该是new String[]Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_READ_CONTACTS
,其中大括号应该在第二个字符串之外。
@Edric - 不应该。第二个常量是请求代码。
哎呀,没看到!感谢您指出这一点。
【参考方案1】:
您遇到的具体问题是假设loadInBackground
立即返回一个包含所有数据的游标,但这不是它的工作原理。
但通常CursorLoader
不是将内容加载到 UI 的推荐模式。
您应该采取不同的做法,例如在 AsyncTask
中查询数据,然后在 onPostExecute
中提供结果。
对于现有代码的最简单更改,我会将fetchAll
更改为阻塞方法,如下所示:
public ArrayList<Contact> fetchAll()
String[] projectionFields = new String[]
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
;
ArrayList<Contact> listContacts = new ArrayList<>();
Cursor c = context.getContentResolver().query(Contacts.CONTENT_URI,projectionFields,null,null,null);
final Map<String, Contact> contactsMap = new HashMap<>(c.getCount());
if (c.moveToFirst())
... // same code
c.close();
matchContactNumbers(contactsMap);
return listContacts;
并从 AsyncTask 调用 if,这样它就不会在 UI 线程上运行任何繁重的代码,如下所示:
new AsyncTask<Void, Void, ArrayList<Contact>>()
@Override
protected ArrayList<Contact> doInBackground(Void... params)
return new ContactFetcher(this).fetchAll();
@Override
protected void onPostExecute(ArrayList<Contact> listContacts)
ContactsAdapter adapterContacts = new ContactsAdapter(this, listContacts);
lvContacts.setAdapter(adapterContacts);
.execute();
【讨论】:
我应该在 mainActivity 中提及 Asyntask 吗?如果是这样,我应该在哪里检查请求权限条件? 您可以将 AsyncTask 代码作为新方法fetchContactsAsync
放入主活动中,并从 showContacts
和 onRequestPermissionsResult
调用它,而不是当前调用 fetchAll
的代码(这 3 行)以上是关于联系人没有加载到我的列表视图android中的主要内容,如果未能解决你的问题,请参考以下文章