Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();
在子線程裏創建 Toast
時出現報錯:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare().
在沒有調用Looper.prepare()
的線程裏,無法創建handler
。
原因是修改 UI 需要在主線程裏。
1. Thread
因爲線程需要 Looper
來循環處理消息,但是子線程中默認是沒有 Looper
的,查看一下 Looper
的源碼,類註釋如下:
/**
* Class used to run a message loop for a thread. Threads by default do
* not have a message loop associated with them; to create one, call
* {@link #prepare} in the thread that is to run the loop, and then
* {@link #loop} to have it process messages until the loop is stopped.
*
* <p>Most interaction with a message loop is through the
* {@link Handler} class.
*
* <p>This is a typical example of the implementation of a Looper thread,
* using the separation of {@link #prepare} and {@link #loop} to create an
* initial Handler to communicate with the Looper.
*
* <pre>
* 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();
* }
* }</pre>
*/
註釋裏說明了線程默認是沒有 Looper
的,需要在線程裏手動調用 Looper.prepare()
來創建 Looper
,並且調用 Looper.loop()
來遍歷消息。並且還附帶了一個例子。
所以我們直接按照官方給的例子調用即可:
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();
2. Handler
如果直接在子線程裏創建 new Handler()
,也會報同樣的錯誤,因爲子線程默認是沒有 Looper 的。
可以使用 public Handler(Looper looper)
構造方法創建 Handler
,傳遞主線程的 Looper
:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();
}
});
3. runOnUiThread
如果是在 Activity
裏,可以使用 runOnUiThread
:
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();
}
});
或者
if (mContext instanceof Activity) {
((Activity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();
}
});