RecyclerView onBindViewHolder点击跳转Activity始终打开同页面
问题根因
你现在点击任意列表项都打开同一个页面,核心问题有两个:
- 构造跳转Intent时把目标Activity写死成了
show_teachers.class,完全没有根据点击条目的数据/位置区分跳转目标 - 如果你原本的需求是点击不同条目打开同一个详情页、只是展示对应条目内容,那你没有给Intent传入当前点击条目的唯一标识(比如教师ID),导致
show_teachers页面启动后拿不到对应条目数据,每次加载的都是默认内容,看起来和点其他条目打开的页面完全一致。
另外你的代码还有两个可优化的隐患:
- 不要在
onBindViewHolder里反复绑定点击事件,列表滚动复用ViewHolder时会重复创建监听器,带来不必要的性能开销,点击事件应该放在ViewHolder构造方法里统一绑定 - 启动Activity不要用
ApplicationContext,直接传入宿主Activity的Context即可,否则部分Android版本上会因为缺少Activity启动栈的flag抛出异常。
修正方案
第一步:调整点击事件绑定位置,不要在onBind里重复设监听
把点击事件逻辑移到ViewHolder的构造方法中,在onBind里只做数据和ViewHolder的绑定即可。
第二步:根据业务需求处理跳转逻辑
- 如果需要根据条目内容跳转到不同Activity:在点击时通过当前绑定的条目数据判断要跳转的目标类,不要写死类名
- 如果是跳转到同一个详情页展示不同内容:跳转时把当前条目的唯一标识(比如从MySQL拉取的教师ID)通过Intent传给目标页面,目标页拿到参数后加载对应数据展示即可。
修正后的Adapter代码参考:
public class TeacherAdapter extends RecyclerView.Adapter<TeacherAdapter.ViewHolder> { private Context mContext; private List<Setter> teacherList; // 构造时传入Activity类型的Context,不要传Application上下文 public TeacherAdapter(Context context, List<Setter> list) { this.mContext = context; this.teacherList = list; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.your_teacher_item_layout, parent, false); return new ViewHolder(itemView); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Setter currentTeacher = teacherList.get(position); // 只做数据绑定,不绑定点击事件 holder.name.setText(currentTeacher.get_TName()); holder.Age.setText("Age: " + currentTeacher.get_age()); holder.Contact.setText("Contact: " + currentTeacher.get_Contact()); holder.Address.setText("Qualification: " + currentTeacher.getAddressd()); holder.qualification.setText("Subject: " + currentTeacher.get_Qualification()); holder.Rate.setText("Rates: " + currentTeacher.get_Rates()); holder.time.setText("Time: " + currentTeacher.get_Time()); holder.Special.setText("Address: " + currentTeacher.get_subject()); // 把当前条目的数据和位置绑定到holder,点击时直接取用 holder.bindData(currentTeacher, position); } @Override public int getItemCount() { return teacherList == null ? 0 : teacherList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { TextView name, Age, Contact, Address, qualification, Rate, time, Special; Button btn; Setter currentTeacher; int currentPos; public ViewHolder(@NonNull View itemView) { super(itemView); // 初始化控件,替换成你布局里对应的控件ID name = itemView.findViewById(R.id.tv_name); Age = itemView.findViewById(R.id.tv_age); Contact = itemView.findViewById(R.id.tv_contact); Address = itemView.findViewById(R.id.tv_address); qualification = itemView.findViewById(R.id.tv_qualification); Rate = itemView.findViewById(R.id.tv_rate); time = itemView.findViewById(R.id.tv_time); Special = itemView.findViewById(R.id.tv_special); btn = itemView.findViewById(R.id.btn); // 在这里统一绑定点击事件,不会重复创建监听器 btn.setOnClickListener(v -> { Toast.makeText(mContext, "yes", Toast.LENGTH_SHORT).show(); Intent jumpIntent; // -------------------------- // 这里替换成你自己的跳转逻辑 // -------------------------- // 场景1:需要跳不同页面的示例:根据教师费率跳不同详情页 if (currentTeacher.get_Rates() >= 100) { jumpIntent = new Intent(mContext, HighLevelTeacherDetail.class); } else { jumpIntent = new Intent(mContext, NormalTeacherDetail.class); } // 场景2:跳同一个详情页展示不同内容,就写死目标类,但是传参 // jumpIntent = new Intent(mContext, show_teachers.class); // 把当前教师的唯一ID传给目标页,目标页拿ID去查对应数据展示 // jumpIntent.putExtra("teacher_id", currentTeacher.get_TeacherId()); mContext.startActivity(jumpIntent); }); } public void bindData(Setter teacher, int position) { this.currentTeacher = teacher; this.currentPos = position; } } }
注意:你的列表数据是从MySQL拉取的,每个教师条目一定有唯一主键ID,跳转详情页时必须传入这个ID,目标页启动后根据ID拉取对应教师的详情数据渲染,就不会出现所有点击打开页面内容完全相同的问题。
内容的提问来源于stack exchange,提问作者moaz
相关产品推荐
相关产品推荐

