单例 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