我的项目中有一个RecyclerView适配器和一个按钮。 当我单击按钮时,我想从服务器中删除其项目,然后从RecyclerView中删除它。 我想通过观察LiveData来做到这一点(当它从服务器中删除时,我必须从回收者视图中将其删除,因此我需要服务器的结果) 最佳做法是什么(我必须观察片段中的内容并将侦听器传递给适配器,并在片段中实现该功能,并且当用户单击按钮时在片段中调用方法,否则有更好的方法可以做到这一点)?
答案 0 :(得分:3)
在几篇文章中进行全面搜索之后,终于找到了推荐的解决方案。 步骤1:在您的适配器中声明一个接口,如下所示:
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()
}
})
}
}
答案 1 :(得分:1)
我知道现在回答已经太晚了。 但我希望它能帮助其他开发者寻找类似问题的解决方案。
看看LiveAdapter。
您只需要在 Gradle 中添加最新的依赖项即可。
dependencies {
implementation 'com.github.RaviKoradiya:LiveAdapter:1.3.2-1608532016'
// kapt 'com.android.databinding:compiler:GRADLE_PLUGIN_VERSION' // this line only for Kotlin projects
}
并将适配器与您的 RecyclerView 绑定
LiveAdapter(
data = liveListOfItems,
lifecycleOwner = this@MainActivity,
variable = BR.item )
.map<Header, ItemHeaderBinding>(R.layout.item_header) {
areContentsTheSame { old: Header, new: Header ->
return@areContentsTheSame old.text == new.text
}
}
.map<Point, ItemPointBinding>(R.layout.item_point) {
areContentsTheSame { old: Point, new: Point ->
return@areContentsTheSame old.id == new.id
}
}
.into(recyclerview)
就是这样。不需要为适配器实现编写额外的代码,观察 LiveData 并通知适配器。
答案 2 :(得分:0)
我认为使用notifyDataSetChanged是可以的。 我的 ViewModel 中有公司作为 LiveData。我可以像这样在 onCreateView 片段中观察它
viewModel.companies.observe(viewLifecycleOwner, {
binding.searchResultsRecyclerView.adapter?.notifyDataSetChanged()
})
当公司有任何变化时,recyclerView 会更新。