联系人APP搜索后点击列表项跳转显示错误数据问题排查
问题原因分析
你遇到的问题核心在于搜索过滤后,点击事件混用了原始联系人数组和过滤后列表的位置索引,两者完全不匹配:
- 初始状态下,ListView展示的是原始数组
arr的内容,点击时用position从arr取数据是正常的。 - 但当你搜索过滤后,你创建了新的过滤列表
listObjects并设置给了新的Adapter,此时ListView的每个item对应的position是过滤后列表的索引,可你点击时依然传递原始数组arr和这个position——这就导致用过滤后的索引去原始数组里取值,自然会拿到错误的联系人数据。
解决方案
我们需要保存当前ListView正在展示的列表,点击时从这个展示列表中获取对应位置的联系人,而不是依赖原始数组。同时优化数据传递方式,直接传递选中的联系人对象而非整个数组,更简洁高效。
步骤1:添加成员变量保存当前展示列表
在showAllContacts类中新增一个成员变量,用来记录当前ListView显示的联系人列表:
public class showAllContacts extends AppCompatActivity { String name, phone, mail; ArrayList<listObject> arr = new ArrayList<>(); ListView listView; EditText search; ListAdapter adapter; private ArrayList<listObject> currentDisplayList; // 新增:保存当前展示的列表 // ... 其他原有代码 }
步骤2:初始化当前展示列表
在onCreate方法中初始化ListView时,把原始数组赋值给currentDisplayList:
// get data from databse and put it in array arr = dp.getAllRecords(); currentDisplayList = new ArrayList<>(arr); // 初始为原始列表 adapter = new ListAdapter(showAllContacts.this, R.layout.list_design, currentDisplayList); listView.setAdapter(adapter);
步骤3:更新搜索过滤逻辑
在搜索的onTextChanged方法中,把过滤后的列表赋值给currentDisplayList:
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { int textlength = s.length(); ArrayList<listObject> listObjects = new ArrayList<>(); for (listObject c : arr) { if (textlength <= c.Name.length()) { if (c.Name.toLowerCase().contains(s.toString().toLowerCase())) { listObjects.add(c); } } } currentDisplayList = listObjects; // 更新当前展示列表 adapter = new ListAdapter(showAllContacts.this, R.layout.list_design, currentDisplayList); listView.setAdapter(adapter); }
步骤4:修改点击事件逻辑
点击时直接从currentDisplayList中获取选中的联系人对象,传递到下一个Activity:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(showAllContacts.this, userPage.class); // 获取当前展示列表中对应位置的联系人 listObject selectedUser = currentDisplayList.get(position); // 直接传递选中的对象(确保listObject已经实现Serializable接口) intent.putExtra("selectedUser", selectedUser); startActivity(intent); } });
步骤5:在userPage中接收数据
在userPage类中,直接获取传递过来的联系人对象即可:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_page); listObject selectedUser = (listObject) getIntent().getSerializableExtra("selectedUser"); // 然后使用selectedUser中的name、phone、mail等数据展示即可 }
额外优化建议
- 可以考虑使用Android原生的
Filter接口来实现列表过滤,而不是每次创建新的Adapter,这样性能更好,代码也更规范。 - 避免在
onCreate中盲目捕获NullPointerException和通用Exception,这会掩盖潜在的错误,不利于调试。
内容的提问来源于stack exchange,提问作者M.fouad
相关产品推荐
相关产品推荐

