如何在Android中以定义的间隔运行一个Runnable线程?

我开发了一个应用程序,以在Android模拟器屏幕中以定义的间隔显示一些文本。 我正在使用Handler类。 这里是我的代码片段:

 handler = new Handler(); Runnable r = new Runnable() { public void run() { tv.append("Hello World"); } }; handler.postDelayed(r, 1000); 

当我运行这个应用程序时,文本只显示一次。 为什么?

你的例子的简单修复是:

 handler = new Handler(); final Runnable r = new Runnable() { public void run() { tv.append("Hello World"); handler.postDelayed(this, 1000); } }; handler.postDelayed(r, 1000); 

或者我们可以使用正常的线程(例如原始亚军):

 Thread thread = new Thread() { @Override public void run() { try { while(true) { sleep(1000); handler.post(this); } } catch (InterruptedException e) { e.printStackTrace(); } } }; thread.start(); 

您可以将可运行对象视为可发送到消息队列执行的命令,并将处理程序作为用于发送该命令的辅助对象。

更多细节在这里http://developer.android.com/reference/android/os/Handler.html

我认为可以改进Alex2k8的第一个解决scheme,每秒更新一次

1.原代码:

 public void run() { tv.append("Hello World"); handler.postDelayed(this, 1000); } 

2.Analysis

  • 在以上成本中,假设tv.append("Hello Word")花费T毫秒,显示500次后延迟时间为500 * T毫秒
  • 运行时间过长会延迟

3.解决scheme

为了避免这种情况,只要改变postDelayed()的顺序,避免延迟:

 public void run() { handler.postDelayed(this, 1000); tv.append("Hello World"); } 
 new Handler().postDelayed(new Runnable() { public void run() { // do something... } }, 100); 

我相信对于这个典型的情况,即运行一个固定的时间间隔, 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不为null)

重复你可以使用的任务

 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来完成。 创build一个可运行的方法

 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 
 Handler handler=new Handler(); Runnable r = new Runnable(){ public void run() { tv.append("Hello World"); handler.postDelayed(r, 1000); } }; handler.post(r); 

如果我正确理解Handler.post()方法的文档:

导致Runnable r被添加到消息队列中。 runnable将在该处理程序所连接的线程上运行。

所以@ alex2k8提供的例子,即使正常工作,是不一样的。 如果使用Handler.post() ,则不会创build新的线程 。 您只需将Runnable发布到Handler的线程以由EDT执行。 之后,EDT只执行Runnable.run() ,没有别的。

记住: Runnable != Thread

一个有趣的例子是你可以连续看到一个计数器/秒表在单独的线程运行。 还显示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(); } 

看代码请看这里:

显示GPS位置和当前时间的主题示例可与主活动的用户界面线程一起运行

如果你想确保Handler将被附加到主线程,你应该像这样初始化它:

 new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { public void run() { // do something... } }, 100);