下面的异常是什么意思;我该怎么解决呢?

这是代码:

Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);

这是例外:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
     at android.os.Handler.<init>(Handler.java:121)
     at android.widget.Toast.<init>(Toast.java:68)
     at android.widget.Toast.makeText(Toast.java:231)

当前回答

下面是Kotlin使用Coroutine的解决方案:

通过MainScope()使用CoroutineScope扩展类:

class BootstrapActivity :  CoroutineScope by MainScope() {}

然后简单地这样做:

launch {
        // whatever you want to do in the main thread
    }

不要忘记添加协程的依赖项:

org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}
org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.kotlinCoroutines}

其他回答

我就是这么做的。

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast(...);
    }
});

可视组件“锁定”于来自外部线程的更改。 因此,由于toast在主屏幕上显示由主线程管理的内容,您需要在主线程上运行这段代码。 希望这对你有所帮助。

我使用下面的代码来显示来自非主线程“context”的消息,

@FunctionalInterface
public interface IShowMessage {
    Context getContext();

    default void showMessage(String message) {
        final Thread mThread = new Thread() {
            @Override
            public void run() {
                try {
                    Looper.prepare();
                    Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
                    Looper.loop();
                } catch (Exception error) {
                    error.printStackTrace();
                    Log.e("IShowMessage", error.getMessage());
                }
            }
        };
        mThread.start();
    }
}

然后使用如下:

class myClass implements IShowMessage{

  showMessage("your message!");
 @Override
    public Context getContext() {
        return getApplicationContext();
    }
}
Handler handler2;  
HandlerThread handlerThread=new HandlerThread("second_thread");
handlerThread.start();
handler2=new Handler(handlerThread.getLooper());

现在handler2将使用一个不同于主线程的线程来处理消息。

错误原因:

工作线程是用来做后台任务的,你不能在工作线程的UI上显示任何东西,除非你调用像runOnUiThread这样的方法。如果你试图在UI线程上显示任何东西而不调用runOnUiThread,将会有一个java.lang.RuntimeException。

所以,如果你在一个活动中,但从工作线程调用Toast.makeText(),这样做:

runOnUiThread(new Runnable() 
{
   public void run() 
   {
      Toast toast = Toast.makeText(getApplicationContext(), "Something", Toast.LENGTH_SHORT).show();    
   }
}); 

上面的代码确保您在UI线程中显示Toast消息,因为您是在runOnUiThread方法中调用它。所以不再有java.lang.RuntimeException。

Toast, alertdialog需要在UI线程上运行,你可以使用Asynctask在android开发中正确使用它们。但有些情况下,我们需要自定义超时,所以我们使用线程,但在线程中,我们不能使用Toast, alertdialog,就像我们在AsyncTask中使用的那样。我们需要单独的Handler来处理弹出这些。

public void onSigned() {
    Thread thread = new Thread(){
        @Override
        public void run() {
            try{
                sleep(3000);
                Message message = new Message();
                message.what = 2;
                handler.sendMessage(message);
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    };
    thread.start();
}

在上面的例子中,我想睡我的线程在3秒后,我想显示一个吐司消息,在你的主线程实现处理程序。

handler = new Handler() {
       public void handleMessage(Message msg) {
           switch(msg.what){
              case 1:
              Toast.makeText(getActivity(),"cool",Toast.LENGTH_SHORT).show();
              break;
           }
           super.handleMessage(msg);
       }
};

我在这里使用了switch case,因为如果你需要以相同的方式显示不同的消息,你可以在Handler类中使用switch case…希望这对你有所帮助