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

为何在MainActivity调用TSDataAdapter的getAllList返回空ArrayList

问题根源

  • getView() 仅在列表项进入可视区域时才会触发,你提前在MainActivity调用getAllList()时,大部分列表项还没执行过getView()逻辑,自然返回空列表。
  • 就算列表完全渲染完,getView()会在列表滚动时反复触发(列表项复用机制),你每次调用都执行allList.add(),最终会得到大量重复的无效数据,不符合预期。
  • 你直接在TSData中持有Chronometer控件引用是错误做法:列表项复用会导致旧的控件引用指向其他列表项,后续操作计时器会出现串项bug。

修复方案

  1. 用ViewHolder模式优化列表性能,避免每次getView()都重复查找控件
  2. 用SparseArray存储每个位置对应的计时器实例,避免重复添加、数据重复的问题
  3. 提前初始化数据源,不要在getView()里填充主数据列表

修改后的参考代码:

public class TSDataAdapter extends ArrayAdapter<TSData>
{
    private ArrayList<TSData> allList;
    // 存储每个position对应的计时器实例
    private SparseArray<Timer> positionTimerMap = new SparseArray<>();

    public TSDataAdapter(Context context, int resource, ArrayList<TSData> tsdList)
    {
        super(context, resource, tsdList);
        // 直接复用传入的数据源,不需要新建空列表
        allList = new ArrayList<>(tsdList);
    }

    static class ViewHolder {
        TextView subTitleTextView;
        TextView countTextView;
        Chronometer chr;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder holder;
        if(convertView == null)
        {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_element, parent, false);
            holder = new ViewHolder();
            holder.subTitleTextView = convertView.findViewById(R.id.titleTextView);
            holder.countTextView = convertView.findViewById(R.id.countTextView);
            holder.chr = convertView.findViewById(R.id.chronometer);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        TSData currentData = getItem(position);
        String subTitle = currentData.getSubTitle();
        int count = currentData.getCount();
        
        // 仅当该位置没有存储计时器时才新建,避免重复创建
        if (positionTimerMap.get(position) == null) {
            Timer timer = new Timer(holder.chr);
            positionTimerMap.put(position, timer);
            // 如果你需要把计时器存到TSData里,直接更新当前data对象即可,不用新建add
            currentData.setTimer(timer);
        }

        holder.subTitleTextView.setText(subTitle);
        holder.countTextView.setText(Integer.toString(count));

        return convertView;
    }

    public ArrayList<TSData> getAllList()
    {
        return allList;
    }
    
    // 也可以单独提供获取计时器的方法
    public Timer getTimerByPosition(int position) {
        return positionTimerMap.get(position);
    }
}

如果你需要在列表还没滚动到对应项时就拿到计时器,不要依赖getView的触发逻辑,建议把计时器的初始化逻辑提前放到数据源构造的阶段,不要和View的渲染逻辑绑定。

内容的提问来源于stack exchange,提问作者SmokeyRon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 05:06:04