单例 Kotlin class 扩展 RoomDatabase 只被调用一次
Singleton Kotlin class extending RoomDatabase is called just once
我正在使用应用程序的 Java 代码库在 Kotlin 中构建另一个应用程序。我写了一个 class AppDatabase
extending RoomDatabase
是一个单例。它工作一次,其他时候不调用 class 。这是 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!!
}
}
我的 MainActivity
显示一个 CalendarView
,它将在 selected 日期之前获取数据(到目前为止,它是在我按下日期后获取的)。
...
...
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)
})
}
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!!
}
}
它有效,但我注意到如果我切换日期,它将不再被调用。例如,如果我在应用程序仅打开 select 一个日期后,我可以为该日期存储任意数量的记录,但是当我切换日期时,它将停止被调用和插入。
这是我基于的 Java 代码:
@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();
}
您应该在修改日期时调用新的 SQL
查询。首先,修改您的 ViewModel
以便它对 Date
变化做出反应:
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
}
}
然后,在您的 MainActivity
onCreate(...)
中,每次 Date
更改只需调用 classesViewModel.setDate(mSelectedDate)
。我删除了 fetchClasses()
因为不需要每次都调用但只在 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)
})
...
}
更多信息请查看here
我正在使用应用程序的 Java 代码库在 Kotlin 中构建另一个应用程序。我写了一个 class AppDatabase
extending RoomDatabase
是一个单例。它工作一次,其他时候不调用 class 。这是 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!!
}
}
我的 MainActivity
显示一个 CalendarView
,它将在 selected 日期之前获取数据(到目前为止,它是在我按下日期后获取的)。
...
...
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)
})
}
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!!
}
}
它有效,但我注意到如果我切换日期,它将不再被调用。例如,如果我在应用程序仅打开 select 一个日期后,我可以为该日期存储任意数量的记录,但是当我切换日期时,它将停止被调用和插入。
这是我基于的 Java 代码:
@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();
}
您应该在修改日期时调用新的 SQL
查询。首先,修改您的 ViewModel
以便它对 Date
变化做出反应:
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
}
}
然后,在您的 MainActivity
onCreate(...)
中,每次 Date
更改只需调用 classesViewModel.setDate(mSelectedDate)
。我删除了 fetchClasses()
因为不需要每次都调用但只在 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)
})
...
}
更多信息请查看here