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

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

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


当前回答

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

1.原始代码:

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

2.分析

在以上成本中,承担tv。append("Hello Word")花费T毫秒,显示500次后延迟时间为500*T毫秒 长时间运行会增加延时

3.解决方案

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

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

其他回答

科特林

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

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

1.原始代码:

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

2.分析

在以上成本中,承担tv。append("Hello Word")花费T毫秒,显示500次后延迟时间为500*T毫秒 长时间运行会增加延时

3.解决方案

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

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

一个有趣的例子是,你可以连续看到一个计数器/秒表在不同的线程中运行。还显示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.post()方法的文档:

导致Runnable r被添加到消息队列。可运行对象将在附加此处理程序的线程上运行。

所以@alex2k8提供的例子,即使工作正常,也是不一样的。 在使用Handler.post()的情况下,不会创建新的线程。您只需将Runnable与Handler一起发布到由EDT执行的线程。 在此之后,EDT只执行Runnable.run(),不执行其他任何操作。

记住: 可运行!=线程。