Как исправить закрутку, постоянно закрывающуюся и открывающую себя, когда я пытаюсь включить элементы из базы данных Firebase в свой список элементов - PullRequest
0 голосов
/ 24 апреля 2019

Я разрабатываю приложение для конкурса.Приложение подключено к базе данных реального времени Firebase, которая организована в несколько дочерних списков, каждый из которых имеет собственное строковое значение следующим образом:

category1:
    child1: "string"
    child2: "string"
category2:
    child3: "string"
    child4: "string"
(etc.)

Я пытаюсь получить имена этих категорий и добавить их ввыпадающий Spinner в одном из моих макетов.Однако когда я тестирую этот макет, происходит нечто особенное.Если я нажму на Spinner, чтобы открыть выпадающий список, он будет постоянно обновляться (я вижу, как он постоянно закрывается и снова открывается).Что еще более странно, так это то, что иногда он будет отображать только список из двух строк (которые я добавляю по умолчанию) и ни одно из названий категорий выше, но в других случаях он будет отображать их оба в списке.

Кажется, проблема обновления возникает независимо от того, пытаюсь ли я добавить дочерние строки из Firebase.Я могу сказать, что это происходит потому, что окно отладчика в Android Studio постоянно спамито

D/ViewRootImpl@a8fa8f6[PopupWindow:d00794f]: Relayout returned: old=[286,729][962,1113] new=[286,729][962,1113] result=0x1 surface={valid=true 531823960064} changed=false

, пока открыто раскрывающееся меню Spinner (в обоих случаях).Я попытался найти эту ошибку вверх (как в целом, так и по частям), но я не смог найти ничего полностью относящегося к тому, что я пытался выполнить.

Вот код, который добавляет список в Spinner (этот метод называетсякогда действие открыто):

    public void onOpen() {
        // This is not the complete method, but the relevant portion of it

        final List<String> categories = new ArrayList<>();
        categories.add(selectionEmpty);
        categories.add(selectionCreateNew);
        dbh.dbref.child("users").child("a_users_uid_goes_here").child("flashcards").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot child : dataSnapshot.getChildren()) {
                    categories.add(child.getKey());
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, categories);
        setSelector.setAdapter(dataAdapter);
    }

А вот OnItemSelectedListener, который я назначил Spinner:

    AdapterView.OnItemSelectedListener selectSet = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long id) {
            String selection = adapterView.getItemAtPosition(pos).toString();
            if (selection.equals(selectionEmpty)) onOpen();
            if (selection.equals(selectionCreateNew)) onCreateNewSet();
            else onSelectSet(selection);
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {

        }
    };

onCreateNewSet() и onSelectSet(String set) в настоящее время являются двумя пустыми методами.Я не верю, что это должно иметь какое-либо влияние, но на всякий случай они ничего не делают в данный момент.onOpen() приведен фрагмент кода выше.

Я впервые использую объекты Spinner, и я также новичок в Android Studio в целом (использую его 6 месяцев), поэтому я приношу свои извинения, если я 'м просто отсутствует очевидная строка кода.Подводя итог: оптимально, выпадающий список Spinner должен отображать две предустановленные строки и все имена категорий в базе данных и открываться только один раз.На самом деле происходит то, что он постоянно закрывается / открывается и показывает имена категорий из базы данных каждый раз, когда он открывается (однако предустановленные строки всегда есть).Я очень признателен за любую помощь!

Я могу в ближайшее время связать GIF с проблемой, с которой я сталкиваюсь, если кому-то понадобится.

ОБНОВЛЕНИЕ: Похоже, что это обновление происходит только тогда, когда у меня есть значение по умолчаниюзначение, выбранное в раскрывающемся списке, которое является одной из двух предустановленных строк.Если я выберу другой, то этот глюк не происходит.Все еще не уверен, почему это происходит.

ВТОРОЕ ОБНОВЛЕНИЕ: Я сам решил это, это была ошибка новичка, которую я смутился совершить.Проблема в том, что в методе onOpen() я установил адаптер для Spinner, но затем в AdapterView.onItemSelectedListener Spinner я снова вызываю onOpen(), что привело к рекурсивному циклу, который нарушал все.Исправление состояло в том, чтобы создать дублирующий метод onOpen() с именем onSelectNoSet(), который делал то же самое, но НЕ устанавливал адаптер для счетчика, и чтобы слушатель вызывал этот метод вместо onOpen().

TL; DR рекурсия плохая

1 Ответ

0 голосов
/ 25 апреля 2019

ВТОРОЕ ОБНОВЛЕНИЕ: я решил это сам, это была ошибка новичка, которую я смутился совершить. Проблема в том, что в методе onOpen() я устанавливаю адаптер для Spinner, но затем в AdapterView.onItemSelectedListener Spinner я снова вызываю onOpen(), что приводит к рекурсивному циклу, который нарушает все. Исправление состояло в том, чтобы создать дублирующий метод onOpen() с именем onSelectNoSet(), который делал то же самое, но НЕ устанавливал адаптер для счетчика, и чтобы слушатель вызывал этот метод вместо onOpen().

TL; DR Рекурсия плохая

...