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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1921514/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:48:33  来源:igfitidea点击:

How to run a Runnable thread in Android at defined intervals?

androidmultithreading

提问by Rajapandian

I developed an application to display some text at defined intervals in the Android emulator screen. I am using the Handlerclass. Here is a snippet from my code:

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

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

When I run this application the text is displayed only once. Why?

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

回答by alex2k8

The simple fix to your example is :

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

handler = new Handler();

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

handler.postDelayed(r, 1000);

Or we can use normal thread for example (with original Runner) :

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

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

thread.start();

You may consider your runnable object just as a command that can be sent to the message queue for execution, and handler as just a helper object used to send that command.

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

More details are here http://developer.android.com/reference/android/os/Handler.html

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

回答by user2212515

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

回答by NguyenDat

I think can improve first solution of Alex2k8 for update correct each second

我认为可以改进 Alex2k8 的第一个解决方案,以便每秒更新正确

1.Original code:

1.原代码:

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

2.Analysis

2.分析

  • In above cost, assume tv.append("Hello Word")cost Tmilliseconds, after display 500times delayed time is 500*Tmilliseconds
  • It will increase delayed when run long time
  • 在上述成本中,假设tv.append("Hello Word")成本为T毫秒,显示500次后延迟时间为500*T毫秒
  • 长时间运行会增加延迟

3. Solution

3. 解决方案

To avoid that Just change order of postDelayed(), to avoid delayed:

为避免这种情况只需更改 postDelayed() 的顺序,以避免延迟:

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

回答by Jawad Zeb

For repeating task you can use

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

new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);

call it like

称之为

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

            }
        },500,1000);

The above code will run first time after half second(500)and repeat itself after each second(1000)

上面的代码将在半秒(500)后第一次运行,并在每一秒(1000)后重复自己

Where

在哪里

taskbeing the method to be executed

task是要执行的方法

afterthe time to initial execution

初始执​​行时间 之后

(intervalthe time for repeating the execution)

间隔重复执行的时间)

Secondly

其次

And you can also use CountDownTimerif you want to execute a Task number of times.

如果您想多次执行任务,也可以使用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

And you can also do it with runnable. create a runnable method like

你也可以用 runnable 来做到这一点。创建一个可运行的方法,如

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

        }
    };

And call it in both these ways

并以这两种方式调用它

new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis  // to work on mainThread

OR

或者

new Thread(runnable).start();//to work in Background 

回答by iTech

I believe for this typical case, i.e. to run something with a fixed interval, Timeris more appropriate. Here is a simple example:

我相信对于这种典型情况,即以固定间隔运行某事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

Using Timerhas few advantages:

使用Timer有几个优点:

  • Initial delay and the interval can be easily specified in the schedulefunction arguments
  • The timer can be stopped by simply calling myTimer.cancel()
  • If you want to have only one thread running, remember to call myTimer.cancel()beforescheduling a new one (if myTimer is not null)
  • 可以在schedule函数参数中轻松指定初始延迟和间隔
  • 只需调用即可停止计时器 myTimer.cancel()
  • 如果只想运行一个线程,记得myTimer.cancel()调度新线程之前调用(如果 myTimer 不为空)

回答by singh arjun

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

回答by Damian Walczak

If I understand correctly the documentation of Handler.post() method:

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

Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached.

将 Runnable r 添加到消息队列中。runnable 将在此处理程序附加到的线程上运行。

So examples provided by @alex2k8, even though are working correctly, are not the same. In case, where Handler.post()is used, no new threads are created. You just post Runnableto the thread with Handlerto be executed by EDT. After that, EDT only executes Runnable.run(), nothing else.

所以@alex2k8 提供的例子,即使工作正常,也不一样。如果Handler.post()使用where ,则不会创建新线程。您只需发布RunnableHandler要由EDT执行的线程即可。之后,EDT 只执行Runnable.run(),不执行其他操作。

Remember: Runnable != Thread.

记住: Runnable != Thread

回答by Khemraj

Kotlin

科特林

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)
}

Java

爪哇

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);
}

回答by Animesh Shrivastav

An interesting example is you can continuously see a counter/stop-watch running in separate thread. Also showing GPS-Location. While main activity User Interface Thread is already there.

一个有趣的例子是你可以连续看到一个计数器/秒表在单独的线程中运行。还显示 GPS 位置。虽然主要活动用户界面线程已经存在。

Excerpt:

摘抄:

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();
}

To look at code see here:

要查看代码,请参见此处:

Thread example displaying GPS Location and Current Time runnable alongside main-activity's User Interface Thread

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

回答by André Abboud

now in Kotlin you can run threads this way:

现在在 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
}