Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Room database Livedata getValue() returns null

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();

}
like image 597
Razon Avatar asked Aug 18 '26 11:08

Razon


1 Answers

Usually Room handle queries Synchronously but using it along LiveData these queries get execute in an ASynchronous manner, so when you call this line:

LiveData<List<Period>> periodList = MyApplication.getDatabase().dao().getAllPeriodList();

, you actually get an empty container which will get updated after the query is executed and completed. So to get the result of the query or even for the query to get executed in the first place, you must observe the returned LiveData.

Now the usual scenario is to just pass the LiveData that Room provides from ViewModel to your View and then observe the LiveData for changes in View.

Inside ViewModel:

public LiveData<List<Period>> getAllPeriods() {
    return MyApplication.getDatabase().dao().getAllPeriodList();
}

Inside View:

viewModel.getAllPeriods().observe(this, new Observer<List<Period>>() {
    @Override
    public void onChanged(@Nullable List<Period> periods) {
        updateList(periods); 
    }
});
like image 55
Keivan Esbati Avatar answered Aug 20 '26 03:08

Keivan Esbati



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!