无法在 RecyclerView.Adapter 类 Kotlin 中获取 ViewModel 实例

Mic*_*ael 3 android mvvm kotlin android-recyclerview

我是 Kotlin 的新手,正在尝试创建一个闹钟应用程序。在这个应用程序中,我使用了 LiveData 和 RecycleView。现在我需要更改警报状态:

切换台

这是我尝试创建的AlarmsRecyclerAdapter.onClickListener{}

override fun onBindViewHolder(holder: AlarmsRecyclerAdapter.AlarmItemHolder, position: Int) {
        //mAlarmViewModel = ViewModelProviders.of( context as Fragment)[AlarmViewModel::class.java]
        if (mAlarms != null) {
            val current = mAlarms!!.get(position)
            holder.view.edit_time_button.text = current.printTime()
            holder.view.switch_alarm_enabled.isEnabled = current.enabled

            holder.view.switch_alarm_enabled.setOnClickListener {
                current.enabled = !current.enabled
               // mAlarmViewModel.insert(current)
            }
        } else {
            // Covers the case of data not being ready yet.
            holder.view.edit_time_button.text = "no timer"
        }
    }
Run Code Online (Sandbox Code Playgroud)

我还尝试ViewModel在注释行中获取实例,但它只会引发错误,例如

java.lang.ClassCastException: android.app.Application 无法转换为 com.xxx.alarm.AlarmsRecyclerAdapter.onBindViewHolder(AlarmsRecyclerAdapter.kt:58) 处的 androidx.fragment.app.FragmentActivity com.xxx.alarm.AlarmsRecyclerAdapter.onBindViewHolder( AlarmsRecyclerAdapter.kt:33)

我需要更改数据库中的警报,那么如何ViewModel在适配器类中获取 的实例?或者有没有更好的方法来管理数据变化?

小智 5

不太确定将 ViewModel 放入 RecyclerView 中,也不确定这是否被视为最佳实践。但这是我这样做的方式,其他人也看到这样做了。首先,您在 Fragment 中创建您的 ViewModel。然后您观察您的 AlarmData,当它发生变化时,您会更新 RecyclerAdapter 中的数据。

所以在你的 Fragment 你做这样的事情():

mAlarmViewModel = ViewModelProviders.of( context as Fragment)[AlarmViewModel::class.java]
mAlarmViewMode.getAlarms().observe(...
    mAdapter.setData(newData)
Run Code Online (Sandbox Code Playgroud)

并在您的 Adapter 中添加以下内容:

setData(data:List) {
    mAlarms= data;
    notifyDataSetChanged();
}    
Run Code Online (Sandbox Code Playgroud)

这应该使您的数据保持更新。

现在更改您的数据。尝试在您的 ViewHolder 中设置 OnclickListener,因为这将提高您的应用程序的速度。要获得您的当前价值,您可以这样做:

val current = mAlarms!!.get(getAdapterPosition())
Run Code Online (Sandbox Code Playgroud)

最后,您应该向您的适配器添加一个接口,如下所示:

interface ItemSelectedListener {
  fun onItemSelected(item:Any, v:View)
}
Run Code Online (Sandbox Code Playgroud)

从您的 Fragment 设置此接口并从 onClickListener 调用它。然后你在你的 Fragment 中拥有你需要的所有数据,并且可以从那里修改它