通过活动重启(方向更改)保留计时器

时间:2013-08-06 14:51:39

标签: android

我有几个TimerView的活动。 TimerView是从textview扩展的自定义视图,用户可以单击该视图开始倒计时。

每个TimerView都拥有一个Timer。现在的问题是,当我更改屏幕的方向时,TimerViews会被重置(当前文本被删除(更改为“”)但运行时更改为bakground),但Handler线程仍在运行,更新TimerViews不再存在(?)。

在方向更改之前发送的消息仍处于活动状态。发送这些消息的线程(?)何时终止?

解决这个问题的正确方法是什么。更新从定时器到新活动的TimerViews的引用,或删除定时器并创建新的定时器?或其他一些更正确的解决方案?所有建设性的批评都表示赞赏!

我发布了我认为相关的代码部分:

TimerView扩展TextView

public class TimerView extends TextView implements View.OnClickListener
{
    private SecondTimer secondTimer;

    public TimerView(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        secondTimer = new SecondTimer(120, this);
        setOnClickListener(this);
    }

    @Override
    public void onClick(View view)
    {
        if(!secondTimer.isRunning())
            secondTimer.start();
    }
}

SecondTimer

//来自Sam的计时器android CountDownTimer - additional milliseconds delay between ticks

public abstract class SecondTimer 
{
    private final long millisInFuture;
    private final long countdownInterval;
    private long stopTimeInFuture;
    private long nextTime;
    private boolean running;

    // Reference to TimerView that this timer should update
    TimerView timerView;

    // Constructor
    public SecondTimer(long secondsInFuture, TimerView timerView)
    {        
        this.millisInFuture = secondsInFuture * 1000;
        this.countdownInterval = 1000;
        this.timerView = timerView;
    }


    private static final int MSG = 1;
    public synchronized SecondTimer start() //Synch needed?
    {
        running = true;

        if(millisInFuture <= 0)
        {
            onFinish();
            return this;
        }

        nextTime = SystemClock.uptimeMillis();
        stopTimeInFuture = nextTime + millisInFuture;

        // Message for start tick
        handler.sendMessage(handler.obtainMessage(MSG));
        return this;
    }

    // Takes care of counting down
    private Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            synchronized(SecondTimer.this)
            {
                final long millisLeft = stopTimeInFuture - SystemClock.uptimeMillis();

                if(millisLeft <= 0)
                {
                    onFinish();
                }
                else
                {
                    onTick(millisLeft);

                    long currentTime = SystemClock.uptimeMillis();
                    do
                    {
                        nextTime += countdownInterval;
                    } while(currentTime > nextTime);

                    // Make sure this interval doesn't exceed the stop time
                    if(nextTime < stopTimeInFuture)
                        sendMessageAtTime(obtainMessage(MSG), nextTime);
                    else
                        sendMessageAtTime(obtainMessage(MSG), stopTimeInFuture);
                }
            }
        }
    };

    private void onTick(long millisUntilFinished)
    {
        long secondsUntilFinished = (millisUntilFinished + 500) / 1000;
        long minutesUntilFinished = secondsUntilFinished / 60;
        secondsUntilFinished %= 60;

        timerView.setText(String.format("%01d", minutesUntilFinished)
                + ":"
                + String.format("%02d", secondsUntilFinished));
    }

    private void onFinish()
    {
        running = false;
    }

    public boolean isRunning()
    {
        return running;
    }
}

1 个答案:

答案 0 :(得分:0)

一种方法是将您的计时器移动到setRetainInstance(true)片段。这样的片段在方向改变时不会被破坏。 (顺便说一下,最好不要更新保留片段中的UI。)