Android загружает контакты слишком медленно
В моем приложении есть 5 блесен, заполненных контактами в телефоне. Я использую код ниже, чтобы заполнить массив контактами, а затем заполнить блесны элементами массива (здесь только 1 блесна).
Когда пользователь открывает приложение, блесны заполняются, чтобы пользователь мог выбрать одно имя для каждого блесны. Дело в том, что загрузка макета с блеснами занимает около 3 секунд, когда пользователь открывает приложение. Поиграв с кодом я понял что не важно как возможно, прядильщики находятся в приложении, источником проблемы является код, который заполняет массив контактами. Я также нашел причину медлительности: я запустил приложение на своем телефоне братьев, и там оно открылось так быстро, как и должно было. У него всего 30 контактов в телефоне, в то время как у меня около 500, большинство из них-контакты на Facebook. Итак, как я могу помочь в этой ситуации?
Вот в чем проблема, независимо от количества прядильщиков. В случае слишком большого количества контактов, это получает медленно:
contactName = null;
final Context context = getApplicationContext();
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur.getCount() > 0)
{
while (cur.moveToNext()) {
String idc = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String namec = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{idc}, null);
while (pCur.moveToNext()) {
contactName = pCur.getString(pCur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
myArr.add(contactName);
}
pCur.close();
}
}
}
myArr.add("");
Collections.sort(myArr);
Вот как я заполняю каждый спиннер (и заставляю их показывать ранее выбранное имя):
Spinner sp1 = (Spinner) findViewById(R.id.Spinner01);
ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, myArr);
sp1.setAdapter(adapter1);
sp1.setOnItemSelectedListener(new MyOnItemSelectedListener1());
mprefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
val1 = mprefs.getString("value1", "No name");
if (!val1.equals("No name"))
{
for (int i=0; i<myArr.size(); i++)
{
if (val1.equals(myArr.get(i)))
{
num = i;
}
}
sp1.setSelection(num);
}
else
{
sp1.setSelection(0);
}
Решение основано на идее Джесси ван Ассена:
Оказалось, что проблема была во втором запросе. Я удалил его и создал переменную" projection " для нужных мне столбцов:
final String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER
};
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + "='1'";
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, projection, selection, null, null);
if (cur.getCount() > 0)
{
while (cur.moveToNext()) {
String idc = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String namec = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
myArr.add(namec);
}
}
Итак, теперь у меня есть один запрос, который собирает только необходимые записи. Однако он был медленным даже с запросом набора данных и со вторым запросом. Реальным решением было удалить второй запрос, однако собрать меньше записей, чем вся база данных, - отличная идея.
2 ответа:
Я бы сказал, что способ, которым вы запрашиваете свои контактные данные, неверен.
Похоже, что вы извлекаете все ваши контакты со всеми данными контакта из базы данных,а затем фильтруете контакты в цикле while. Я бы предложил сделать это из запроса, что-то вроде этого (не проверено):
Cursor cur = cr.query( ContactsContract.Contacts.CONTENT_URI, new String[] { "_ID", "DISPLAY_NAME" }, "HAS_PHONE_NUMBER = ?", new String[] { "1" }, null);