Android загружает контакты слишком медленно - PullRequest
2 голосов
/ 04 сентября 2011

в моем приложении есть 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 ]

3 голосов
/ 04 сентября 2011

Я бы сказал, что ваш запрос о контактах неверен.

Похоже, вы извлекаете ВСЕ ваши контакты со всеми данными о контактах из базы данных, а затем фильтруете контакты в цикле while. Я бы предложил сделать это из запроса, что-то вроде этого (не проверено):

Cursor cur = cr.query(
    ContactsContract.Contacts.CONTENT_URI, 
    new String[] { "_ID", "DISPLAY_NAME" },
    "HAS_PHONE_NUMBER = ?", new String[] { "1" }, 
    null);
0 голосов
/ 05 мая 2014

Ваши счетчики будут заполняться намного быстрее , если вы использовали break, чтобы выпрыгнуть из своего for -цикла, как только вы назначите

num = i
...