簡體   English   中英

Android 定時器更新 textview (UI)

[英]Android timer updating a textview (UI)

我正在使用計時器來創建秒表。 計時器通過增加 integer 值來工作。 然后我想通過不斷更新 textview 在活動中顯示這個值。

這是我嘗試更新活動的 textview 的服務中的代碼:

protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
        }
    }, 0, 1000);
}

我在錯誤的線程中更新 UI 時遇到了某種錯誤。

如何調整我的代碼以完成不斷更新 textview 的任務?

protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            mHandler.obtainMessage(1).sendToTarget();
        }
    }, 0, 1000);
}

public Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
    }
};

上面的代碼將工作...

注意:處理程序必須在您的主線程中創建,以便您可以修改 UI 內容。

您應該使用Handler每 X 秒更新一次 UI。 這是另一個顯示示例的問題: 重復一個有時間延遲的任務?

您的方法不起作用,因為您正在嘗試從非 UI 線程更新 UI。 這是不允許的。

StopWatch.time.post(new Runnable() {
    StopWatch.time.setText(formatIntoHHMMSS(elapsedTime));
});

此代碼塊基於 Handler,但您不需要創建自己的 Handler 實例。

您可以使用以下實用程序:

/**
 * Created by Ofek on 19/08/2015.
 */
public class TaskScheduler extends Handler {
    private ArrayMap<Runnable,Runnable> tasks = new ArrayMap<>();
    public void scheduleAtFixedRate(final Runnable task,long delay,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        postDelayed(runnable, delay);
    }
    public void scheduleAtFixedRate(final Runnable task,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        runnable.run();
    }
    public void stop(Runnable task) {
        Runnable removed = tasks.remove(task);
        if (removed!=null) removeCallbacks(removed);
    }

}

然后在由 UI 線程運行的代碼中的任何地方,您都可以像這樣簡單地使用它:

TaskScheduler timer = new TaskScheduler();
        timer.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime()));
            }
        },1000);

你可以使用處理程序。

此代碼每秒增加一個計數器,並在textView顯示和更新計數器值。

public class MainActivity extends Activity {


    private Handler handler = new Handler();
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        startTimer();
    }


    int i = 0;
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            i++;
            textView.setText("counter:" + i);
            startTimer();
        }
    };

    public void startTimer() {
        handler.postDelayed(runnable, 1000);
    }

    public void cancelTimer() {
        handler.removeCallbacks(runnable);
    }

    @Override
    protected void onStop() {
        super.onStop();
        handler.removeCallbacks(runnable);
    }
}

TimerTask 實現了 Runnable,這將使它成為一個線程。 如果不做一些工作,您無法直接從不同的線程更新主 UI 線程。 您可以做的一件事是使用 Async Task 創建計時器並每秒發布一次更新,以更新 UI。

我假設StopWatch.time是一些 static 或對您的 TextView 的公共引用。 而不是這樣做,您應該實現BroadcastReceiver以在您的計時器(從單獨的線程運行)和您的 TextView 之間進行通信。

我用這種方式:

String[] array = {"man", "for", "think"}; 
int j;

然后添加更多onCreate

TextView t = findViewById(R.id.textView);

new CountDownTimer(5000,1000) {

    @Override
    public void onTick(long millisUntilFinished) {}

    @Override
    public void onFinish() {
        t.setText("I " + array[j] + " You");
        j++;
        if (j == array.length - 1) j = 0;
        start();
    }
}.start();
 timer.schedule(new TimerTask() {
            @Override
            public void run() {

                //your actions

            }
        },1*1000);//1 sec

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM