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

Flutter中如何统计PageView各页面的停留时长?

高效实现页面停留时长统计方案

需求说明

通过PageView.builder展示名言列表时,需要:

  • 精准统计用户在每个页面的停留时长
  • 再次访问已浏览页面时,重新计时并将时长累加至对应DataModel的timeSpent字段

实现思路

核心逻辑放在父组件HomePage中统一管理,避免每个子页面单独维护计时状态,提升性能和可维护性:

  • 使用Stopwatch跟踪当前页面停留时间,比手动记录时间戳更简洁可靠
  • 通过PageView的onPageChanged回调触发页面切换时的时长计算与累加
  • 在组件销毁前,确保最后一个页面的停留时长被正确保存

修改后的完整代码

homepage.dart

import 'package:flutter/material.dart';
import 'package:rdx_test/data_model.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late List<DataModel> data;
  int currentPageIndex = 0;
  final Stopwatch _stopwatch = Stopwatch();

  @override
  void initState() {
    super.initState();
    data = [
      DataModel("We are what our thoughts have made us; so take care about what you think. Words are secondary. Thoughts live; they travel far. ~ Swami Vivekananda", 0),
      DataModel("First they ignore you, then they laugh at you, then they fight you, then you win. ~ Mahatma Gandhi", 0),
      DataModel("I slept and dreamt that life was joy. I awoke and saw that life was service. I acted and behold, service was joy. ~ Rabindranath Tagore", 0),
      DataModel("It is no measure of health to be well adjusted to a profoundly sick society. ~ Jiddu Krishnamurti", 0),
      DataModel("When the flower blooms, the bees come uninvited. ~ Ramakrishna", 0),
    ];
    // 启动初始页面计时
    _stopwatch.start();
  }

  @override
  void dispose() {
    // 页面销毁时,保存最后一个页面的停留时长
    _updateTimeSpent(currentPageIndex);
    _stopwatch.stop();
    super.dispose();
  }

  void _onPageChanged(int newIndex) {
    // 计算并保存上一个页面的停留时长
    _updateTimeSpent(currentPageIndex);
    // 更新当前页面索引
    setState(() {
      currentPageIndex = newIndex;
    });
    // 重置并启动新页面的计时
    _stopwatch.reset();
    _stopwatch.start();
  }

  void _updateTimeSpent(int index) {
    if (_stopwatch.isRunning) {
      // 将毫秒数转换为秒(可根据需求调整单位)
      final int elapsedSeconds = _stopwatch.elapsed.inSeconds;
      setState(() {
        data[index].timeSpent += elapsedSeconds;
      });
      print("页面 $index 累计停留时长:${data[index].timeSpent} 秒");
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: PageView.builder(
          itemCount: data.length,
          onPageChanged: _onPageChanged,
          itemBuilder: (context, index) {
            return SinglePage(
              data: data[index].data,
              // 可选:显示当前页面累计时长
              timeSpent: data[index].timeSpent,
            );
          },
        ),
      ),
    );
  }
}

class SinglePage extends StatelessWidget {
  final String data;
  final int? timeSpent;

  const SinglePage({
    Key? key,
    required this.data,
    this.timeSpent,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(data, textAlign: TextAlign.center, style: const TextStyle(fontSize: 18)),
            if (timeSpent != null)
              Padding(
                padding: const EdgeInsets.only(top: 20),
                child: Text("累计停留:$timeSpent 秒", style: const TextStyle(color: Colors.grey)),
              ),
          ],
        ),
      ),
    );
  }
}

data_model.dart

class DataModel {
  final String data;
  int timeSpent;

  DataModel(this.data, this.timeSpent);
}

关键细节说明

  • 使用Stopwatch替代手动记录时间戳,简化计时逻辑,减少出错概率
  • 所有计时和数据更新逻辑集中在HomePage状态中,子页面改为StatelessWidget,降低组件复杂度
  • 在dispose方法中处理最后一次计时,避免页面销毁时丢失未保存的时长数据
  • 可根据需求调整计时单位(比如保留毫秒数),只需修改_updateTimeSpent中的转换逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:25:43