[英]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.