如何在 Kotlin 中使用与 Activity 和 Fragment 相同的 RecyclerView 适配器?

How to use the same RecyclerView adapter with Activity and Fragment in Kotlin?

我创建了一个完美运行的应用程序。我决定对我的应用程序进行一些更改,即在某些地方使用 Fragment 而不是 Activity。 activity 中有一个 RecyclerView,用于加载从 Firestore 中获取的数据。除了将使用 Fragment 而不是 Activity.

之外,一切都将保持不变

现在我遇到的问题是 recyclerView 适配器需要上下文。

open class CargoListAdapter(
    private val context: Context,
    private var list: ArrayList<Cargo>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

单击按钮时,我必须检查上下文以采取相应的进一步操作。

            holder.binding.ibDelete.setOnClickListener {

            when (context) {
                is OrderActivity -> {
                    val activity = holder.itemView.context as? OrderActivity

                    activity?.viewSpecialRequest(
                        model.custom_request
                    )
                }

                is MyOrderDetailsActivity -> {
                    val activity = holder.itemView.context as? MyOrderDetailsActivity

                    activity?.viewSpecialRequest(
                        model.custom_request
                    )
                }

                is CargoFragment -> {
                    val activity = holder.itemView.context as? CargoFragment

                    activity?.editDeleteSpecialRequestDialog(
                        holder.binding.ibEditDeleteNote,
                        holder.binding.ibAddNote,
                        model.id,
                        model.custom_request
                    )

                }
            }
        }

这就是我在其中一项活动中打电话的方式。

val cargoListAdapter = CargoListAdapter(this@OrderActivity, mCargoList)

我尝试像下面这样从 fragment 调用,但我在 is CargoFragment -> {

看到错误“不兼容的类型:CargoFragment 和上下文”
val cargoListAdapter = CargoListAdapter(requireContext(), mCargoList)

编辑: 这不是问题的一部分,而是展示当 recyclerView 中有几个按钮时我做了什么,并根据单击哪个按钮采取行动。已采纳答案的评论区已经有人问过了

现在适配器 class 的 onClickItem 已根据我的要求更改。如您所见,我有 action:String,这会让我知道单击了哪个按钮以及 function/action 需要进一步完成什么。

open class CargoListAdapter(
    private val context: Context,
    private var list: ArrayList<Cargo>,
    private val onClickItem: (pos: Int,addButton: ImageButton,deleteButton: ImageButton,model: Cargo,action:String) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>()

onBindViewHolder 我有以下内容。

 holder.binding.ibRemoveItem.setOnClickListener {
                        onClickItem(holder.adapterPosition,
                            holder.binding.ibAddNote,
                            holder.binding.ibDeleteNote,
                            model,
                            "removeItem")
}

每当单击一个按钮时,按钮 onClickListener 就会像上面那样设置,并且根据按钮我会更改 'action' 的值。如您所见,在上面的示例中,它是 'removeItem',因此从下面的代码中,将发生 'removeItem' 下的操作。 以下是我在 'CargoFragment'

中的内容
when (action) {
"DeleteNote" -> {
 ///TAKE SOME ACTION HERE
}
"AddNote" -> {
///TAKE SOME ACTION HERE
 }
"removeItem" -> {
///TAKE SOME ACTION HERE
}

这就是我为处理 recyclerView 中有多个按钮的情况所做的工作,并且它没有任何缺陷。希望有高手给点意见,让新手知道可不可以照着做。

您检查上下文,然后将其转换为创建适配器的 activity 或片段,并且在您调用 activity/fragment 方法后 viewSpecialRequest 这不是很正确,如果您要在单击 ibDelete 后调用 activity/fragment 方法,您需要添加一个接口。

open class CargoListAdapter(
    private val context: Context,
    private var list: ArrayList<Cargo>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

interface OnItemActionsListener {
        fun onDeleteClicked()
    }

var onItemActionsListener:OnItemActionsListener? =null

 holder.binding.ibDelete.setOnClickListener {
     onItemActionsListener?.onDeleteClicked()
 } 

********* 
 }
}

订单活动

adapter = CargoListAdapter(this, arrayListOf())
adapter.onItemActionsListener = object  : CargoListAdapter.OnItemActionsListener {
                    override fun onDeleteClicked() {
                        // TODO logic
                    }
                }

CargoFragment

adapter = CargoListAdapter(requireActivity(), arrayListOf())
adapter.onItemActionsListener = object  : CargoListAdapter.OnItemActionsListener {
                    override fun onDeleteClicked() {
                        // TODO logic
                    }
                }

如果您需要在适配器中执行逻辑,而不是上下文检查,您可以使用枚举。

public enum DeleteCaseEnum {
    NONE, CASE_1, CASE_2, CASE_3
}

open class CargoListAdapter(
    private val context: Context,
    private var list: ArrayList<Cargo>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

var deleteCase:DeleteCaseEnum  = DeleteCaseEnum .NONE

   holder.binding.ibDelete.setOnClickListener {

            when (deleteCase) {
                is DeleteCaseEnum.CASE_1-> {
                 // TODO
                }
              
                is DeleteCaseEnum.CASE_2-> {
                 // TODO
                }
            }

订单活动

adapter = CargoListAdapter(this, arrayListOf())
adapter.deleteCase = DeleteCaseEnum.CASE_1

CargoFragment

adapter = CargoListAdapter(requireActivity(), arrayListOf())
adapter.deleteCase = DeleteCaseEnum.CASE_2

您可以使用 Kotlin 高阶函数使适配器独立并在代码中的任何位置使用它,而不是使用接口并通过使用 Activity 或 Fragment 实例访问函数。

open class CargoListAdapter(
    private val context: Context,
    private var list: ArrayList<Cargo>,
    private val onClickItem:(pos: Int, viewId: Int) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

点击时在 ViewHolder 中调用 onClickItem :

    holder.binding.ibDelete.setOnClickListener {
        onClickItem(adapterPosition, it.id)
    }

    holder.binding.ibEdit.setOnClickListener {
        onClickItem(adapterPosition, it.id)
    }

在 Activity 或片段中:

adapter = CargoListAdapter(context, list){position, viewId->
   //receive click here
    when(viewId){
        R.id.ibDelete -> //Delete Action
        R.id.ibEdit -> //Delete Action
        // You can use sam click listener for multiple views by passing id
    }
}

查看此要点以获得完整的适配器示例:https://github.com/Noddy20/Gists/blob/master/RecyclerViewAdapter-1.kt