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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:57:47