Listview中的CountDown Timer

时间:2014-01-04 14:55:26

标签: android listview countdowntimer

我正在开发一个Android应用程序,在一个屏幕上我有Listview每行都有倒数计时器。我正在使用列表适配器。我试过谷歌和其他参考,但没有得到实际的输出。我从web服务返回秒数,我将秒转换为hh:mm:ss格式并使用CountdownTimer类启动倒数计时器。但是当我滚动Listview时它会改变行为,我知道这是android Listview的常见问题,但我想在每一行显示倒数计时器,并且每秒都有完整的移动时间。

请帮助我的朋友,提前致谢。

2 个答案:

答案 0 :(得分:0)

您可以创建一个将在每一行中处理计时器的类。我的意思是一个可重复使用的课程。你已经创建了一个类来使你的计时器然后利用它。在那个类中,你应该能够监视你的listview项目,以便计时器将继续运行。你可以引用该listitem的id。

希望它能给你一些提示

答案 1 :(得分:0)

来自this thread的meh给出了一个很好的建议。

在CountDownTimer中,不要直接更新listview-item中的textviews,而是从适配器更新数据对象中的一些String。 然后让另一个单独的CountDownTimer调用adapter.notifyDataSetChanged()让listitem-views自行更新。我在代码中称这个为adapterNotifier。

如果每个其他单个CountDownTimer本身都调用adatper.notifyDataSetChanged(),那么adapterNotifier应该单独调用adapter.notifyDataSetChanged()以避免额外的开销。

在来自适配器的getView()方法中,不要做任何花哨的事情,只能从数据对象中读取预先计算的字符串并照常更新文本视图。

这种方法的主要缺点是,您更新了整个每个列表项,如果您有例如列表项目中的网络加载图像。我会尝试进一步优化这一点。

这是一些代码

public Adapter(Context context, ListData dataList) {
    super(context, dataList);
    this.dataList = dataList;
    initTimerData(dataList);
}

private void initTimerData(ListData dataList) {
    long longestTimerInterval = 0;
    for (final Data data : dataList) {
        if (data.show_timer) {
            if (data.end_time == null) {
                data.show_timer = false;
                continue;
            }
            long endTimeMillis = 0;
            try {
                endTimeMillis = dataDateTimeProcessor.parse(data.end_time).getTime();
            } catch (ParseException e) {
                Log.e(DataDetailFragment.class.getSimpleName(), "Error parsing data-time: ", e);
            }

            // TODO use the server-time for reliability
            long nowTime = System.currentTimeMillis();
            long timeInterval = endTimeMillis - nowTime;

            // if the data is over or more than 24 hours away, don't display the timer
            if (nowTime >= endTimeMillis ||
                timeInterval > 24 * 3600 * 1000) {
                data.show_timer = false;
                continue;
            }

            // save the longest interval for an extra adapter-notifier timer
            if (timeInterval > longestTimerInterval)
                longestTimerInterval = timeInterval;

            // this listener holds the references to the currently visible data-timerviews
            DataCountDownTimerListener timerListener = new DataCountDownTimerListener() {
                @Override
                public void onTick(long millisUntilFinished) {
                    int seconds = (int) ((millisUntilFinished / 1000) % 60);
                    int minutes = (int) ((millisUntilFinished / (60000)) % 60);
                    int hours   = (int) ((millisUntilFinished / (3600000)) % 24);
                    data.timerSeconds = String.format("%02d", seconds);
                    data.timerMinutes = String.format("%02d", minutes);
                    data.timerHours = String.format("%02d", hours);
                }
                @Override
                public void onFinish() {
                    data.timerSeconds = "00";
                    data.timerMinutes = "00";
                    data.timerHours = "00";
                }
            };

            if (data.endTimer != null) {
                Utils.stopDataTimer(data);
            }

            data.endTimer = new DataCountDownTimer(timeInterval, 1000);
            data.endTimer.setDataCountDownTimerListener(timerListener);
            data.endTimer.start();
        } else {
            data.show_timer = false;
        }
    }

    initAdapterNotifier(longestTimerInterval);
}

private void initAdapterNotifier(long longestTimerInterval) {
    // no timers here, go away
    if (longestTimerInterval == 0)
        return;

    adapterNotifier = new DataCountDownTimer(longestTimerInterval, 1000);
    DataCountDownTimerListener adapterNotifierListener = new DataCountDownTimerListener() {
        @Override
        public void onTick(long millisUntilFinished) {
            // TODO evaluate performance
            // update the adapter-dataset for timer-refreshes
            notifyDataSetChanged();
        }

        @Override
        public void onFinish() {
            // last timer finished, nothing to do here
        }
    };
    adapterNotifier.setDataCountDownTimerListener(adapterNotifierListener );
    adapterNotifier.start();
}

public void stopDataTimers() {
    if (adapterNotifier != null)
        adapterNotifier.cancel();
    for (Data data : dataList) {
        if (data.endTimer != null) {
            Utils.stopDataTimer(data);
        }
    }
}