Fragment中RecyclerView的onItemClick事件未触发问题排查
问题原因分析
你的RecyclerView点击事件未触发,核心问题在于重复设置Adapter且新Adapter未绑定点击监听:
- 你先初始化了基于空列表的
TaskAdapter(list),并给这个adapter绑定了点击监听,随后将它设置给RecyclerView。 - 但API请求成功后,你又创建了一个全新的
TaskAdapter(response.body()!!),直接替换了RecyclerView的adapter。这个新adapter没有调用setOnItemClickListener,所以实际显示的列表根本没有绑定点击事件。
另外还有一个潜在问题:点击监听里使用的是初始空列表list,但实际显示的是API返回的数据源,就算点击能触发,也会因为数组越界崩溃。
修复方案
推荐采用复用Adapter+更新数据的方式,避免重复创建Adapter,同时保证点击监听始终有效:
第一步:修改TaskAdapter,添加数据更新方法
class TaskAdapter(var list: List<TasksItem>) : RecyclerView.Adapter<TaskAdapter.MyViewHolder>() { private var listener2: OnItemClickListener? = null interface OnItemClickListener { fun onItemClick(position: Int) } fun setOnItemClickListener(listener: OnItemClickListener){ listener2 = listener } // 添加数据更新方法 fun updateData(newList: List<TasksItem>) { this.list = newList notifyDataSetChanged() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item, parent,false) return MyViewHolder(itemView,listener2) } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { val currentitem = list[position] holder.TaskName.text = currentitem.taskName holder.Date.text = currentitem.dueDate holder.Assignee.text = currentitem.assignee holder.Status.text = currentitem.taskStatus } override fun getItemCount(): Int { return list.size } class MyViewHolder(itemView : View, listener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView){ val TaskName : TextView = itemView.findViewById(R.id.tvTaskname) val Assignee : TextView = itemView.findViewById(R.id.tvAssignee) val Date : TextView = itemView.findViewById(R.id.tvDate) val Status : TextView = itemView.findViewById(R.id.tvStatus) init { itemView.setOnClickListener{ listener?.onItemClick(adapterPosition) } } } }
第二步:修改Fragment1的onViewCreated逻辑
class Fragment1 : Fragment() { private lateinit var binding: Fragment1Binding private lateinit var list : ArrayList<TasksItem> private lateinit var recyclerView: RecyclerView private lateinit var manager: RecyclerView.LayoutManager private lateinit var myAdapter: TaskAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_1, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) recyclerView = view.findViewById(R.id.app_list) recyclerView.setHasFixedSize(true) list = arrayListOf() manager = LinearLayoutManager(this.requireContext()) // 初始化Adapter并绑定点击监听 myAdapter = TaskAdapter(list) recyclerView.layoutManager = manager recyclerView.adapter = myAdapter myAdapter.setOnItemClickListener(object : TaskAdapter.OnItemClickListener { override fun onItemClick(position: Int) { // 直接使用Adapter内的数据源,避免不一致 val currentTask = myAdapter.list[position] val intent = Intent(activity, ViewTaskActivity::class.java).apply{ putExtra("taskname", currentTask.taskName) putExtra("desc", currentTask.taskDesc) putExtra("category", currentTask.category) putExtra("duedate", currentTask.dueDate) putExtra("assignee", currentTask.assignee) putExtra("point", currentTask.pointEarned) Log.d("Fragment1", "onItemClick executed, position: $position") } startActivity(intent) } }) // API请求:更新Adapter数据而非重新创建 GroomedKidzApi.retrofitService.getTasksProgress().enqueue(object : Callback<List<TasksItem>?> { override fun onResponse( call: Call<List<TasksItem>?>, response: Response<List<TasksItem>?> ) { val responseBody = response.body() if (responseBody != null) { myAdapter.updateData(responseBody) Log.e("TAG", "response 33: "+ responseBody) } } override fun onFailure(call: Call<List<TasksItem>?>, t: Throwable) { Log.e("TAG", "API请求失败", t) } }) } }
内容的提问来源于stack exchange,提问作者Alex Chong01
相关产品推荐
相关产品推荐

