在安卓中使用handler和postDelayed实现暂停

10

我对安卓编程非常陌生,所以请原谅我的新手。我正在尝试创建一个非常简单的活动,其中在布局中间有一个 TextView,并且每隔几秒钟就将其切换到不同的文本。例如,TextView 将显示 "text1",暂停几秒钟,然后显示 "text2" 并再次暂停。最终,我想添加更多文本,并让它们依次循环。我知道这似乎是一件超级简单的事情,但我主要是想学习线程和处理程序。无论如何,我已经阅读了应该将冗长的事物从 UI 线程中移开以防止错误的内容,因此我想使用处理程序来简单地在屏幕上切换 2 个文本。不幸的是,我无法让它正常工作。以下是一些代码:

public class MainActivity extends Activity {

String[] myarray = {"text1" , "text2"};
int arraylength = myarray.length;
int count;
Handler handler = new Handler();

TextView mytexts;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mytexts = (TextView)findViewById(R.id.my_texts);
    mytexts.setText(myarray[0]);

    Thread t = new Thread( new Runnable(){
        public void run() {
            for (int count = 0; count < arraylength; count++){
                handler.postDelayed(new Runnable(){
                    public void run() {
                        mytexts.setText(myarray[1]);
                    }                   
                }, 7000);
            }
        }
    });
    t.start();
    }
}

根据logcat,处理程序似乎连续运行postDelayed(在我的代码中,它不等待7秒钟就会执行另一个postDelayed)。此外,我想让“mytexts.setText(myarray [1]);”中的数字1与for循环中的“count”相同,以便它可以与数组中的字符串之一相同,但这给我带来了错误。我已经被卡住几个小时了,我在网上找到的其他示例对于像我这样主要想掌握基础知识的人来说似乎过于复杂。任何关于这些问题的帮助都将不胜感激。谢谢。

为什么不移除 postDelayed,改用带有 whilepost,然后再使用 Thread.sleep(time) - Rotary Heart
@RotaryHeart,postDelay方法将在延迟后将代码发布到主线程上执行。您不需要使线程休眠。在这种特殊情况下,他根本不需要使用线程! - Ali
@Ali 是的,你说得对,我并不想改变他的代码,而是告诉他如何使用那段代码实现它。 - Rotary Heart
我最初确实尝试使用Thread.sleep方法,但在许多其他地方都读到过,处理程序是代码暂停的正确方式。这是真的吗,还是只是程序员之间的某种偏好? - John Octavious
2个回答

19
postDelayed 是非阻塞的,这意味着它会将任务添加到“稍后执行”的队列中。因此,你可能会看到所有文本更新在第7秒一起发生。我这么说是因为你正在从 onCreate 方法中进行 postDelay 操作,而实际上你可能希望从 onResume 或者 onPostResume 中进行。
此外,没有理由创建一个线程来添加可运行项到该队列中。你的代码应该像这样:
(注意延迟时间的乘数)
@Override
protected void onResume() {
    super.onResume();
    for (int count = 0; count < arraylength; count++){
        handler.postDelayed(new Runnable(){
            @Override
            public void run() {
                mytexts.setText(myarray[count]);
            }
        }, 7000 * (count + 1));
    }
}

是的,所有文本更新都发生在第7秒。我有些不清楚为什么不需要创建新线程。不过,postDelayed是否会自动在后台线程中执行7秒等待呢?我知道这个等待会导致UI出错,这就是我最初认为需要一个新线程的原因。 - John Octavious
你已经明白了,它会在当前(UI)线程之外“等待”。 - JRomero
不客气。标记问题已回答有助于回报;) - JRomero
如果我在postDelayed函数的第二个参数中放入7000而不是7000 *(count + 1),那么我的程序将在第7秒看到所有文本更新同时发生。为什么?我真的很困惑!:( - sandra
就像我所说的,postDelay 是一个定时的延迟。它不会增加每个字母之间的时间,而是所有“Runnable”都在 7 秒后触发,而不是在 7 秒、14 秒、21 秒等之后触发。 - JRomero

2
这是因为你的循环设置了所有处理程序在7秒后运行,但不是相互之间的7秒,而是从现在开始的7秒。你可以在处理程序中添加postDelayed方法或使用postAtTime方法。另外,你不需要在线程中执行此操作,可以完全摆脱它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接