如何在Android上从后台线程显示Toast?


Answers:


246

您可以通过在线程中调用ActivityrunOnUiThread方法来实现:

activity.runOnUiThread(new Runnable() {
    public void run() {
        Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
    }
});

我不确定我该怎么做。我已有现有的public void run()。我试着把这段代码放在那里。我知道这是不对的,因为它不起作用,但是我真的很困惑。
SwimBikeRun 2012年

14
是否将“活动”传递给其构造函数中的非ui线程?从单独的线程中获取正在使用的活动对象的正确方法是什么?
snapfractalpop 2012年

Thread对象的引用设置为ActivityActivityonResume。取消它在ActivityonPausesynchronized都在Activity并同时Thread遵守的锁下进行操作。
JohnnyLambada'4

5
有时无法访问Activity实例,您可以使用简单的帮助程序类,请参见此处:stackoverflow.com/a/18280318/1891118
Oleksii K.

5
我通常发现MyActivity.this.runOnUiThread()Thread/ 内部可以正常工作AsyncTask
安东尼·阿特金森

62

我喜欢在我的活动中有一个方法,showToast可以从任何地方调用...

public void showToast(final String toast)
{
    runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}

然后,我经常在MyActivity这样的任何线程中从内部调用它...

showToast(getString(R.string.MyMessage));

3
谢谢,我现在要添加大多数活动。
Gene Myers 2013年

1
对于TOAST,请始终使用应用程序上下文,而不是活动上下文!
Yousha Aleayoub 2015年

1
@YoushaAleayoub为什么?
OneWorld '02

1
@OneWorld,证明:1-对于Toast消息,《 Google Dev Guide》使用应用程序上下文,并明确声明要使用它。2- stackoverflow.com/a/4128799/1429432 3- stackoverflow.com/a/10347346/1429432 4- groups.google.com/d/msg/android-developers/3i8M6-wAIwM/...
有啥Aleayoub

@YoushaAleayoub您提供的链接中有很多讨论和猜测。例如RomainGuy说,您的证明编号没有内存泄漏。4.有些链接来自Android在2009年的早期。人们在其他链接中说,您可以同时使用这两种上下文。活动和应用。也许您有一个更新的基于真实证据的证据?您是否有1个链接?
OneWorld '02

28

这与其他答案类似,但是针对新的可用api进行了更新并且更加简洁。另外,不要假设您处于活动上下文中。

public class MyService extends AnyContextSubclass {

    public void postToastMessage(final String message) {
        Handler handler = new Handler(Looper.getMainLooper());

        handler.post(new Runnable() {

            @Override
            public void run() {
                Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
            }
        });
    }
}

当您所处的环境不是一个完美的答案时。非常感谢!
弗朗卡斯

17

一种可以在几乎任何地方(包括没有Activityor的地方View)使用的方法是抓住a Handler并显示主线程:

public void toast(final Context context, final String text) {
  Handler handler = new Handler(Looper.getMainLooper());
  handler.post(new Runnable() {
    public void run() {
      Toast.makeText(context, text, Toast.LENGTH_LONG).show();
    }
  });
}

这种方法的优点是可以与任何对象一起使用Context,包括ServiceApplication


10

喜欢这个这个,用Runnable表示Toast。即

Activity activity = // reference to an Activity
// or
View view = // reference to a View

activity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        showToast(activity);
    }
});
// or
view.post(new Runnable() {
    @Override
    public void run() {
        showToast(view.getContext());
    }
});

private void showToast(Context ctx) {
    Toast.makeText(ctx, "Hi!", Toast.LENGTH_SHORT).show();
}

6

有时,您必须将消息从另一个发送Thread到UI线程。当您无法在UI线程上执行网络/ IO操作时,会发生这种情况。

下面的示例处理该情况。

  1. 你有UI线程
  2. 您必须启动IO操作,因此无法Runnable在UI线程上运行。因此,将您的帖子发布RunnableHandlerThread
  3. 从中获取结果Runnable并将其发送回UI线程并显示一条Toast消息。

解:

  1. 创建一个HandlerThread并启动它
  2. 创建一个处理程序活套来自HandlerThreadrequestHandler
  3. 从主线程创建带有Looper的处理程序: responseHandler并重写handleMessage方法
  4. post一项Runnable任务requestHandler
  5. 里面Runnable的任务,呼吁sendMessageresponseHandler
  6. 这个sendMessage结果调用handleMessageresponseHandler
  7. 从中获取属性Message并进行处理,更新UI

样例代码:

    /* Handler thread */

    HandlerThread handlerThread = new HandlerThread("HandlerThread");
    handlerThread.start();
    Handler requestHandler = new Handler(handlerThread.getLooper());

    final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

    for ( int i=0; i<5; i++) {
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                try {

                    /* Add your business logic here and construct the 
                       Messgae which should be handled in UI thread. For 
                       example sake, just sending a simple Text here*/

                    String text = "" + (++rId);
                    Message msg = new Message();

                    msg.obj = text.toString();
                    responseHandler.sendMessage(msg);
                    System.out.println(text.toString());

                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        };
        requestHandler.post(myRunnable);
    }

有用的文章:

handlerthreads和为什么要在您的Android应用程序中使用它们

android-looper-handler-handlerthread-i


5
  1. 获取UI线程处理程序实例并使用 handler.sendMessage();
  2. 通话post()方式handler.post();
  3. runOnUiThread()
  4. view.post()

3

您可以Looper用来发送Toast消息。通过此链接了解更多详细信息。

public void showToastInThread(final Context context,final String str){
    Looper.prepare();
    MessageQueue queue = Looper.myQueue();
    queue.addIdleHandler(new IdleHandler() {
         int mReqCount = 0;

         @Override
         public boolean queueIdle() {
             if (++mReqCount == 2) {
                  Looper.myLooper().quit();
                  return false;
             } else
                  return true;
         }
    });
    Toast.makeText(context, str,Toast.LENGTH_LONG).show();      
    Looper.loop();
}

它在您的线程中被调用。上下文可能Activity.getContext()正在从Activity您必须展示的吐司中得到。


2

我根据mjaggard的回答做了这种方法:

public static void toastAnywhere(final String text) {
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        public void run() {
            Toast.makeText(SuperApplication.getInstance().getApplicationContext(), text, 
                    Toast.LENGTH_LONG).show();
        }
    });
}

对我来说很好。


0

我遇到了同样的问题:

E/AndroidRuntime: FATAL EXCEPTION: Thread-4
              Process: com.example.languoguang.welcomeapp, PID: 4724
              java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()
                  at android.widget.Toast$TN.<init>(Toast.java:393)
                  at android.widget.Toast.<init>(Toast.java:117)
                  at android.widget.Toast.makeText(Toast.java:280)
                  at android.widget.Toast.makeText(Toast.java:270)
                  at com.example.languoguang.welcomeapp.MainActivity$1.run(MainActivity.java:51)
                  at java.lang.Thread.run(Thread.java:764)
I/Process: Sending signal. PID: 4724 SIG: 9
Application terminated.

之前:onCreate函数

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
    }
});
thread.start();

之后:onCreate函数

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
    }
});

有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.