为啥 ArrayList 在仅适配器中总是相同的值?

Posted

技术标签:

【中文标题】为啥 ArrayList 在仅适配器中总是相同的值?【英文标题】:Why ArrayList is always same value in only Adapter?为什么 ArrayList 在仅适配器中总是相同的值? 【发布时间】:2021-11-13 09:32:51 【问题描述】:

这是我见过的最糟糕的错误。我按照以下方式获取呼叫日志。

ArrayList<HashMap<String, String>> callLog= new ArrayList<>();
        HashMap<String, String> data = new HashMap<>();
        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())
            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;

我试图将其设置为适配器。这是我如何将它们链接到适配器的方式

ContactViewAdapter contactViewAdapter = new ContactViewAdapter(getActivity(),getActivity(),CallLog(getActivity()),"contact");
        recyclerViewCallLog.setAdapter(contactViewAdapter);

由于适配器类有点大,因此我没有添加所有上下文。我只是在这里添加构造函数。

public class ContactViewAdapter extends RecyclerView.Adapter<ContactViewAdapter.MyViewHolder> 

Context context;
    ArrayList<HashMap<String, String>> list;
    String type;
    Activity activity;

    public ContactViewAdapter(Activity activity,Context context, ArrayList<HashMap<String,String>> list,String type)
        this.activity = activity;
        this.context = context;
        this.list = list;
        this.type = type;
    

这对于 android 应用开发者来说是可以理解的。下面列出了该错误:

我实际上是在使用多个RecyclerView 使用Adapter。它们的布局非常相似,这就是为什么我选择使用可以减少源代码数量的单个适配器的原因。它对联系人工作正常。但该错误在 CallLog 中可用。 该方法可以返回所有通话记录。在 DialerFragment (我正在调用该方法)中,我也可以看到所有 CallLog。当列表到达 Adapter 时,只会返回单个 CallLog。

我正在从 Logcat 列表中删除 phoneNumber。

[date=123123, name=null, phoneNumber=+4365643, duration=45, type=1, date=43743, name=null, phoneNumber=+4543, duration=45, type=1, date=23452, name=null, phoneNumber=+3245432, duration=45, type=1, date=234523, name=null, phoneNumber=+3245432, duration=45, type=1, date=1617550988892 , name=null, phoneNumber=+2345, duration=45, type=1, date=1617550923452388892, name=null, phoneNumber=+88018115723457032, duration=45, type=1, date=16175502345988892, name=null , phoneNumber=+88018234511577032, duration=45, type=1, date=16175509888234592, name=null, phoneNumber=+88018112345577032, duration=45, type=1, date=16172345550988892, name=null, phoneNumber=+ 88018112345577032,持续时间=45,类型=1,日期=16175234550988892,名称=null,电话号码=+88018234511571237032,持续时间=45,类型=1

logcat 来自方法。我也得到相同的登录片段(活动)页面。适配器中的 Logcat。

2021-09-19 14:00:07.995 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.012 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.026 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.040 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.054 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.068 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.082 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.098 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.112 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.126 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.140 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1
2021-09-19 14:00:08.154 20558-20558/com.contact D/LOGCAT: date=1617550988892, name=null, phoneNumber=+88018115747032, duration=45, type=1

不关心 DATE。它们的格式正确。它们以毫秒为单位。也不在乎数字。我在这些数字中添加了一个数字(字符)。这是我如何称呼它的。

@Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) 
        String phoneNumber = list.get(position).get(Constants.PHONE_NUMBER);
        String name = list.get(position).get(Constants.NAME);
        Bitmap imgBitmap = null;
        String photo = null;

        Log.d("LOGCAT", String.valueOf(list.get(position)));

但为什么它们每次都返回相同的值?

【问题讨论】:

每个列表索引都指向同一个HashMap,您只需在循环的每次迭代中覆盖键的值,丢失任何先前设置的值。将data HashMap 的实例化移动到循环内部,它应该可以解决问题。 【参考方案1】:

代替:

ArrayList<HashMap<String, String>> callLog= new ArrayList<>();
    HashMap<String, String> data = new HashMap<>();
    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())
        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;

试试:

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())
        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));

        HashMap<String, String> data = new HashMap<>();
        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发生在while循环中以获得正确的代码

以上是关于为啥 ArrayList 在仅适配器中总是相同的值?的主要内容,如果未能解决你的问题,请参考以下文章

Java ArrayList Contain 总是返回 false,尽管它包含相同的值

当返回指向本地数组的指针时,为啥它总是相同的值?

为啥循环遍历 ArrayList<String> 与常规数组相同? [复制]

为啥这个方法返回一个包含所有相同对象的 ArrayList? JAVA

为啥将刷新令牌存储在仅 HTTP 的 Cookie 中以防止 CSRF 攻击?

为啥在函数中登录时 textarea 的值总是空的? [复制]