如何优化 Android 中 ViewPager2 的长日期范围加载性能

心靈之曲

心靈之曲

2026-07-14

328人浏览

原创

如何优化 Android 中 ViewPager2 的长日期范围加载性能

本文介绍如何解决因预生成 10 年日期列表导致 activity 启动延迟 5–6 秒的问题,核心方案是避免主线程阻塞、取消冗余预计算,并采用按需计算日期的懒加载适配器设计。

本文介绍如何解决因预生成 10 年日期列表导致 activity 启动延迟 5–6 秒的问题,核心方案是避免主线程阻塞、取消冗余预计算,并采用按需计算日期的懒加载适配器设计。

在 MainActivity 中,当前逻辑在 onCreate() 内同步调用 getList(start, end) —— 该方法遍历约 3650 天(10 年),对每一天执行 Calendar 操作 + SimpleDateFormat 解析与格式化,全部运行在主线程。这不仅造成严重卡顿,还极易触发 ANR(Application Not Responding)。更关键的是:ViewPager2 并不需要一次性持有全部日期字符串——它只渲染当前页及相邻缓存页(默认 1 页前后),其余项完全可“按需生成”。

✅ 正确做法:彻底移除预生成列表,改用数学驱动的懒加载适配器

1. 将日期范围抽象为「起始日 + 总天数」

无需 ArrayList,仅需两个字段:

Android开发教程与笔记pdf版
Android开发教程与笔记pdf版

Android文件存取与数据库编程知识,文件操作主要是读文件、写文件、读取静态文件等,同时还介绍了创建添加文件内容并保存,打开文件并显示内容;数据库编程方面主要介绍了SQLite数据库的使用、包括创建、删除、打开数据库、非查询SQL操作指令、查询SQL指令-游标Cursors等知识。

下载
private final Calendar startDate = Calendar.getInstance();
private final int totalDays; // = 3650(或动态计算)

// 初始化时设置:5年前 → 5年后 = 10年 = ~3650天
startDate.add(Calendar.YEAR, -5);
totalDays = 3650;

2. 改写适配器:不依赖数据源数组,而是按索引实时计算日期

public class LazyDateAdapter extends RecyclerView.Adapter<lazydateadapter.viewholder> {
    private final Calendar baseDate; // 起始日期(如 2019-01-01)
    private final int totalItems;

    public LazyDateAdapter(Calendar start, int days) {
        this.baseDate = (Calendar) start.clone();
        this.totalItems = days;
    }

    @Override
    public int getItemCount() {
        return totalItems;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_date, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // ✅ 关键:仅在绑定时计算当前 position 对应的日期字符串
        Calendar target = (Calendar) baseDate.clone();
        target.add(Calendar.DAY_OF_YEAR, position); // O(1) 运算

        String formatted = formatDate(target);
        holder.textView.setText(formatted);
    }

    private String formatDate(Calendar cal) {
        // 推荐使用 ThreadLocal 或 AndroidX Core 的 SimpleDateFormat(线程安全)
        return String.format(Locale.getDefault(), "%d/%s/%d",
                cal.get(Calendar.DAY_OF_MONTH),
                getMonthAbbr(cal.get(Calendar.MONTH)),
                cal.get(Calendar.YEAR));
    }

    private String getMonthAbbr(int month) {
        String[] abbr = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
        return abbr[month];
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        ViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.date_text);
        }
    }
}</lazydateadapter.viewholder>

3. 在 Activity 中轻量初始化(毫秒级)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ViewPager2 viewPager = findViewById(R.id.view_pager);

    // ⚡ 极速初始化:无循环、无字符串生成
    Calendar start = Calendar.getInstance();
    start.add(Calendar.YEAR, -5);
    int totalDays = 3650; // 或用 endDate.getTime() - startDate.getTime() / 86400000 精确计算

    LazyDateAdapter adapter = new LazyDateAdapter(start, totalDays);
    viewPager.setAdapter(adapter);

    // 设置默认居中页:从 -5 年到 +5 年,中间即第 5 年(索引 = 5 * 365 ≈ 1825)
    int centerPosition = (int) (totalDays * 0.5f);
    viewPager.setCurrentItem(centerPosition, false);
}

⚠️ 注意事项与进阶建议

  • 禁止在 onBindViewHolder 中创建 SimpleDateFormat 实例:它非线程安全且开销大。优先使用 String.format() 或 java.time.format.DateTimeFormatter(API 26+);若需兼容低版本,可用 ThreadLocal 封装。
  • 避免 Calendar.clone() 频繁调用:虽比 new Calendar() 轻量,但仍有开销。可考虑用 long 时间戳代替 Calendar,通过 TimeUnit.DAYS.toMillis(position) 偏移计算毫秒值再格式化。
  • 添加加载状态(可选):若首次滑动稍有延迟(极罕见),可在 ViewPager2 外层包裹 ProgressBar,onPageSelected 触发后隐藏。
  • 内存优势:原方案占用约 3650 × 16B ≈ 58KB 字符串内存;新方案常驻内存

通过此重构,Activity 启动时间将从 5–6 秒降至 50ms 以内,同时显著降低内存占用与 GC 压力,真正实现高性能、可扩展的日期浏览体验。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

android

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

2023.08.14

759

4

android是什么系统
android是什么系统

Android是一种功能强大、灵活可定制、应用丰富、多任务处理能力强、兼容性好、网络连接能力强的操作系统。本专题为大家提供android相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.22

2058

5

android权限限制怎么解开
android权限限制怎么解开

android权限限制可以使用Root权限、第三方权限管理应用程序、ADB命令和Xposed框架解开。详细介绍:1、Root权限,通过获取Root权限,用户可以解锁所有权限,并对系统进行自定义和修改;2、第三方权限管理应用程序,用户可以轻松地控制和管理应用程序的权限;3、ADB命令,用户可以在设备上执行各种操作,包括解锁权限;4、Xposed框架,用户可以在不修改系统文件的情况下修改应用程序的行为和权限。

2023.09.19

3319

7

android重启应用的方法有哪些
android重启应用的方法有哪些

android重启应用有通过Intent、PendingIntent、系统服务、Runtime等方法。本专题为大家提供Android相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

382

5

Android语音播放功能实现方法
Android语音播放功能实现方法

实现方法有使用MediaPlayer实现、使用SoundPool实现两种。可以根据具体的需求选择适合的方法进行实现。想了解更多语音播放的相关内容,可以阅读本专题下面的文章。

2024.03.01

723

5

Maven零基础入门教程
Maven零基础入门教程

本合集由PHP中文网精心整理,提供Maven零基础入门到完整使用的保姆级教程。内容涵盖环境安装、核心配置、仓库管理及项目构建等核心知识点。通过详细步骤解析与代码示例,助你快速掌握Maven的依赖管理与自动化构建,轻松解决Java项目中的各种痛点,是新手入门与进阶的必备指南。

2026.08.05

2

18

Maven安装及配置教程
Maven安装及配置教程

本合集由PHP中文网精心整理,提供Maven安装配置与环境配置详情指南。内容涵盖Maven下载、解压安装、环境变量配置、阿里云镜像加速及本地仓库修改等全流程。教程通俗易懂,帮助开发者轻松解决依赖管理难题,快速掌握Maven核心构建技能,是Java开发者的必备实战指南。

2026.08.05

2

24

Selenium WebDriver元素定位与页面操作教程
Selenium WebDriver元素定位与页面操作教程

本专题整理Selenium WebDriver元素定位、XPath、CSS Selector、等待机制、窗口切换、Frame处理、Alert弹窗、Cookie操作和文件上传等核心用法。

2026.08.05

4

26

Selenium Grid分布式测试与并行执行教程
Selenium Grid分布式测试与并行执行教程

本专题整理Selenium Grid架构、远程WebDriver、并行测试、Docker部署、Kubernetes动态Grid、浏览器矩阵和测试环境扩展方法,适合进阶自动化测试团队使用。

2026.08.05

1

18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 39.5万人学习

Java 教程
Java 教程

共578课时 | 172万人学习

Uniapp从零开始实现新闻资讯应用
Uniapp从零开始实现新闻资讯应用

共64课时 | 8.6万人学习