База данных комнат Livedata getValue() возвращает ноль
Я пытался получить список пользовательских данных объекта из комнаты, используя LiveData и viewmodel. При использовании метода getValue() Livedata возвращает ноль, но при получении списка непосредственно отображаются фактические данные. Как получить класс List of Period с помощью LiveData в классе viewmodel.
Классы сущностей
@Entity
public class Period {
@PrimaryKey
@NonNull
String header;
@TypeConverters(WritterConverter.class)
ArrayList<Writter> writters;
public Period(String header, ArrayList<Writter> writters) {
this.header = header;
this.writters = writters;
}
public String getHeader() {
return header;
}
public ArrayList<Writter> getWritters() {
return writters;
}
}
@Entity
public class Writter {
String birth;
String death;
String name;
ArrayList<String> novels;
public Writter(){}
public Writter(String birth, String death, String name, ArrayList<String> novels) {
this.birth = birth;
this.death = death;
this.name = name;
this.novels = novels;
}
public String getBirth() {
return birth;
}
public String getDeath() {
return death;
}
public String getName() {
return name;
}
public ArrayList<String> getNovels() {
return novels;
}
}
Конвертер Класс
public class WritterConverter {
@TypeConverter
public static ArrayList<Writter> fromString(String value){
Type listType = new TypeToken<ArrayList<Writter>>(){}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String fromArrayList(ArrayList<Writter> list){
Gson gson = new Gson();
String json = gson.toJson(list);
return json;
}
}
Класс DAO
@Dao
@TypeConverters({WritterConverter.class})
public interface DAO {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertPeriod(Period period);
@Query("SELECT * FROM Period WHERE header LIKE :header")
Period getPeriodList(String header);
@Query("SELECT * FROM Period")
LiveData<List<Period>> getAllPeriodList();
}
База данных
@Database(version = 1, entities = {Period.class})
public abstract class MyDatabase extends RoomDatabase{
static MyDatabase databaseInstance;
public static MyDatabase getDatabaseInstance(Context context) {
if (databaseInstance == null)
databaseInstance = Room
.databaseBuilder(context, MyDatabase.class, "testDatabase1")
.fallbackToDestructiveMigration()
// .addMigrations(FROM_1_TO_2)
.build();
return databaseInstance;
}
abstract public DAO dao();
}
Получить метод данных в классе viewmodel
private void getDataFromDatabase() {
new AsyncTask<Void, Void, LiveData<List<Period>>>() {
@Override
protected LiveData<List<Period>> doInBackground(Void... voids) {
LiveData<List<Period>> periodList = MyApplication.getDatabase().dao().getAllPeriodList();
// Period periodList = MyApplication.getDatabase().dao().getWriterList(EndPoints.THE_OLD_ENGLISH_PERIOD);
return periodList;
}
@Override
protected void onPostExecute(LiveData<List<Period>> aVoid) {
super.onPostExecute(aVoid);
// Period period = aVoid.getValue().get(0);
Log.d("header", aVoid.getValue().get(0).getHeader());
}
}.execute();
}
2 ответа
Дело в том,
Asynctask
работает в другом потоке в фоновом режиме асинхронноLivedata
работает как плавающая над базой данных, чтобы увидеть изменения.
Таким образом, требуется время для выполнения операции выборки для Asyntask
, Вы можете увидеть это, протестировав Asynctask
с задержкой 10 секунд. Поэтому лучше напрямую вызвать операцию извлечения в модели представления и отправить ее, отправив ее в Activity/ фрагмент в виде liveata.observe.
Обычно Room
обрабатывать запросы синхронно, но используя его вместе LiveData
эти запросы выполняются асинхронно, поэтому при вызове этой строки:
LiveData<List<Period>> periodList = MyApplication.getDatabase().dao().getAllPeriodList();
вы фактически получаете пустой контейнер, который будет обновляться после выполнения и завершения запроса. Таким образом, чтобы получить результат запроса или даже выполнить запрос в первую очередь, вы должны наблюдать возвращаемый результат. LiveData
,
Теперь обычный сценарий состоит в том, чтобы просто передать LiveData
тот Room
предоставить из ViewModel в ваш вид, а затем наблюдать за LiveData
для изменений в представлении.
Внутри ViewModel:
public LiveData<List<Period>> getPeriods() {
return MyApplication.getDatabase().dao().getAllPeriodList();
}
Вид изнутри:
viewModel.getPeriods().observe(this, new Observer<List<Period>>() {
@Override
public void onChanged(@Nullable List<Period> periods) {
updateList(periods);
}
});