I was trying to fetch a list of custom object data from room using LiveData and viewmodel. While using Livedata's getValue() method, returns null but getting list directly shows the actual data. How can I get List of Period class using LiveData in viewmodel class.
Entity classes
@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;
}
}
Converter Class
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 class
@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
@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();
}
Get Data method in viewmodel class
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();
}
The fact is,
Asynctask
is running on another thread in background asynchronouslyLivedata
is working like floating over database to see the changes.So it takes time to accomplish the fetch operation for Asyntask
. You can see it by testing the Asynctask
within a handler of 10 sec delay.
So its better to directly call the fetch operation in view model and send it to activity/fragment as livedata.observe.