java - 使用 Thread.sleep 了解循环中的 toast

标签 java android toast

我是 Android 开发新手。只是想测试以下代码,点击按钮执行一些任务。在日志显示循环结束后 Toast 弹出,因为 Toast 是异步的。但是

  • 当我注释掉 Thread.sleep()(在没有 thread.sleep() 的情况下循环)时,所有 toast 都显示为 0 到 14
  • 当 Thread.sleep(1000) 时,toasts 显示为 7 到 14
  • 当 Thread.sleep(500) 时,toasts 显示为 3 到 14
  • Thread.sleep(2000)时,只显示第14条toast

为什么会这样?据我所知,这一切都发生在 UI 线程中。如果只有一个线程,那么toast是如何异步工作的?

谢谢

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int i=0;
                int j=0;
                Log.d("tag", "sec "+i);
                while(i++<15){
                    Log.d("tag", "sec "+i);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    Toast.makeText(getApplicationContext(),"num"+(j),Toast.LENGTH_SHORT).show();
                    j++;
                 }

            }
        });

最佳答案

Toast is asynchronous

首先,默认情况下 Toast 不是异步的。

why does it behave like this?

使用 Toast.LENGTH_SHORT 创建的 toast 的生命周期为 2 秒。现在,如果您的 UI 线程被锁定(因为 Thread.sleep),则 toast 将不会出现在屏幕上。它会在显示之前“死亡”。

如何让它按预期工作

在新创建的 Thread 中运行整个 block ,并且只在主线程中创建和显示 Toast, 你需要按照以下几行做一些事情,

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int i = 0;
                int j = 0;
                Log.d("tag", "sec " + i);
                while (i++ < 15) {
                    Log.d("tag", "sec " + i);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    final int finalJ = j;
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), "num" + (finalJ), Toast.LENGTH_SHORT).show();
                        }
                    });
                    j++;
                }
            }
        }).start();
    }
});

通过使用 Handler.postDelayed

,您也可以在不使用不同线程的情况下获得类似的结果
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        final int[] i = {0};
        final int[] j = {0};
        final int delayTime = 1000;

        Log.d("tag", "sec "+ i[0]);
        final Handler handler = new Handler();
        final Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if(i[0]++<15) {
                    Log.d("tag", "sec " + i[0]);
                    Toast.makeText(getApplicationContext(), "num" + (j[0]), Toast.LENGTH_SHORT).show();
                    j[0]++;
                    handler.postDelayed(this, delayTime);
                }
            }
        };
        handler.postDelayed(runnable, delayTime);
    }
});

P.S - 切勿在主线程中使用 Thread.sleep,它会阻塞 UI 并导致糟糕的 UX。

关于java - 使用 Thread.sleep 了解循环中的 toast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57344531/

相关文章:

java - Selenium 远程独立服务器 - 驱动程序未知

java - 使用助手类使用 Soot 检测 Android 应用程序

java - 从单独的线程制作 Toast 消息

angular - 有没有办法对所有消息只使用一个 p-toast?

android - 如何在处理程序/线程中显示 Toast?

java - 如何在java集合hashmap或hashset或arraylist中存储webtable?

java - 在我的 fragment 中,非法状态异常显示在我的文档引用 firestore 集合中

java - 突出显示的文本存储在哪里?

android - 将滚动 fragment 设置为滚动 Activity

标签 View 中标签下方底部的 Android admob 广告