1

Тема: Робота з контактами

Добрий вечір. Пишу програму, у якій є потреба отримати усі контакти з телефонної книги і вивести їх в спінер для вибору користувачем. Наче все і працює за вийнятком дивного сортування контактів де спершу "І", а потім "А", але коли повернутись з activity на якій здійснюється вибір контакту на головну, а потім знову перейти на неї і так декілька разів туди-сюди - програма вилітає. Під час декількох змін орієнтування екрану теж вилітає. Якщо закоментувати метод, який працює з контактами - програма перестає вилітати. Підкажіть, будь ласка, як з цим боротися, а головне - чому це відбувається. Є підозри, що це через переповнення оперативної пам'яті.

Ось мій кострубатий метод:

    public void getContacts() {
        String phoneNumber = null;

        Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
        String _ID = ContactsContract.Contacts._ID;
        String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
        String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;

        Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
        String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;

        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(CONTENT_URI, null,null, null, null);

        ArrayList data = new ArrayList();

        if (cursor.getCount() > 0) {
            while (cursor.moveToNext()) {
                String contact_id = cursor.getString(cursor.getColumnIndex( _ID ));
                String name = cursor.getString(cursor.getColumnIndex(DISPLAY_NAME));
                int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(HAS_PHONE_NUMBER)));

                if (hasPhoneNumber > 0) {
                    Cursor phoneCursor = contentResolver.query(PhoneCONTENT_URI, null,
                            Phone_CONTACT_ID + " = ?", new String[] { contact_id }, null);
                    while (phoneCursor.moveToNext()) {
                        phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
                        data.add(name + "   " + phoneNumber);
                    }
                }
            }
        }

        Set<String> set = new HashSet<>(data);
        data.clear();
        data.addAll(set);
        Collections.sort(data);

        ArrayAdapter<String> adapterS = new ArrayAdapter<String>(this, R.layout.spinner_item, R.id.spinner_text, data);
        adapterS.setDropDownViewResource(R.layout.spinner_item);
        mainSpinner.setAdapter(adapterS);
        cursor.close();
    }

Дякую за допомогу.

2

Re: Робота з контактами

Ви при змінах орієнтації екрану запитуєте дані на сервері?

3

Re: Робота з контактами

koala написав:

Ви при змінах орієнтації екрану запитуєте дані на сервері?

Ні, з сервером взагалі не працюю. Фактично в activity користувач вибирає дату та час, контакт і вводить текстове повідомлення, а на mainActivity буде відображено список з усіма запланованими і вже надісланими повідомленнями.

4

Re: Робота з контактами

Вибачте, я не дуже розуміюся на андроїдах. Що саме робить виклик

contentResolver.query(CONTENT_URI, null,null, null, null);

окрім того, що створює об'єкт типу Cursor?
Крім того, курсори точно обов'язково треба закривати

        cursor.close();

І ще - ви точно певні, що падає саме ця функція, а не якась інша, що смикає дані, отримані цією? Коли ви закоментовуєте цей метод - там же ще, мабуть, треба щось додатково закоментовувати, скажімо, його виклики чи його зв'язування з подіями?

Подякували: leofun011

5

Re: Робота з контактами

koala написав:

Вибачте, я не дуже розуміюся на андроїдах. Що саме робить виклик

contentResolver.query(CONTENT_URI, null,null, null, null);

окрім того, що створює об'єкт типу Cursor?
Крім того, курсори точно обов'язково треба закривати

        cursor.close();

І ще - ви точно певні, що падає саме ця функція, а не якась інша, що смикає дані, отримані цією? Коли ви закоментовуєте цей метод - там же ще, мабуть, треба щось додатково закоментовувати, скажімо, його виклики чи його зв'язування з подіями?


contentResolver дає доступ до даних поставщика послуг (смутно цю тему розумію), а згенерувала цей код Android Studio сама.

Курсор я закрив ще вчора, але це не допомогло.

А більше поки що в програмі нічого проблемного немає, лиш цей метод і його виклик. Інші методи працюють з datePicker і timePicker, а з цим все нормально.

6

Re: Робота з контактами

А, вибачте, про курсор - це було питання, але я десь загубив знак. Ви ще один курсор відкриваєте і його не закриваєте - це точно так і треба?
ContentResolver - я правильно розумію, що це звернення до внутрішніх ресурсів вашої програми, і, відповідно, воно не буде повертати несподіваних результатів?
Загалом - ви б дебагером пройшлися. Чи хоча б навісили обробник виключних ситуацій, не кажу вже про валідацію всіх даних всередині коду - наприклад, ви точно певні, що абсолютно всі hasPhoneNumber мають тип int?

Подякували: Volodymyr, leofun012

7

Re: Робота з контактами

koala написав:

А, вибачте, про курсор - це було питання, але я десь загубив знак. Ви ще один курсор відкриваєте і його не закриваєте - це точно так і треба?
ContentResolver - я правильно розумію, що це звернення до внутрішніх ресурсів вашої програми, і, відповідно, воно не буде повертати несподіваних результатів?
Загалом - ви б дебагером пройшлися. Чи хоча б навісили обробник виключних ситуацій, не кажу вже про валідацію всіх даних всередині коду - наприклад, ви точно певні, що абсолютно всі hasPhoneNumber мають тип int?

Змінній hasPhoneNumber присвоюються значення, які через метод parseInt() приведені до типу int, тому там все наче добре. Ви хороші запитання ставите, а головне - правильні: відразу після циклу while прописав вихід з курсору phoneCursor і все почало працювати стабільно. Дуже дякую за допомогу.