我有一个RecyclerView适配器和一个按钮.

当我点击按钮时,我想从服务器上删除它的项目,然后从RecyclerView中删除.

I want to do that by observing LiveData (when it removed from server I have to remove it from recycler view thus I need the result of server)

What is the best practice way to do that - I must observe in the fragment and pass a listener to the adapter and implement that in the fragment and when user clicked on the button call a method in fragment or there is a better way to do that?

推荐答案

After a full searching in several posts, finally, I found the recommended solution. Step 1: declare an interface in your adapter as below:

class AddExpenseLabelAdapter(
    val items: List<LabelResponse>, 
    val context: Context, 
    val listener: OnLabelClickListener
) : RecyclerView.Adapter<AddExpenseLabelAdapter.ViewHolder>() {

    interface OnLabelClickListener {
        fun onLabelDeleteButtonClicked(request : SubCategoryLabelRequest)
    }

    lateinit var binding: ItemListExpenseAddLabelBinding

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(context)
        val binding = ItemListExpenseAddLabelBinding.inflate(inflater)
        this.binding = binding
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(items[position])
    }

    override fun getItemCount(): Int = items.size

    inner class ViewHolder(val binding: ItemListExpenseAddLabelBinding) : RecyclerView.ViewHolder(binding.root), OnClickListener {
        lateinit var item: LabelResponse
        fun bind(item: LabelResponse) {
            this.item = item
            binding.itemListLabelLayout.setBackgroundColor(Color.parseColor("#" + item.color))
            binding.labelResponse = item
            binding.onClickListener = this
            binding.executePendingBindings()
        }

        override fun onClick(view: View) {
            if (view.id == binding.itemListLabelLayout.id) {
                val subCategoryLabelRequest = SubCategoryLabelRequest(item.id)
                listener.onLabelDeleteButtonClicked(subCategoryLabelRequest)
            }
        }
    }
}

第2步:在视图中实现接口,并将其传递给适配器,如下所示:

class AddExpenseLabelDialog : DialogFragment(), AddExpenseLabelAdapter.OnLabelClickListener {

    lateinit var binding: DialogAddExpenseLabelBinding

    lateinit var view: Any

    var expenseId: Int = 0
    var categoryId: Int = 0

    lateinit var application: MyApplication

    lateinit var addExpenseLabelViewModel: AddExpenseLabelViewModel

    fun newInstance(expenseId: Int, categoryId: Int): AddExpenseLabelDialog = 
        AddExpenseLabelDialog().also { fragment ->
            arguments = Bundle().also { bundle ->
                bundle.putInt("expenseId", expenseId)
                bundle.putInt("categoryId", categoryId)
            }
        }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        binding = DataBindingUtil.inflate(layoutInflater, R.layout.dialog_add_expense_label, container, false)
        addExpenseLabelViewModel = ViewModelProviders.of(this).get(AddExpenseLabelViewModel::class.java)
        expenseId = arguments!!.getInt("expenseId")
        categoryId = arguments!!.getInt("categoryId")
        initialize()
        view = binding.root
        return view as View
    }

    fun initialize() {

        binding.labelRec.layoutManager = LinearLayoutManager(context)
        addExpenseLabelViewModel.liveData.observe(this, Observer { response ->
            binding.labelRec.adapter = AddExpenseLabelAdapter(response as ArrayList<LabelResponse>, context!!, this)
        })
    }

    override fun onLabelDeleteButtonClicked(request : SubCategoryLabelRequest) {
        addExpenseLabelViewModel.createExpenseLabel(categoryId, expenseId, request).observe(this, Observer { response ->
            when (response?.status) {
                Status.LOADING -> Toast.makeText(activity, "LOADING", Toast.LENGTH_SHORT).show()
                Status.SUCCESS -> {
                    dismiss()
                    Toast.makeText(activity, "SUCCESS", Toast.LENGTH_SHORT).show()
                }
                else -> Toast.makeText(activity, InjectorUtil.convertCodeToMessage(response?.error?.code!!), Toast.LENGTH_SHORT).show()
            }
        })
    }
}

Kotlin相关问答推荐

有什么原因,我得到一个空相关的错误在这个代码

如何通过更改现有数据类型来执行Android房间数据库迁移?

为何Kotlin标准库中的AND和OR函数不能像&&和||一样进行短路运算?

Kotlin - 协程未按预期执行

Eclipse:无法安装 Kotlin 插件

kotest 更改环境变量

如何在 Hibernate Panache 中进行部分搜索

为什么 Kotlin 的 null 安全性不能与局部变量初始化器一起正常工作?

如何通过 compose 处理剪切区域?

奇怪的 cotlin check Not Null 参数错误

有没有办法重用 Job 实例?

Fragment的onDestroy()中是否需要将ViewBinding设置为null?

Koin Android:org.koin.error.NoBeanDefFoundException

来自类型参数的属性的自定义 getter

是否可以在 kotlin 中嵌套数据类?

API 26 上未显示 Android 通知

Kotlin Flow 收集后无法执行代码

你如何在 Kotlin 中注释 Pair 参数?

我应该在哪里调用 MobileAds.initialize()?

Kotlin中对象和数据类的区别是什么?