0

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

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

在方向改变之前发送的消息仍然有效。发送这些消息的线程(?)何时终止?

解决这个问题的正确方法是什么。将 Timers 的引用更新到新活动的 TimerViews,或者删除 Timers 并创建新的?还是其他更正确的解决方案?感谢所有建设性的批评!

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

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();
    }
}

秒计时器

// 这里派生自 Sam 的计时器android CountDownTimer - 滴答之间的额外毫秒延迟

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;
    }
}
4

1 回答 1

0

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

于 2013-08-06T18:16:36.927 回答