我开发了一个应用程序,可以在Android模拟器屏幕中以定义的间隔显示一些文本。我正在使用Handler
课程。以下是我的代码片段:
handler = new Handler();
Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
}
};
handler.postDelayed(r, 1000);
当我运行此应用程序时,文本仅显示一次。为什么呢?
答案 0 :(得分:498)
您示例的简单修复是:
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
或者我们可以使用普通线程(使用原始Runner):
Thread thread = new Thread() {
@Override
public void run() {
try {
while(true) {
sleep(1000);
handler.post(this);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
您可以将runnable对象视为可以发送到消息队列以执行的命令,并将handler作为用于发送该命令的辅助对象。
详情请见http://developer.android.com/reference/android/os/Handler.html
答案 1 :(得分:40)
我认为可以改进Alex2k8的第一个解决方案,以便每秒更新一次
1.原始代码:
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
<强> 2.Analysis 强>
tv.append("Hello Word")
费用 T 毫秒,显示 500 次延迟时间 500 * T 毫秒< / LI>
第3。溶液强>
要避免只改变postDelayed()的顺序,以避免延迟:
public void run() {
handler.postDelayed(this, 1000);
tv.append("Hello World");
}
答案 2 :(得分:39)
new Handler().postDelayed(new Runnable() {
public void run() {
// do something...
}
}, 100);
答案 3 :(得分:23)
我相信这种典型情况,即以固定间隔运行某些东西,Timer
更合适。这是一个简单的例子:
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
@Override
public void run() {
// If you want to modify a view in your Activity
MyActivity.this.runOnUiThread(new Runnable()
public void run(){
tv.append("Hello World");
});
}
}, 1000, 1000); // initial delay 1 second, interval 1 second
使用Timer
几乎没有优势:
schedule
函数参数myTimer.cancel()
myTimer.cancel()
(如果myTimer不为空)答案 4 :(得分:23)
对于重复任务,您可以使用
new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);
称之为
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
}
},500,1000);
以上代码将在半秒(500)之后首次运行,并在每次秒(1000)后重复
哪里
任务是要执行的方法
在初始执行时间后
(间隔重复执行的时间)
<强>其次强>
如果您想执行任务次数,也可以使用 CountDownTimer 。
new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
}
}.start();
//Above codes run 40 times after each second
你也可以用runnable来做。创建一个像
这样的可运行方法Runnable runnable = new Runnable()
{
@Override
public void run()
{
}
};
并以这两种方式称呼它
new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis // to work on mainThread
或强>
new Thread(runnable).start();//to work in Background
答案 5 :(得分:16)
Handler handler=new Handler();
Runnable r = new Runnable(){
public void run() {
tv.append("Hello World");
handler.postDelayed(r, 1000);
}
};
handler.post(r);
答案 6 :(得分:3)
如果我理解了Handler.post()方法的文档:
使Runnable r添加到消息队列中。 runnable将在连接此处理程序的线程上运行。
所以@ alex2k8提供的例子即使工作正常也不一样。
如果使用Handler.post()
,不会创建新线程。您只需将Runnable
发布到Handler
的帖子即EDT执行。
之后,EDT仅执行Runnable.run()
,而不执行任何其他操作。
记住:
Runnable != Thread
。
答案 7 :(得分:1)
一个有趣的例子是你可以在不同的线程中连续看到一个计数器/秒表运行。还显示GPS位置。虽然主要活动用户界面线程已经存在。
摘录:
try {
cnt++; scnt++;
now=System.currentTimeMillis();
r=rand.nextInt(6); r++;
loc=lm.getLastKnownLocation(best);
if(loc!=null) {
lat=loc.getLatitude();
lng=loc.getLongitude();
}
Thread.sleep(100);
handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {
Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}
要查看代码,请参阅此处:
答案 8 :(得分:1)
在Kotlin中,可以使用协同程序执行以下操作:
CoroutineScope(Dispatchers.Main).launch { // Main, because UI is changed
ticker(delayMillis = 1000, initialDelayMillis = 1000).consumeEach {
tv.append("Hello World")
}
}
尝试here!
答案 9 :(得分:0)
现在在Kotlin中,您可以通过以下方式运行线程:
class SimpleRunnable: Runnable {
public override fun run() {
println("${Thread.currentThread()} has run.")
}
}
fun main(args: Array<String>) {
val thread = SimpleThread()
thread.start() // Will output: Thread[Thread-0,5,main] has run.
val runnable = SimpleRunnable()
val thread1 = Thread(runnable)
thread1.start() // Will output: Thread[Thread-1,5,main] has run
}
答案 10 :(得分:0)
private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
val handler = Handler()
runnable = Runnable {
// do your work
handler.postDelayed(runnable, 2000)
}
handler.postDelayed(runnable, 2000)
}
Runnable runnable;
Handler handler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
// do your work
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
}