【问题标题】:notifyDataSetChanged() doesn't call's onBindViewHolder() methodnotifyDataSetChanged() 不调用 onBindViewHolder() 方法
【发布时间】:2017-03-23 06:53:14
【问题描述】:

我有一个 RecyclerView 的适配器,我在其中动态添加项目,当我调用适配器的 updateMessages 函数时,旧数据列表正在正确更改,但回收站项目保持不变。

这是我的适配器中的 updateMessages 方法:

fun updateMessages(messages: List<MessageReceivedResponseModel>?){
    messages?.let {
       this.messages.clear()
       this.messages.addAll(messages)
    }
    notifyDataSetChanged()
}

这里也是完整的适配器类,我不明白是什么问题

class MessagesRecyclerAdapter(private val itemActionListener: IOnMessageItemActionListener) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

private val messages = ArrayList<MessageReceivedResponseModel>()

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.awesome_chat_item, parent, false)
    return MyHolder(view)
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    (holder as MyHolder).updateUI(messages[position])
}

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

fun updateMessages(messages: List<MessageReceivedResponseModel>?){
    messages?.let {
        this.messages.clear()
        this.messages.addAll(messages)
    }
    notifyDataSetChanged()
}

private inner class MyHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val messageTextView: TextView = itemView.findViewById(R.id.chat_from_text_id) as TextView
    private val msgQuantityTextView: TextView = itemView.findViewById(R.id.msg_quantity_txt_id) as TextView

    internal fun updateUI(msg: MessageReceivedResponseModel) {
        messageTextView.text = msg.from
        msgQuantityTextView.text = msg.quantity.toString()
    }
}

}

这是我的适配器和回收器初始化的地方

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater?.inflate(R.layout.activity_awesome_chat, container, false)
    recycler = view?.findViewById(R.id.awesome_chat_list_view_id) as RecyclerView
    val layoutManager = LinearLayoutManager(activity)
    recycler?.layoutManager = layoutManager
.....
}

override fun onMessageReceived(messages: List<MessageReceivedResponseModel>){
        adapter?.updateMessages(messages)
        Log.e(TAG, messages.size.toString())
  }
// called in oncreateView of fragment
private fun initRecycler(items: List<MessageReceivedResponseModel>?) {
    adapter = MessagesRecyclerAdapter(this)
    adapter?.updateMessages(items)
    recycler?.adapter = adapter
    Log.e(TAG, items?.size.toString())
}

【问题讨论】:

  • 尝试将 updateMessages 方法移动到您使用适配器的活动中。
  • 从我的活动中调用适配器?.updateMessages(messages:List)
  • 你能展示你的活动在哪里使用适配器吗?
  • 查看 onMessageReceived() 方法

标签: java android listview android-recyclerview kotlin


【解决方案1】:

我意识到我的问题在所有这些类中,问题出在我的交互器类中,从那里开始检索请求的消息

fun startMessageRetrieveRequest(callback: OnRequestFinishedListener<List<MessageReceivedResponseModel>>){
    doAsync {
        Thread.sleep(1000)
        val idx = Random().nextInt(2)
        val its: List<MessageReceivedResponseModel>
        when(idx){
            0 -> its = REs
            1 -> its = RES_1
            else -> its = RES_1
        }
        callback.onResponse(its)
    }
}

我删除了 doAsync 并正常工作,这里 callback.onResponse() 是从非 UI 线程调用的,它导致了问题 Only the original thread that created a view hierarchy can touch its views.,但并非总是如此。应用程序也没有崩溃,我错过了日志

【讨论】:

    【解决方案2】:

    尝试使用notifyItemRangeChanged(0, messages.size - 1);

    fun updateMessages(messages: List<MessageReceivedResponseModel>?){
        messages?.let {
            this.messages.clear()
            this.messages.addAll(messages)
            this.notifyItemRangeChanged(0, messages.size - 1)
        }
    }
    

    我认为 notifyDataSetChanged() 不起作用,因为您的数据集(messages 字段)仍然是同一个对象。

    您可以尝试替换消息对象:

    fun updateMessages(messages: List<MessageReceivedResponseModel>?){
        messages?.let {
            this.messages = messages
            notifyDataSetChanged()
        }
    }
    

    【讨论】:

    • 我意识到我的问题
    【解决方案3】:

    您应该在适配器上使用notifyDataSetChanged();,如下所示: adapter.notifyDataSetChanged(); 。 如果你想使用一个类,你只需要将适配器变量声明为类的成员变量,然后像我上面所说的那样调用方法。其中adapter 是您的适配器的名称。

    【讨论】:

    • 他在适配器内更新适配器,没有问题。
    • 你的意思是从片段调用适配器通知方法?
    • 如果我像 initRecycler(listOf(MessageReceivedResponseModel("from",1))) 那样将虚拟数据传递给 oncreateView() 内部的 initRecycler() ,它工作正常,但如果我使用这种方法在 onMessageReceived() 方法内部它不起作用
    • 是的。尝试调用 notifyDataSetChanged();调用后调用 initRecycler。也许它在函数中不起作用
    • 你能把整个onCreateView贴出来吗?
    猜你喜欢
    • 2019-01-15
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多