连续countdowntimer与处理程序不会更新的TextView正确 [英] sequential countdowntimer with handler wont update textView correctly

查看:202
本文介绍了连续countdowntimer与处理程序不会更新的TextView正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图建立某种顺序倒计时。意思是,我建立的演习,每一个包含一个特定的时间,这是倒计时时间的队列。在自定义倒计时类,我弹出这些演习从队列和使用的持续时间进行倒计时。
我希望这些倒数运行此起彼伏。为此,我建立了一个倒计时类,基于抽象类 CountDownTimer 的code的基础上。

I was trying to build some sort of sequential countdown. Meaning, that I build up a queue of "exercises", each one containing a specific duration, which is the countdown time. In a custom Countdown class, I pop these exercises off the queue and use the duration as countdown. I want these countdowns to run one after another. For this I built a Countdown class, based on the code basis of the abstract class CountDownTimer.

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Locale;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.widget.Button;
import android.widget.TextView;

    public class ExerciseMeCountDownTimer {

    private static final int MSG_COUNTDOWN = 100;
    private static final int MSG_FINISH = 99;
    private ArrayDeque<Exercise> eq;
    private long mMillisInFuture;
    private int mCountdownInterval;
    private String name;
    private long mStopTimeInFuture;
    CountdownHandler cHandler;

    public ExerciseMeCountDownTimer(ArrayList<Exercise> elist,
            Button startStopButton, TextView countdownText,
            CountdownHandler cHandler) {

        this.cHandler = cHandler;
        eq = new ArrayDeque<Exercise>(elist);
        this.start();
    }

    public final void cancel() {
        mHandler.removeMessages(MSG);
    }

    private synchronized final ExerciseMeCountDownTimer start() {
        if (!eq.isEmpty()) {
            Exercise e = eq.pop();
            this.mMillisInFuture = Long.parseLong(e.getDuration());
            this.mCountdownInterval = 30;
            this.name = e.getName();
        } else {
            onFinish();
            return this;
        }

        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }

    public void onTick(long millisUntilFinished) {
        Message msg = cHandler.obtainMessage(MSG_COUNTDOWN);
        Bundle data = new Bundle();
        String text = String.format(Locale.GERMANY, "%02d:%02d:%03d",
                millisUntilFinished / 100000, millisUntilFinished / 1000,
                millisUntilFinished % 1000);
        data.putString("countdown", text);
        msg.setData(data);
        cHandler.sendMessage(msg);

    }

    public void onFinish() {
        if (!eq.isEmpty()) {
            this.start();
        }

        Message msg = cHandler.obtainMessage(MSG_FINISH);
        Bundle data = new Bundle();
        String text = String.format(Locale.GERMANY, "00:00:000");
        data.putString("finish", text);
        msg.setData(data);
        cHandler.sendMessage(msg);
    }

    private static final int MSG = 1;

    // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            final long millisLeft = mStopTimeInFuture
                    - SystemClock.elapsedRealtime();

            if (millisLeft <= 0) {
                onFinish();
            } else if (millisLeft < mCountdownInterval) {
                // no tick, just delay until done
                sendMessageDelayed(obtainMessage(MSG), millisLeft);
            } else {
                long lastTickStart = SystemClock.elapsedRealtime();
                onTick(millisLeft);

                // take into account user's onTick taking time to
                // execute
                long delay = lastTickStart + mCountdownInterval
                        - SystemClock.elapsedRealtime();

                // special case: user's onTick took more than interval
                // to
                // complete, skip to next interval
                while (delay < 0)
                    delay += mCountdownInterval;

                sendMessageDelayed(obtainMessage(MSG), delay);
            }
        }

    };

    @Override
    public String toString() {
        return this.name;
    }
}

最重要的部分是的sendMessage 部分,在这里我向留在倒计时一处理时间的我的 MainActivity ,然后,应更新一个TextView。

The important part is the sendMessage part, where I send the time left on the countdown to a handler of my MainActivity, which then, should update a textview.

import android.os.Handler;
import android.os.Message;

class CountdownHandler extends Handler {
private static final int MSG_COUNTDOWN = 100;
private static final int MSG_FINISH = 99;
private MainActivity mActivity;

CountdownHandler(MainActivity activity) {
    this.mActivity = activity;
}

@Override
public void handleMessage(Message msg) {
    if (msg.what == MSG_COUNTDOWN) {
        String text = msg.getData().getString("countdown");
        this.mActivity.sayLog(text);
    }
    if (msg.what == MSG_FINISH) {
        String text = msg.getData().getString("finish");
        this.mActivity.sayLog(text);
    }

}

最后更新的TextView MainActivty

public void sayLog(String text) {
    countdown.setText(text);
}

ExerciseMeCountDownTimer由

ExerciseMeCountDownTimer is called by

new ExerciseMeCountDownTimer(elist, cHandler); 

这是一些的onClick()。

on some onClick().

的问题是,有时(实际上大部分时间)不更新TextView的正常。它停止更新的随机时间像00:05:211等。
会有人能告诉我这是为什么持续发生?也许还加入了解决方案,或者至少一些文献(也许指出了部分路段),我应该阅读理解问题?我也为UPEN替代方法,因为我是新来这个处理程序在Android中,线程的事情。

The problem is, that sometimes (actually most of the time) the textView is not updated properly. It stops updating on random times like 00:05:211 etc. Would anyone mind telling me why this is keeps happening? Maybe also adding a solution or at least some literature (maybe pointing out some sections) which I should read to understand the problem? I am also upen for alternative approaches, as I am new to this "handler", "threads" thing in android.

修改


  • TextView的正在更新,但是TextView的是点击。每当我点击了它的TextView停止更新!

  • 作为公认的答案显示,我决定使用更新 onTick()方法内适当的TextView的DIREKT方法。

  • the textview was updating, but the textview was clickable. Whenever I clicked on the textview it stopped updating!
  • as the accepted answer shows, I decided to use the direkt approach of updating the appropriate textview inside the onTick() method.

推荐答案

使用处理程序,事情在这种情况下是使它过于复杂。

Using Handler and things in this situation is making it overly complicated.

CountDownTimer 取值 onTick() onFinish() UI线程都运行所以更新 TextViews 查看期从任何一种方法可以很容易地只是路过查看的参考类的构造函数中完成,因为你已经在做。然后,你只需在需要的方法更新它。

CountDownTimers onTick() and onFinish() both run on the UI Thread so updating TextViews and other Views from either method can be done easily just by passing a reference of the View to the constructor of the class, as you are already doing. Then you simply update it in the method needed.

// could create a member variable for the TextView with your other member variables
...
mTV;

然后在构造函数中给它分配
    //删除了对处理器 - 你已经提到这里的TextView
    公共ExerciseMeCountDownTimer(ArrayList的ELIST,
            按钮startStopButton,TextView的countdownText){
         MTV = countdownText;

then in your constructor assign it // removed reference to Handler--you already have reference to TextView here public ExerciseMeCountDownTimer(ArrayList elist, Button startStopButton, TextView countdownText) { mTV = countdownText;

然后更新任何需要的方式

then update in whichever method is needed

public void onTick(long millisUntilFinished) {

    String text = String.format(Locale.GERMANY, "%02d:%02d:%03d",
            millisUntilFinished / 100000, millisUntilFinished / 1000,
            millisUntilFinished % 1000);
    mTV.setText(text);  // set the text here


}

public void onFinish() {
    if (!eq.isEmpty()) {
        this.start();
    }

这篇关于连续countdowntimer与处理程序不会更新的TextView正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆