Android开发:读取通话记录后ArrayList在Adapter中全部显示相同值的问题
问题分析与解决方案:Adapter重复显示单条通话记录
嘿,这个问题我之前也踩过坑!本质是对象引用复用导致的经典错误,咱们一步步拆解:
问题根源
你看获取通话记录的代码,HashMap<String, String> data = new HashMap<>();是在while循环外面创建的——这意味着整个循环过程中,你始终在修改同一个HashMap对象的内容,然后反复把这个对象的引用塞进callLog列表里。
打个比方:你有一个空盒子,每次循环往盒子里装不同的东西,然后把盒子的“地址”写在纸条上放进列表。最后列表里的所有纸条都指向同一个盒子,自然显示的都是最后一次装的东西。
原代码里的问题点:
// 只创建了1个HashMap,循环全程复用 HashMap<String, String> data = new HashMap<>(); while(c.moveToNext()){ data.put(...) // 每次都是修改同一个HashMap的内容 callLog.add(data); // 加的是同一个对象的引用 }
修复方案
只需要把HashMap的创建移到while循环内部,让每次循环都生成一个全新的HashMap对象就行:
修正后的获取通话记录代码:
ArrayList<HashMap<String, String>> callLog= new ArrayList<>(); Cursor c = activity.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC "); String phoneNumber,type,date,duration,name; while(c.moveToNext()){ // 关键:每次循环新建一个HashMap,避免复用同一个对象 HashMap<String, String> data = new HashMap<>(); phoneNumber = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER)); type = c.getString(c.getColumnIndex(CallLog.Calls.TYPE)); date = c.getString(c.getColumnIndex(CallLog.Calls.DATE)); duration = c.getString(c.getColumnIndex(CallLog.Calls.DURATION)); name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME)); data.put(Constants.PHONE_NUMBER, phoneNumber); data.put(Constants.NAME, name); data.put(Constants.DATE, date); data.put(Constants.TYPE, type); data.put(Constants.DURATION, duration); callLog.add(data); } c.close(); return callLog;
额外优化建议
虽然用HashMap能解决问题,但在Android开发中,更推荐**创建实体类(比如CallRecord)**来封装通话记录的字段,这样代码可读性更强,也能从根源上避免这类引用问题,后续扩展字段也更方便:
示例实体类:
public class CallRecord { private String phoneNumber; private String name; private String date; private String callType; private String duration; // 构造方法 public CallRecord(String phoneNumber, String name, String date, String callType, String duration) { this.phoneNumber = phoneNumber; this.name = name; this.date = date; this.callType = callType; this.duration = duration; } // Getter方法(按需生成) public String getPhoneNumber() { return phoneNumber; } // 其他Getter... }
之后把获取通话记录的逻辑改成创建CallRecord对象,Adapter也换成ArrayList<CallRecord>作为数据源,代码会更健壮易维护。
内容的提问来源于stack exchange,提问作者Unknown
相关产品推荐
相关产品推荐

