无法在未调用Looper.prepare()的线程内创建处理程序

mic*_*ael 919 android ui-thread android-toast

以下例外意味着什么; 我该怎么解决?

这是代码:

Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
Run Code Online (Sandbox Code Playgroud)

这是例外:

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)
Run Code Online (Sandbox Code Playgroud)

Jac*_*ble 820

您需要Toast.makeText(...)从UI线程调用:

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

这是从另一个(重复的)SO答案复制粘贴的.

  • 很好的答案.这让我困惑了一段时间.需要注意的是,我不需要这项活动.在runOnUiThread之前. (13认同)

Ebo*_*ike 655

你是从工作线程调用它.您需要Toast.makeText()从主线程中调用(以及处理UI的大多数其他函数).例如,您可以使用处理程序.

查找文档中的UI线程进行通信.简而言之:

// Set this up in the UI thread.

mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message message) {
        // This is where you do your work in the UI thread.
        // Your worker tells you in the message what to do.
    }
};

void workerThread() {
    // And this is how you call it from the worker thread:
    Message message = mHandler.obtainMessage(command, parameter);
    message.sendToTarget();
}
Run Code Online (Sandbox Code Playgroud)

其他选择:

您可以使用AsyncTask,它适用于在后台运行的大多数事情.它有一些钩子,您可以调用它来指示进度,以及何时完成.

您还可以使用Activity.runOnUiThread().

  • 把我的两分钱加到Cleggy说的话.最好简要说明你的意思(无论多么做作),因为编码的例子往往可以说明自己的意义. (5认同)
  • 要获得完整的技术答案,请参阅此http://prasanta-paul.blogspot.kr/2013/09/android-looper-and-toast-from.html (5认同)
  • 在几乎支持所有GUI编程语言据我所知,如果你更新/更改/显示/使用GUI直接交互,它应该在程序的主线程上完成. (3认同)

mjo*_*osh 435

更新 - 2016年

最好的选择是使用RxAndroid(用于特异性结合RxJava)用于PMVP给负责FO数据.

首先Observable从现有方法返回.

private Observable<PojoObject> getObservableItems() {
    return Observable.create(subscriber -> {

        for (PojoObject pojoObject: pojoObjects) {
            subscriber.onNext(pojoObject);
        }
        subscriber.onCompleted();
    });
}
Run Code Online (Sandbox Code Playgroud)

像这样使用这个Observable -

getObservableItems().
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Observer<PojoObject> () {
    @Override
    public void onCompleted() {
        // Print Toast on completion
    }

    @Override
    public void onError(Throwable e) {}

    @Override
    public void onNext(PojoObject pojoObject) {
        // Show Progress
    }
});
}
Run Code Online (Sandbox Code Playgroud)

-------------------------------------------------- -------------------------------------------------- ------------------------------

我知道我有点晚了但是这里去了.Android基本上适用于两种线程类型,即UI线程后台线程.根据android文档 -

不要从UI线程外部访问Android UI工具包来解决此问题,Android提供了几种从其他线程访问UI线程的方法.以下是可以提供帮助的方法列表:

Activity.runOnUiThread(Runnable)  
View.post(Runnable)  
View.postDelayed(Runnable, long)
Run Code Online (Sandbox Code Playgroud)

现在有各种方法可以解决这个问题.

我将通过代码示例解释它:

runOnUiThread

new Thread()
{
    public void run()
    {
        myactivity.this.runOnUiThread(new Runnable()
        {
            public void run()
            {
                //Do your UI operations like dialog opening or Toast here
            }
        });
    }
}.start();
Run Code Online (Sandbox Code Playgroud)

LOOPER

用于为线程运行消息循环的类.默认情况下,线程没有与之关联的消息循环; 创建一个,在运行循环的线程中调用prepare(),然后循环()让它处理消息,直到循环停止.

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // process incoming messages here
            }
        };

        Looper.loop();
    }
}
Run Code Online (Sandbox Code Playgroud)

的AsyncTask

AsyncTask允许您在用户界面上执行异步工作.它在工作线程中执行阻塞操作,然后在UI线程上发布结果,而不需要您自己处理线程和/或处理程序.

public void onClick(View v) {
    new CustomTask().execute((Void[])null);
}


private class CustomTask extends AsyncTask<Void, Void, Void> {

    protected Void doInBackground(Void... param) {
        //Do some work
        return null;
    }

    protected void onPostExecute(Void param) {
        //Print Toast or open dialog
    }
}
Run Code Online (Sandbox Code Playgroud)

处理器

Handler允许您发送和处理与线程的MessageQueue关联的Message和Runnable对象.

Message msg = new Message();


new Thread()
{
    public void run()
    {
        msg.arg1=1;
        handler.sendMessage(msg);
    }
}.start();



Handler handler = new Handler(new Handler.Callback() {

    @Override
    public boolean handleMessage(Message msg) {
        if(msg.arg1==1)
        {
            //Print Toast or open dialog        
        }
        return false;
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 这是_exactly_我​​正在寻找的.特别是`runOnUiThread`的第一个例子 (7认同)
  • 谢谢,5年的Android编程,我从来不知道`View`也有方法`post(Runnable)`和`postDelayed(Runnable,long)`!这么多处理程序都是徒劳的.:) (5认同)

Khu*_*Sim 88

试试这个,当你看到由于Looper没有在handler之前准备好而导致的runtimeException.

Handler handler = new Handler(Looper.getMainLooper()); 

handler.postDelayed(new Runnable() {
  @Override
  public void run() {
  // Run your task here
  }
}, 1000 );
Run Code Online (Sandbox Code Playgroud)

  • @StealthRabbi从正确的命名空间即android.os.Handler导入Handler。 (2认同)

Aya*_*fov 87

Toast.makeText()应该从Main/UI线程调用.Looper.getMainLooper()帮助您实现它:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
    }
});
Run Code Online (Sandbox Code Playgroud)

此方法的一个优点是您可以在非Activity(或没有Context)类中使用它.

  • 谢谢其他答案并不适合我.我正在使用库糖记录来管理持久性.在里面,我没有活动.但这非常有效 (2认同)

Chi*_*ird 40

我遇到了同样的问题,这就是我修复它的方法:

private final class UIHandler extends Handler
{
    public static final int DISPLAY_UI_TOAST = 0;
    public static final int DISPLAY_UI_DIALOG = 1;

    public UIHandler(Looper looper)
    {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg)
    {
        switch(msg.what)
        {
        case UIHandler.DISPLAY_UI_TOAST:
        {
            Context context = getApplicationContext();
            Toast t = Toast.makeText(context, (String)msg.obj, Toast.LENGTH_LONG);
            t.show();
        }
        case UIHandler.DISPLAY_UI_DIALOG:
            //TBD
        default:
            break;
        }
    }
}

protected void handleUIRequest(String message)
{
    Message msg = uiHandler.obtainMessage(UIHandler.DISPLAY_UI_TOAST);
    msg.obj = message;
    uiHandler.sendMessage(msg);
}
Run Code Online (Sandbox Code Playgroud)

要创建UIHandler,您需要执行以下操作:

    HandlerThread uiThread = new HandlerThread("UIHandler");
    uiThread.start();
    uiHandler = new UIHandler((HandlerThread) uiThread.getLooper());
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 最后一行不应该是`uiHandler = new UIHandler(uiThread.getLooper());`? (2认同)

My *_*God 34

错误原因:

工作线程用于执行后台任务,除非您调用runOnUiThread之类的方法,否则无法在工作线程中的UI上显示任何内容.如果你尝试在不调用runOnUiThread的情况下在UI线程上显示任何内容,那么将会有一个java.lang.RuntimeException.

因此,如果您在工作线程中进行activity调用Toast.makeText(),请执行以下操作:

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

上面的代码确保您UI threadrunOnUiThread方法中调用它时显示Toast消息.所以没有了java.lang.RuntimeException.


Epi*_*rce 21

我收到此错误,直到我执行以下操作.

public void somethingHappened(final Context context)
{
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(
        new Runnable()
        {
            @Override
            public void run()
            {
                Toast.makeText(context, "Something happened.", Toast.LENGTH_SHORT).show();
            }
        }
    );
}
Run Code Online (Sandbox Code Playgroud)

并将其变成了单例类:

public enum Toaster {
    INSTANCE;

    private final Handler handler = new Handler(Looper.getMainLooper());

    public void postMessage(final String message) {
        handler.post(
            new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(ApplicationHolder.INSTANCE.getCustomApplication(), message, Toast.LENGTH_SHORT)
                        .show();
                }
            }
        );
    }

}
Run Code Online (Sandbox Code Playgroud)


eir*_*ran 20

这就是我做的.

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast(...);
    }
});
Run Code Online (Sandbox Code Playgroud)

可视组件被"锁定"到来自外部线程的更改.因此,由于toast在主屏幕上显示由主线程管理的内容,因此您需要在该线程上运行此代码.希望有帮助:)


小智 9

 runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(mContext, "Message", Toast.LENGTH_SHORT).show();
            }
        });
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用,我使用 lambda `runOnUiThread(() -&gt; { Toast toast = Toast.makeText(getApplicationContext(), "Message", Toast.LENGTH_SHORT); toast.show(); });` (2认同)

Has*_*sef 9

第一个调用Looper.prepare(),然后调用Toast.makeText().show()最后一个调用,Looper.loop()如:

Looper.prepare() // to be able to make toast
Toast.makeText(context, "not connected", Toast.LENGTH_LONG).show()
Looper.loop()
Run Code Online (Sandbox Code Playgroud)


Bis*_*kar 8

这是因为Toast.makeText()是从工作线程调用的.应该像这样从主UI线程调用它

runOnUiThread(new Runnable() {
      public void run() {
        Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
      }
 });
Run Code Online (Sandbox Code Playgroud)


Bri*_*old 7

ChicoBird的答案为我工作.我所做的唯一改变是创建了我必须做的UIHandler

HandlerThread uiThread = new HandlerThread("UIHandler");
Run Code Online (Sandbox Code Playgroud)

Eclipse拒绝接受任何其他内容.我想是有道理的.

uiHandler显然,这是一个全局定义的类.我仍然没有声称理解Android是如何做到这一点以及发生了什么,但我很高兴它的工作原理.现在我将继续研究它,看看我是否能理解Android正在做什么以及为什么必须经历所有这些环和循环.感谢ChicoBird的帮助.


jun*_*dev 6

出色的Kotlin解决方案:

runOnUiThread {
    // Add your ui thread code here
}
Run Code Online (Sandbox Code Playgroud)

  • `runOnUiThread`是Activity的一部分,即`activity?.runOnUiThread {...}` (3认同)

Abd*_*rek 6

协程会完美地做到这一点

CoroutineScope(Job() + Dispatchers.Main).launch {
                        Toast.makeText(context, "yourmessage",Toast.LENGTH_LONG).show()}
Run Code Online (Sandbox Code Playgroud)


Gen*_*wen 5

对于Rxjava和RxAndroid用户:

public static void shortToast(String msg) {
    Observable.just(msg)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(message -> {
                Toast.makeText(App.getInstance(), message, Toast.LENGTH_SHORT).show();
            });
}
Run Code Online (Sandbox Code Playgroud)


COR*_*ian 5

爪哇8

new Handler(Looper.getMainLooper()).post(() -> {
    // Work in the UI thread

}); 
Run Code Online (Sandbox Code Playgroud)

科特林

Handler(Looper.getMainLooper()).post{
    // Work in the UI thread
}
Run Code Online (Sandbox Code Playgroud)

GL