【问题标题】:How can i pass ViewModel into Adapter?如何将 ViewModel 传递给适配器?
【发布时间】:2022-02-05 01:35:38
【问题描述】:

我有一个使用房间的提醒应用。我有一个回收站视图,其中包含通过从房间数据库获取所有提醒。在每个元素中都存在结束提醒的计划日期。当元素开始设置它们的位置时,我想检查过期日期。但我只有一个想法如何做到这一点。

我认为我需要检查适配器中的过期日期,然后在适配器中调用视图模型并将数据发送到数据库。但是,我无法将视图模型传递给适配器。 无论如何,我阅读了一些主题,他们说在视图模型中传递适配器的糟糕体验。

有什么想法吗?

这是我的适配器类

class MainPageAdapter : RecyclerView.Adapter<MainPageAdapter.MyViewHolder>() {

    private var remList = emptyList<ReminderModel>()
    private lateinit var reminder : OverdueReminderModel

    class MyViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {}

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.main_page_reminders_row, parent, false))
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val list = remList[position]

        val sdf = SimpleDateFormat("dd.M.yyyy")

        holder.itemView.idForDelete.text = list.id.toString()
        holder.itemView.rowHeader.text = list.header
        holder.itemView.goneDescription.text = list.description
        holder.itemView.rowStartTime.text = list.startTime
        holder.itemView.rowEndTime.text = sdf.format(list.endTime.toLong())

        //redirect with safe args to show reminder
        holder.itemView.rowOfMainPageItems.setOnClickListener {
            val action = MainPageRemindersDirections.actionMainPageRemindersToShowFullReminder(list)
            holder.itemView.findNavController().navigate(action)
        }

        val currentDate = Calendar.getInstance().timeInMillis.toString()

        if(currentDate.toLong() > getDateInMills(holder.itemView.rowEndTime.text.toString())){
            reminder = OverdueReminderModel(
                0,
                holder.itemView.rowHeader.text.toString(),
                holder.itemView.goneDescription.text.toString(),
                getDateInMills(holder.itemView.rowEndTime.text.toString()).toString()
            )
        }
//there are two methods which i want to use for sending and deleting data
        /*
        TODO:
            overdueViewModel.addOverdueReminder(reminder)
            deleteReminderFromDatabase(Integer.parseInt(viewHolder.itemView.idForDelete.text.toString()))
         */
    }

    override fun getItemCount(): Int {
        return remList.size
    }

    @SuppressLint("NotifyDataSetChanged")
    fun setData(reminder : List<ReminderModel>){
        this.remList = reminder
        notifyDataSetChanged()
    }


    @SuppressLint("SimpleDateFormat")
    fun getDateInMills(date : String) : Long{
        val sdf = SimpleDateFormat("dd.M.yyyy")
        val dateParse = sdf.parse(date)
        val dateInMills = dateParse.time
        return dateInMills
    }
}

这就是我在适配器中发送数据的方式

        private lateinit var viewModel : ReminderViewModel


        viewModel = ViewModelProvider(this).get(ReminderViewModel::class.java)


        viewModel.readAllReminders.observe(viewLifecycleOwner, Observer {
            adapter.setData(it)
        })

【问题讨论】:

  • 为了清晰地分离关注点,您不应该将视图模型传递给适配器。让适配器公开一个回调接口,该接口由 ViewHolders 中视图的单击侦听器调用。承载 RecyclerView 的 Activity 或 Fragment 可以实现这个接口并让它与 ViewModel 通信。

标签: android kotlin android-recyclerview android-room


【解决方案1】:

您可以简单地使用 Kotlin lambda 函数,

在您的适配器类中添加这些函数和属性

private lateinit var overdueCallback : (item: ReminderModel) -> Unit

fun overdueListener(callback: (item: ReminderModel) -> Unit){
    overdueCallback = callback
}

如下调用ViewModel中的函数,处理item。

adapter.overdueListener{
       //it: Reminder Model
       // Code to handle the item from adapter
}

当你想将 item 传递给 ViewModel 时,然后调用

overdueCallback(reminderItem)

【讨论】:

  • 效果很好!我试图解决这个问题 2 天。谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 2019-08-30
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多