我试图使用LiveData和viewmodel从房间中获取自定义对象数据列表。使用Livedata的getValue()方法时,返回null但直接获取列表显示实际数据。如何在viewmodel类中使用LiveData获取Period类的List。
实体类
@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类中获取Data方法
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();
}
事实上,
Asynctask
异步运行在后台的另一个线程上Livedata
正在像浮动数据库一样工作以查看更改。因此,完成Asyntask
的获取操作需要时间。您可以通过在10秒延迟的处理程序中测试Asynctask
来查看它。因此,最好直接调用视图模型中的fetch操作,并将其作为livedata.observe发送到activity / fragment。
通常Room
处理查询同步但在LiveData
上使用它们这些查询以异步方式执行,所以当你调用这行时:
LiveData<List<Period>> periodList = MyApplication.getDatabase().dao().getAllPeriodList();
,你实际上得到一个空容器,它将在执行和完成查询后得到更新。因此,要获取查询结果或甚至查询首先执行,您必须观察返回的LiveData
。
现在通常的情况是将LiveData
提供的Room
从ViewModel传递到您的View,然后观察LiveData
以查看View中的更改。
在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);
}
});