Я работаю над концепцией привязки данных в реальном времени. Я устанавливаю список для счетчика, используя специальный адаптер привязки. Но я получаю нулевые данные при первом извлечении из комнаты.
код:
@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);
}
}
});
все, чем я поделился, я просто устанавливаю список живых данных на счетчик
Прикрепите модель представления для просмотра в действии.
проверить обновленный код
проверить этот код stackoverflow.com/a/53660823/7592063.
при использовании Room вы должны читать данные в фоновом потоке.
Пытаться
listLiveData = StudentDB.getAppDatabase(application).studentDao().getAllItems();
return listLiveData;
Проверьте, возвращает ли этот studentDB.studentDao().getAllItems() данные или нет.
Я думаю, вы не соблюдаете данные. Поэтому. Попробуйте listLiveData.setValue(list);
да, он возвращается, но работает, если я делаю listLiveData.observe в действии
Попробуйте этот код listLiveData.setValue(studentDB.studentDao().getAllItems());
вам не нужно устанавливать значение из комнаты, мы получаем listLiveData, который содержит список объектов
я получаю listlivedata из БД, не могли бы вы еще раз проверить мой код
Проверьте эти две вещи:
.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);
}
listLiveData
Похоже, вашему представлению это все равно понадобится, какой смысл лениво загружать его? Это только сделает ваш код более сложным и трудным для отладки, сделав вашу модель представления более активной. Просто с нетерпением загрузите список студентов и объявите его окончательным, чтобы сделать его еще лучше.
public final LiveData listLiveData = studentDB.studentDao().getAllItems();
Если вам нужна отложенная загрузка listLiveData
, убедитесь, что она инициализирована. В вашем .xml:
<android.support.v7.widget.AppCompatSpinner
...
bind:entries = "@{viewmodel.getListLiveData()}"
... />
на самом деле я получил решение bind:entries = "@{viewmodel.listLiveData.getValue()}", но в любом случае вы упомянули то же самое
Я не упоминаю одно и то же. Обычно вы не должны использовать «getValue» для «LiveData». 'getValue' получает значение синхронно и только один раз, что лишает смысла весь смысл использования 'LiveData'.
bind:entries = "@{viewmodel.getListLiveData()}" если я укажу так, он не работает и возникает ошибка привязки
насколько я понял, в xml мы не можем напрямую предоставлять livedata.
я получаю listLiveData.getValue() null в адаптере привязки счетчика viewmodel, я думаю, единственный способ использовать наблюдатели livedata, только мы можем данные
получение нулевого значения для listLiveData.getValue()
— это нормально, потому что getValue()
буквально получает значение, даже если LiveData
еще не имеет никакого значения. Вы пробовали другой подход — не ленивую загрузку LiveData
? Насколько я знаю, вы МОЖЕТЕ напрямую предоставить LiveData
, если вы определили свою модель представления в теге <data> и назначили модель представления в привязке в своем действии/фрагменте.
я не определил livedata в теге данных, но все же я могу получить значения списка внутри адаптера привязки spinner, потому что xml livedata извлекает значения асинхронно
Давайте продолжить обсуждение в чате.
поделитесь своим кодом Viewmodel.