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

Raj*_*ian 335 multithreading android

我开发了一个应用程序,在Android模拟器屏幕中以定义的间隔显示一些文本.我正在Handler上课.以下是我的代码中的代码段:

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

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

ale*_*2k8 516

对您的示例的简单修复是:

handler = new Handler();

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

handler.postDelayed(r, 1000);
Run Code Online (Sandbox Code Playgroud)

或者我们可以使用普通线程(使用原始Runner):

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

thread.start();
Run Code Online (Sandbox Code Playgroud)

您可以将runnable对象视为可以发送到消息队列以执行的命令,并将handler作为用于发送该命令的辅助对象.

更多细节请访问http://developer.android.com/reference/android/os/Handler.html

  • 您可以定义布尔变量_stop,并在想要停止时将其设置为"true".并将'while(true)'更改为'while(!_ stop)',或者如果使用的是第一个样本,只需更改为'if(!_ stop)handler.postDelayed(this,1000)'. (10认同)

use*_*515 41

new Handler().postDelayed(new Runnable() {
    public void run() {
        // do something...              
    }
}, 100);
Run Code Online (Sandbox Code Playgroud)

  • 如果你想确保Handler将被附加到主线程,你应该像这样初始化它:new Handler(Looper.getMainLooper()); (2认同)

Ngu*_*Dat 40

我认为可以改善Alex2k8的第一个解决方案,每秒更新一次

1.原始代码:

public void run() {
    tv.append("Hello World");
    handler.postDelayed(this, 1000);
}
Run Code Online (Sandbox Code Playgroud)

2.Analysis

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

3.解决方案

为了避免只改变postDelayed()的顺序,以避免延迟:

public void run() {
    handler.postDelayed(this, 1000);
    tv.append("Hello World");
}
Run Code Online (Sandbox Code Playgroud)

  • -1你假设你在run()中执行的任务是每次运行的成本是一个恒定的数量,如果这是对动态数据的操作(通常是这样)那么你最终会遇到多个run()一旦.这就是postDelayed通常放在最后的原因. (6认同)

Xar*_*mer 25

对于重复任务,您可以使用

new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);
Run Code Online (Sandbox Code Playgroud)

称之为

new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

            }
        },500,1000);
Run Code Online (Sandbox Code Playgroud)

上面的代码将在半秒(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
Run Code Online (Sandbox Code Playgroud)

你也可以用runnable来做.创建一个像run的运行方法

Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {

        }
    };
Run Code Online (Sandbox Code Playgroud)

并以这两种方式称呼它

new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis  // to work on mainThread
Run Code Online (Sandbox Code Playgroud)

要么

new Thread(runnable).start();//to work in Background 
Run Code Online (Sandbox Code Playgroud)


iTe*_*ech 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
Run Code Online (Sandbox Code Playgroud)

使用Timer几乎没有优势:

  • 可以在schedule函数参数中轻松指定初始延迟和间隔
  • 只需调用即可停止计时器 myTimer.cancel()
  • 如果您只想运行一个线程,请记住myTimer.cancel() 安排新线程之前调用(如果myTimer不为null)

  • 我不相信计时器更合适,因为它不考虑android生命周期.暂停和恢复时,没有保证定时器能够正常运行.我认为可运行是更好的选择. (7认同)

小智 16

Handler handler=new Handler();
Runnable r = new Runnable(){
    public void run() {
        tv.append("Hello World");                       
        handler.postDelayed(r, 1000);
    }
}; 
handler.post(r);
Run Code Online (Sandbox Code Playgroud)

  • 这应该会出错.在你的第二行,你正在调用已定义的变量`r`. (5认同)

Khe*_*raj 6

科特林

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)
}
Run Code Online (Sandbox Code Playgroud)

爪哇

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);
}
Run Code Online (Sandbox Code Playgroud)