[英]Android, how can i update a view element from a private inner class which is an AsyncTask
I am making an android application as part of a school assignment. 我正在做一个android应用程序作为学校作业的一部分。
I need to be able to display a timer in hh:mm:ss
and update the timer every second. 我需要能够在
hh:mm:ss
显示一个计时器,并每秒更新一次计时器。
I have managed to come up with the code i think will produce the results i need, but i cannot get the AsyncTask
to execute every second. 我设法提出了我认为会产生所需结果的代码,但是我无法使
AsyncTask
每秒执行一次。 This is my current code: 这是我当前的代码:
TimerHand timerHand = new TimerHandling(timerTextView);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
timerHand.execute();
} },1000, 1000); // 1000ms == 1 second
This is the Async task this is a nested class inside the class which holds the above code, and the declaration of the TextView tv: 这是Async任务,这是一个包含上述代码以及TextView tv声明的类中的嵌套类:
class TimerHandling extends AsyncTask<Void, Void, Void>{
private long secs, mins, hours, millis;
private String timeString;
private TextView tv;
private long startTime;
private boolean stop;
private Handler handler;
public TimerHandling(TextView tv){
this.tv = tv;
startTime = System.currentTimeMillis();
stop = false;
handler = new Handler();
}
@Override
protected Void doInBackground(Void... params) {
while(stop != true){
millis = System.currentTimeMillis() - startTime;
hours += TimeUnit.MILLISECONDS.toHours(millis);
mins += TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis));
secs += TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MILLISECONDS.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis));
timeString = String.format("%02d:%02d:%02d",hours, mins, secs);
handler.post(new Runnable() {
@Override
public void run() {
tv.setText(timeString);
}
});
}
return null;
}
public void setStopCondition(boolean condition){
this.stop = condition;
}
}
}
It produces the following logCat output: 它产生以下logCat输出:
01-23 18:00:27.865: E/AndroidRuntime(14458): FATAL EXCEPTION: AsyncTask #5
01-23 18:00:27.865: E/AndroidRuntime(14458): Process: dcs.aber.ac.uk.cs211.group02, PID: 14458
01-23 18:00:27.865: E/AndroidRuntime(14458): java.lang.RuntimeException: An error occured while executing doInBackground()
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.os.AsyncTask$3.done(AsyncTask.java:300)
01-23 18:00:27.865: E/AndroidRuntime(14458): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
01-23 18:00:27.865: E/AndroidRuntime(14458): at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
01-23 18:00:27.865: E/AndroidRuntime(14458): at java.util.concurrent.FutureTask.run(FutureTask.java:242)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
01-23 18:00:27.865: E/AndroidRuntime(14458): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
01-23 18:00:27.865: E/AndroidRuntime(14458): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
01-23 18:00:27.865: E/AndroidRuntime(14458): at java.lang.Thread.run(Thread.java:841)
01-23 18:00:27.865: E/AndroidRuntime(14458): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:824)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.view.View.requestLayout(View.java:16431)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.view.View.requestLayout(View.java:16431)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.view.View.requestLayout(View.java:16431)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.view.View.requestLayout(View.java:16431)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.view.View.requestLayout(View.java:16431)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.widget.TextView.checkForRelayout(TextView.java:6600)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.widget.TextView.setText(TextView.java:3813)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.widget.TextView.setText(TextView.java:3671)
01-23 18:00:27.865: E/AndroidRuntime(14458): at android.widget.TextView.setText(TextView.java:3646)
I understand that is is caused because the nested class has a different View so it cannot update the TextView, how can i overcome this? 我知道这是由于嵌套类具有不同的View导致的,因此它无法更新TextView,我该如何克服呢?
When i run my code, i can see it executing and after about 2 seconds the app will crash wth the posted error message. 当我运行我的代码时,我可以看到它正在执行,大约2秒钟后,该应用程序将因发布的错误消息而崩溃。
Update: 更新:
public void startCountingTimer() { 公共无效startCountingTimer(){
final Handler handler = new Handler();
final Runnable task = new Runnable()
{
@Override
public void run() {
millis = System.currentTimeMillis() - startTime;
hours += TimeUnit.MILLISECONDS.toHours(millis);
mins += TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis));
secs += TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MILLISECONDS.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis));
timeString = String.format("%02d:%02d:%02d",hours, mins, secs);
handler.postDelayed(task, 1000); //problem on this line
}
};
task.run();
} }
I have pointed out the problem with a single line comment, "task" is undeclared. 我已经指出了单行注释的问题,“任务”未声明。
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
You are trying to update ui from a non ui thread which is not possible. 您尝试从非ui线程更新ui,这是不可能的。 You should update ui from the ui thread.
您应该从ui线程更新ui。
Timer
runs on a different thread. Timer
在其他线程上运行。
Also read threading rules @ http://developer.android.com/reference/android/os/AsyncTask.html 另请阅读线程规则@ http://developer.android.com/reference/android/os/AsyncTask.html
I need to be able to display a timer in hh:mm:ss and update the timer every second.
You can use a Handler
or a CountDownTimer
您可以使用
Handler
或CountDownTimer
Handler
is associated with the thread in which it is created. Handler
程序与创建它的线程相关联。
http://developer.android.com/reference/android/os/Handler.html http://developer.android.com/reference/android/os/Handler.html
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
@Override
public void run() {
// do something
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
For the count down timer 对于倒数计时器
Countdowntimer in minutes and seconds 倒数计时器,以分钟和秒为单位
Edit: 编辑:
public class MainActivity extends Activity {
Handler handler;
Runnable task ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startCountingTimer();
}
public void startCountingTimer() {
handler = new Handler();
task = new Runnable()
{
@Override
public void run() {
// do something
handler.postDelayed(task, 1000);
}
};
task.run();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.