Android 使用 Runnable 和 postDelayed 更新 UI 不适用于计时器应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3765161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Updating UI with Runnable & postDelayed not working with timer app
提问by bdelliott
I have looked at every discussion and thread I can find on getting this to work but it is not. I have a simple timer that updates a text view (mTimeTextField in the example below). The mUpdateTimeTask run method is being executed correctly (every second) but the UI/text field is not being updated.
我已经查看了我可以找到的关于使其工作的所有讨论和线程,但事实并非如此。我有一个简单的计时器来更新文本视图(下面示例中的 mTimeTextField)。mUpdateTimeTask run 方法正在正确执行(每秒),但 UI/文本字段未更新。
I have code based on the info found here:
我有基于此处找到的信息的代码:
http://android-developers.blogspot.com/2007/11/stitch-in-time.htmlhttp://developer.android.com/resources/articles/timed-ui-updates.html
http://android-developers.blogspot.com/2007/11/stitch-in-time.html http://developer.android.com/resources/articles/timed-ui-updates.html
Here is the code:
这是代码:
package com.something.handlertest;
import com.something.handlertest.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class Test extends Activity {
private Handler mHandler = new Handler();
private int labelNo = 0;
private long currTime = 0L;
private long mStartTime = 0L;
TextView mTimeTextField;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTimeTextField = (TextView)findViewById(R.id.timeTextFieldl);
Button startButton = (Button)findViewById(R.id.start_button);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mStartTime == 0L) {
mStartTime = System.currentTimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
}
});
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
final long start = mStartTime;
//long millis = SystemClock.uptimeMillis() - start;
long millis = SystemClock.uptimeMillis();
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
//setContentView(mTimeTextField); This will blow up if I use it
if (seconds < 10) {
mTimeTextField.setText("" + minutes + ":0" + seconds);
} else {
mTimeTextField.setText("" + minutes + ":" + seconds);
}
//mHandler.postAtTime(this,
// start + (((minutes * 60) + seconds + 1) * 1000));
mHandler.postAtTime(this, 1000);
}
};
}
Per some suggestions, I have tried adding:
根据一些建议,我尝试添加:
setContentView(mTimeLabel);
But this will crash complain about the view not having a parent. FYI, I do have a:
但这会崩溃抱怨没有父级的视图。仅供参考,我确实有一个:
setContentView(R.layout.main);
call in my onCreate()
.
呼入我的onCreate()
.
回答by Fedor
Replace
代替
mHandler.postAtTime(this, 1000);
with
和
mHandler.postDelayed(this, 1000);
回答by david m lee
- You need to do UI updates in the UI thread.
You need to create a Handler in the UI thread to run tasks in the UI thread.
public class MainActivity extends AppCompatActivity private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { mHandler = new Handler(); // This to create the Handler in the UI thread // ... }
- 您需要在 UI 线程中进行 UI 更新。
需要在UI线程中创建一个Handler来运行UI线程中的任务。
public class MainActivity extends AppCompatActivity private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { mHandler = new Handler(); // This to create the Handler in the UI thread // ... }
回答by Laith Alnagem
This might be more along the lines of what you are looking for:
这可能更符合您正在寻找的内容:
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
final long start = mStartTime;
long elapseTime = System.currentTimeMillis() - start;
int seconds = (int) (elapseTime / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
if (seconds < 10) {
mTimeTextField.setText("" + minutes + ":0" + seconds);
} else {
mTimeTextField.setText("" + minutes + ":" + seconds);
}
// add a delay to adjust for computation time
long delay = (1000 - (elapseTime%1000));
mHandler.postDelayed(this, delay);
}
};
I found this to be a good way to add a time to video's
我发现这是为视频添加时间的好方法
回答by Hariharan Veerappan
view can only be displayed on UI thread. you have to start the runnable using ru
视图只能显示在 UI 线程上。你必须使用 ru 启动 runnable
回答by bask0xff
if (seconds < 10) {
mTimeTextField.setText("" + minutes + ":0" + seconds);
} else {
mTimeTextField.setText("" + minutes + ":" + seconds);
}
shorter is:
较短的是:
mTimeTextField.setText(minutes + ":" + (seconds < 10 ? "0" : "") + seconds);
but better way is using String.format^
但更好的方法是使用 String.format^
mTimeTextField.setText(String.format("%d:%s%d", minutes, (seconds < 10 ? "0" : ""), seconds);
回答by Fedor
Please ensure R.id.timeTextFieldl is a correct id.
请确保 R.id.timeTextFieldl 是正确的 ID。