Android中PutExtra传递数据至CardView显示异常问题
解决ListView点击传递数据错误的问题
你遇到的核心问题是把ListView的OnItemClickListener错误地放在了populateView方法内部。这个方法会在每一个列表项渲染时执行一次,相当于给ListView重复绑定了N次点击监听器(N为列表项总数),最后实际生效的是最后一次循环中绑定的监听器——所以不管你点击哪个列表项,传递的都是最后一个渲染项的model数据。
修复步骤及代码示例
第一步:调整MainActivity中的监听器位置
把点击监听器从populateView内部移出,只在适配器初始化完成后设置一次,通过position从适配器获取对应位置的正确数据:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = findViewById(R.id.list_view_database); userSearchView = findViewById(R.id.searchViewUsuario); mDatabase = FirebaseDatabase.getInstance().getReference(); Query query = FirebaseDatabase.getInstance() .getReference() .child("Usuarios"); FirebaseListOptions<Usuarios> options = new FirebaseListOptions.Builder<Usuarios>() .setQuery(query, Usuarios.class) .setLayout(R.layout.item_row) .build(); adapter = new FirebaseListAdapter<Usuarios>(options) { @Override protected void populateView(View v, final Usuarios model, int position) { // 这里只做视图绑定工作,不要放置点击监听器 final TextView textName = v.findViewById(R.id.NombreUsuario); textName.setText(model.getNombre()); final TextView textEmail = v.findViewById(R.id.Email); textEmail.setText("Email: " + model.getEmail()); final TextView textPago = v.findViewById(R.id.imgBtnPago); textPago.setText(model.getPago()); } }; // 将点击监听器移到此处,仅设置一次 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { // 获取当前点击位置的正确用户数据 Usuarios clickedUser = adapter.getItem(position); if (clickedUser == null) return; Toast.makeText(MainActivity.this, ""+adapter.getRef(position).getKey(), Toast.LENGTH_SHORT).show(); Intent intent = new Intent(MainActivity.this, UserEdit.class); intent.putExtra("Nombre", clickedUser.getNombre()); intent.putExtra("Email", clickedUser.getEmail()); intent.putExtra("Pago", clickedUser.getPago()); startActivity(intent); } }); // 给ListView设置适配器(如果之前没加的话) mListView.setAdapter(adapter); }
第二步:优化接收数据的代码(可选,增加稳定性)
在接收数据的UserEdit页面,增加空值判断避免空指针异常,同时简化ToggleButton的逻辑:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.cardview_usuario); mNombre = findViewById(R.id.NombreUsuario); mEmail = findViewById(R.id.Email); mToogleBtn = findViewById(R.id.toggleButton); Intent iin = getIntent(); Bundle b = iin.getExtras(); if(b != null) { String n = (String) b.get("Nombre"); String e = (String) b.get("Email"); String p = (String) b.get("Pago"); // 空值判断,防止NullPointerException if(n != null) mNombre.setText("Nombre: "+n); if(e != null) mEmail.setText("Email: "+e); // 简化ToggleButton状态设置逻辑 if(p != null) { mToogleBtn.setChecked("1".equals(p)); } } }
问题原因再梳理
populateView方法会为每个列表项执行一次,每次执行都会给ListView覆盖式设置新的点击监听器。当你点击任意列表项时,触发的是最后一次设置的监听器,而该监听器绑定的model是最后一个列表项的对象,这就导致传递的数据始终错误。把监听器移到populateView外部,通过position从适配器获取对应位置的数据,就能拿到点击项的正确信息了。
内容的提问来源于stack exchange,提问作者Gastón Saillán
相关产品推荐
相关产品推荐

