Reputation:
I am using a Java codebase of an app to build another app in Kotlin. I've written a class AppDatabase
extending RoomDatabase
that is a singleton. It works once, and the other times the class isn't called. This is the class:
@Database(entities = [Classes::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun classesDao() : ClassesDao
}
object DatabaseProvider {
private var database: String = "db_classes"
private var sInstance: AppDatabase? = null
fun getInstance(context: Context) : AppDatabase {
if (sInstance == null) {
sInstance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
database
).build()
}
return sInstance!!
}
}
My MainActivity
displays a CalendarView
that will fetch data by the selected date (so far it fetches after I pressed a date).
...
...
mCalendar = findViewById(R.id.calendar)
mCalendar?.setOnDateChangeListener { _, y, m, d ->
mSelectedDate = DateUtils.convertToDate(y.toString(), m.toString(), d.toString())
fetchClasses()
}
...
...
private fun fetchClasses() {
val modelFactory = MainViewModelFactory(this.applicationContext, mSelectedDate!!)
val classesViewModel = ViewModelProviders.of(this, modelFactory).get(MainViewModel::class.java)
classesViewModel.getClasses().observe(this, Observer<List<Classes>> {
if (it!!.isEmpty()) {
mRvClasses?.visibility = View.GONE
mTvNoClasses?.visibility = View.VISIBLE
mImgNoClasses?.visibility = View.VISIBLE
}
mAdapter?.setClasses(it)
})
}
The MainViewModel
:
class MainViewModel(context: Context, date: String) : ViewModel() {
private var classes: LiveData<List<Classes>>? = null
private var db: AppDatabase? = null
init {
db = DatabaseProvider.getInstance(context)
classes = db?.classesDao()?.getClassesByDate(date)
}
fun getClasses() : LiveData<List<Classes>> {
return classes!!
}
}
It works, but I noticed that if I switch the date, it will not be called anymore. If I, for example after the app opens select one date only, I can store as many records for that date as I want, but the moment I switch the date, it will stop being called and inserted.
This is the Java code I based on:
@Database(entities = { TaskEntry.class }, version = 1, exportSchema = false)
@TypeConverters(DateConverter.class)
public abstract class AppDatabase extends RoomDatabase {
private static final Object LOCK = new Object();
private static final String DATABASE_NAME = "todolist";
private static AppDatabase sInstance;
public static AppDatabase getInstance(Context context) {
if (sInstance == null) {
synchronized (LOCK) {
sInstance = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, AppDatabase.DATABASE_NAME).build();
}
}
return sInstance;
}
public abstract TaskDao taskDao();
}
Upvotes: 1
Views: 776
Reputation: 14660
You should invoke a new SQL
query when the date is modified. First, modify your ViewModel
so that it reacts to Date
changes:
class MainViewModel(context: Context, date: String) : ViewModel() {
private var db: AppDatabase? = null
private val dateInput = MutableLiveData<String>()
val classes: LiveData<List<Classes>>
init {
db = DatabaseProvider.getInstance(context)
dateInput.value = date
classes = Transformations.switchMap(dateInput, {
db?.classesDao()?.getClassesByDate(it)
})
}
fun setDate(date: String) {
dateInput.value = date
}
}
Then, in your MainActivity
onCreate(...)
each time a Date
changes just call classesViewModel.setDate(mSelectedDate)
. I removed fetchClasses()
because there's no need to call each time but only in onCreate
:
override fun onCreate(savedInstanceState: Bundle?) {
...
mCalendar = findViewById(R.id.calendar)
mCalendar?.setOnDateChangeListener { _, y, m, d ->
mSelectedDate = DateUtils.convertToDate(y.toString(), m.toString(), d.toString())
// just update the date and nothing else is needed
classesViewModel.setDate(mSelectedDate)
}
val modelFactory = MainViewModelFactory(this.applicationContext, mSelectedDate)
val classesViewModel = ViewModelProviders.of(this, modelFactory).get(MainViewModel::class.java)
classesViewModel.classes.observe(this, Observer<List<Classes>> {
if (it!!.isEmpty()) {
mRvClasses?.visibility = View.GONE
mTvNoClasses?.visibility = View.VISIBLE
mImgNoClasses?.visibility = View.VISIBLE
}
mAdapter?.setClasses(it)
})
...
}
For more info please look here
Upvotes: 0