База данных комнат 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 ответа

Решение

Дело в том,

  1. Asynctask работает в другом потоке в фоновом режиме асинхронно
  2. 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); 
    }
});
Другие вопросы по тегам