You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:52:18