Записи Spinner привязки livedata комнаты адаптера не работают

Я работаю над концепцией привязки данных в реальном времени. Я устанавливаю список для счетчика, используя специальный адаптер привязки. Но я получаю нулевые данные при первом извлечении из комнаты.

код:

     @Query("select * from Student")
        LiveData<List<Student>> getAllItems();


        @BindingAdapter({"bind:entries"})
            public static void customSpinnerBinding(AppCompatSpinner appCompatSpinner,LiveData<List<Student>> listLiveData){
                if (listLiveData != null && listLiveData.getValue().size() > 0){
                    ArrayAdapter<Student> spinnerArrayAdapter = new ArrayAdapter<Student>
                            (appCompatSpinner.getContext(), android.R.layout.simple_spinner_item,
                                    listLiveData.getValue()); //selected item will look like a spinner set from XML
                    spinnerArrayAdapter.setDropDownViewResource(android.R.layout
                            .simple_spinner_dropdown_item);
                    appCompatSpinner.setAdapter(spinnerArrayAdapter);
                }
            }

        public LiveData<List<Student>> getListLiveData() {
            if (listLiveData == null){
               listLiveData = studentDB.studentDao().getAllItems();
            }
            return listLiveData;
        }

        <android.support.v7.widget.AppCompatSpinner
                    android:id = "@+id/spinner"
                    android:layout_width = "0dp"
                    bind:entries = "@{viewmodel.listLiveData}"
                    android:layout_height = "wrap_content"
                    android:layout_marginStart = "16dp"
                    android:layout_marginLeft = "16dp"
                    android:layout_marginTop = "16dp"
                    android:layout_marginEnd = "16dp"
                    android:layout_marginRight = "16dp"
                    android:layout_marginBottom = "16dp"
                    app:layout_constraintBottom_toBottomOf = "parent"
                    app:layout_constraintEnd_toEndOf = "parent"
                    app:layout_constraintStart_toStartOf = "parent"
                    app:layout_constraintTop_toTopOf = "parent" />

but if i observe livedata in activity this is working

  mainViewModel.getListLiveData().observe(this, new Observer<List<Student>>() {
           @Override
           public void onChanged(@Nullable List<Student> students) {
               if (students.size() > 0){
                   ArrayAdapter<Student> spinnerArrayAdapter = new ArrayAdapter<Student>
                    (MainActivity.this, android.R.layout.simple_spinner_item,
                            students); //selected item will look like a spinner set from XML
            spinnerArrayAdapter.setDropDownViewResource(android.R.layout
                    .simple_spinner_dropdown_item);
            activityMainBinding.appbar.contentid.spinner.setAdapter(spinnerArrayAdapter);
               }
           }
       });

поделитесь своим кодом Viewmodel.

Rajnish suryavanshi 29.05.2019 12:29

все, чем я поделился, я просто устанавливаю список живых данных на счетчик

skyshine 29.05.2019 12:38

Прикрепите модель представления для просмотра в действии.

Rajnish suryavanshi 29.05.2019 12:40

проверить обновленный код

skyshine 29.05.2019 12:45

проверить этот код stackoverflow.com/a/53660823/7592063.

Rajnish suryavanshi 29.05.2019 12:51

при использовании Room вы должны читать данные в фоновом потоке.

Faisal 30.05.2019 04:51
1
6
513
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Пытаться

listLiveData = StudentDB.getAppDatabase(application).studentDao().getAllItems();
return listLiveData;

Проверьте, возвращает ли этот studentDB.studentDao().getAllItems() данные или нет.

Rajnish suryavanshi 29.05.2019 12:21

Я думаю, вы не соблюдаете данные. Поэтому. Попробуйте listLiveData.setValue(list);

Rajnish suryavanshi 29.05.2019 12:23

да, он возвращается, но работает, если я делаю listLiveData.observe в действии

skyshine 29.05.2019 12:24

Попробуйте этот код listLiveData.setValue(studentDB.studentDao().getAllItems());

Rajnish suryavanshi 29.05.2019 12:25

вам не нужно устанавливать значение из комнаты, мы получаем listLiveData, который содержит список объектов

skyshine 29.05.2019 12:25

я получаю listlivedata из БД, не могли бы вы еще раз проверить мой код

skyshine 29.05.2019 12:27
Ответ принят как подходящий

Проверьте эти две вещи:

  1. Измените свой .customSpinnerBinding, чтобы принять List<Student> вместо LiveData<List<Student>>.

BindingAdapter принимает то, что находится внутри LiveData, а не само LiveData. LiveData не тот, кто меняется. Меняется только содержание LiveData уведомлений.

Пример BindingAdapter:

        @BindingAdapter({"bind:entries"})
        public static void customSpinnerBinding(AppCompatSpinner appCompatSpinner, List<Student> students) {

            ArrayAdapter<Student> spinnerArrayAdapter = new ArrayAdapter<Student>
                    (appCompatSpinner.getContext(), android.R.layout.simple_spinner_item,
                         students); //selected item will look like a spinner set from XML
            spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            appCompatSpinner.setAdapter(spinnerArrayAdapter);
        }


  1. Не ленитесь грузить listLiveData

Похоже, вашему представлению это все равно понадобится, какой смысл лениво загружать его? Это только сделает ваш код более сложным и трудным для отладки, сделав вашу модель представления более активной. Просто с нетерпением загрузите список студентов и объявите его окончательным, чтобы сделать его еще лучше.

public final LiveData listLiveData = studentDB.studentDao().getAllItems();

Если вам нужна отложенная загрузка listLiveData, убедитесь, что она инициализирована. В вашем .xml:

    <android.support.v7.widget.AppCompatSpinner
                ...
                bind:entries = "@{viewmodel.getListLiveData()}"
                ... />

на самом деле я получил решение bind:entries = "@{viewmodel.listLiveData.getValue()}", но в любом случае вы упомянули то же самое

skyshine 30.05.2019 08:16

Я не упоминаю одно и то же. Обычно вы не должны использовать «getValue» для «LiveData». 'getValue' получает значение синхронно и только один раз, что лишает смысла весь смысл использования 'LiveData'.

Sanlok Lee 30.05.2019 17:18

bind:entries = "@{viewmodel.getListLiveData()}" если я укажу так, он не работает и возникает ошибка привязки

skyshine 31.05.2019 07:59

насколько я понял, в xml мы не можем напрямую предоставлять livedata.

skyshine 31.05.2019 08:03

я получаю listLiveData.getValue() null в адаптере привязки счетчика viewmodel, я думаю, единственный способ использовать наблюдатели livedata, только мы можем данные

skyshine 31.05.2019 08:05

получение нулевого значения для listLiveData.getValue() — это нормально, потому что getValue() буквально получает значение, даже если LiveData еще не имеет никакого значения. Вы пробовали другой подход — не ленивую загрузку LiveData? Насколько я знаю, вы МОЖЕТЕ напрямую предоставить LiveData, если вы определили свою модель представления в теге <data> и назначили модель представления в привязке в своем действии/фрагменте.

Sanlok Lee 31.05.2019 08:09

я не определил livedata в теге данных, но все же я могу получить значения списка внутри адаптера привязки spinner, потому что xml livedata извлекает значения асинхронно

skyshine 31.05.2019 08:14

Давайте продолжить обсуждение в чате.

Sanlok Lee 31.05.2019 08:15

Другие вопросы по теме