0

私は数人で活動していTimerViewます。TimerView は、ユーザーがクリックしてカウントダウンを開始できる textview から拡張されたカスタム ビューです。

各 TimerView は Timer を所有します。現在の問題は、画面の向きを変更すると TimerViews がリセットされることです (現在のテキストは削除されます ("" に変更されます) が、bakground へのランタイムの変更は保持されます) が、ハンドラー スレッドは引き続き実行され、更新されます。もう存在しない (?) TimerViews。

向きが変わる直前に送信されたメッセージはまだアクティブです。これらのメッセージを送信するスレッド (?) はいつ終了しますか?

これを解決する正しい方法は何ですか。タイマーから新しいアクティビティの TimerView への参照を更新するか、タイマーを削除して新しいタイマーを作成しますか? または、他のより正しい解決策はありますか?すべての建設的な批判を歓迎します!

関連すると思われるコードの部分を投稿しています。

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