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

Android ListView加载初期滚动跳回顶部故障问题求助

解决ListView加载初期滚动跳回顶部的问题

嘿,我来帮你排查这个ListView滚动跳回顶部的问题!看了你的代码,几个关键问题导致了加载后前3秒的滚动异常,咱们一步步来修复:

核心问题分析

  • ConvertView完全没复用:你在getView里每次都重新inflate布局,这会让ListView滚动时疯狂创建新View,加上图片异步加载的开销,前3秒UI线程严重卡顿,直接导致滚动跳回顶部。
  • ProgressBar频繁触发UI重绘:每一行的getView都把进度条设为不可见,这会导致多次不必要的UI刷新,干扰滚动的流畅性。
  • 选中状态更新时全量刷新列表:点击列表项时调用notifyDataSetChanged(),会让整个ListView重新绘制,在加载初期雪上加霜。
  • 图片加载无占位处理:Picasso加载图片时没有占位图,布局会因为图片加载完成而跳动,进一步影响滚动稳定性。

具体修复方案

1. 实现ViewHolder模式复用ConvertView

这是ListView优化的基础,能大幅减少View创建次数,提升性能:

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    ViewHolder holder;
    // 只有当convertView为空时才初始化布局
    if (convertView == null) {
        convertView = inflater.inflate(resource, parent, false);
        holder = new ViewHolder();
        holder.countryName = convertView.findViewById(R.id.countryNamelbl);
        holder.countryFlag = convertView.findViewById(R.id.countryFlagimg);
        holder.checked = convertView.findViewById(R.id.countryCheckedimg);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    final CountryModel countryModel = countryModels.get(position);
    assert countryModel != null;
    holder.countryName.setText(countryModel.getName());
    
    // 优化Picasso加载,添加占位图
    Picasso.get()
            .load(countryModel.getImage())
            .placeholder(R.drawable.flag_placeholder) // 替换成你的占位图资源
            .fit()
            .into(holder.countryFlag);

    // 更新选中状态
    if(!useFilter) {
        holder.checked.setVisibility(selectedCountryId == countryModel.getId() ? View.VISIBLE : View.INVISIBLE);
    }

    // 点击事件逻辑
    convertView.setOnClickListener(v -> {
        if(!useFilter) {
            if (holder.checked.getVisibility() == View.VISIBLE) {
                holder.checked.setVisibility(View.INVISIBLE);
                selectedCountryId = -1;
            } else {
                // 先隐藏之前选中项的选中状态
                if (selectedCountryId != -1) {
                    int prevPosition = getPositionById(selectedCountryId);
                    if (prevPosition != -1) {
                        View prevView = parent.getChildAt(prevPosition - parent.getFirstVisiblePosition());
                        if (prevView != null) {
                            ViewHolder prevHolder = (ViewHolder) prevView.getTag();
                            prevHolder.checked.setVisibility(View.INVISIBLE);
                        }
                    }
                }
                holder.checked.setVisibility(View.VISIBLE);
                selectedCountryId = countryModel.getId();
            }
            selectedCountryIdtxt.get().setText(String.valueOf(selectedCountryId));
        } else {
            Intent i = new Intent(getContext(), PicturesActivity.class);
            i.putExtra("countryId",countryModel.getId());
            i.putExtra("countryName", countryModel.getName());
            getContext().startActivity(i);
        }
    });

    return convertView;
}

// ViewHolder内部类
private static class ViewHolder {
    TextView countryName;
    ImageView countryFlag;
    ImageView checked;
}

// 辅助方法:通过id获取列表位置
private int getPositionById(int countryId) {
    for (int i = 0; i < countryModels.size(); i++) {
        if (countryModels.get(i).getId() == countryId) {
            return i;
        }
    }
    return -1;
}

2. 调整ProgressBar的显示逻辑

不要在getView里每一行都设置进度条,应该在数据源加载完成后统一设置一次,比如在你初始化适配器或者更新数据源的地方:

// 比如在数据加载完成后调用
progressBarWeakReference.get().setVisibility(View.INVISIBLE);

3. 移除不必要的全量刷新

之前点击时调用notifyDataSetChanged()会刷新整个列表,现在通过直接更新前后选中项的View来替代,避免全量刷新带来的性能开销。

额外优化建议

  • 确保你的CountryModel的hashCode()实现稳定,避免getItemId()返回值频繁变化。
  • 如果列表数据量很大,考虑使用RecyclerView替代ListView,它的性能优化更完善。
  • 可以给Picasso设置内存缓存和磁盘缓存的大小,提升图片加载速度:
Picasso picasso = new Picasso.Builder(getContext())
        .memoryCache(new LruCache(24 * 1024 * 1024)) // 24MB内存缓存
        .build();
Picasso.setSingletonInstance(picasso);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:18:28