简体   繁体   English

联系人未加载到我的列表视图中

[英]contacts are not loading into my list view android

I am trying to load the contacts in my phone into list view of an android app, but it doesn't loading my contacts. 我正在尝试将手机中的联系人加载到android应用程序的列表视图中,但没有加载我的联系人。 I got a dailog box to allow or deny permissions, when i pressed allow, its showing me a blank screen 我有一个允许或拒绝权限的对话框,当我按“允许”时,它向我显示一个空白屏幕

I used contact fetcher class to retrieve the contacts. 我使用contact fetcher类检索联系人。 when i DENY permissions, its showing toast as expected but not showing contacts as list view 当我拒绝权限时,按预期显示其吐司,但不以列表视图显示联系人

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();
}

here is my mainActivity... 这是我的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;
}

The specific issue you have there is assuming that loadInBackground immediately returns a cursor with all the data in hand, that's not how it works. 您遇到的特定问题是假设loadInBackground立即返回一个包含所有数据的游标,而事实并非如此。

But in general CursorLoader is not a recommended pattern to load stuff onto UI. 但通常不建议使用CursorLoader模式将内容加载到UI。 You should do it differently, by querying for data inside an AsyncTask for example, and then delivering the results in the onPostExecute . 您应该以不同的方式进行AsyncTask ,例如,在AsyncTask查询数据,然后将结果传递到onPostExecute

For the simplest changes from your existing code, I would change fetchAll to be a blocking method, like so: 对于现有代码中最简单的更改,我将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;
}

and call if from an AsyncTask so it won't run any heavy code on the UI thread, like so: 并从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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM