[英]How do you display a Toast from a background thread on Android?
您可以通過從您的線程調用Activity
的runOnUiThread
方法來實現:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
我喜歡在我的活動中有一個名為showToast
的方法,我可以從任何地方調用它...
public void showToast(final String toast)
{
runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}
然后,我最常從MyActivity
在任何像這樣的線程上調用它......
showToast(getString(R.string.MyMessage));
這與其他答案類似,但是針對新的可用 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();
}
});
}
}
一種幾乎適用於任何地方(包括沒有Activity
或View
)的方法是將Handler
抓取到主線程並顯示 Toast:
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
,包括Service
和Application
。
像這樣或這樣,帶有一個顯示Toast
的Runnable
。 即,
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();
}
有時,您必須從另一個Thread
向 UI 線程發送消息。 當您無法在 UI 線程上執行網絡/IO 操作時,就會發生這種情況。
下面的示例處理這種情況。
Runnable
。 因此,將您的Runnable
到HandlerThread
上的處理程序Runnable
獲取結果並將其發送回 UI 線程並顯示Toast
消息。解決方案:
HandlerThread
使用Looper創建一個處理程序: requestHandler
responseHandler
並覆蓋handleMessage
方法requestHandler
上post
一個Runnable
任務Runnable
任務中,在responseHandler
上調用sendMessage
sendMessage
結果在responseHandler
調用handleMessage
。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-and-why-you-should-be-using-them-in-your-android-apps
handler.sendMessage();
post()
方法handler.post();
runOnUiThread()
view.post()
您可以使用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();
}
它在您的線程中被調用。 Context 可能是Activity.getContext()
從你必須展示 toast 的Activity
獲取。
我根據 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();
}
});
}
對我來說效果很好。
帶有 runOnUiThread 的 Kotlin 代碼
runOnUiThread(
object : Runnable {
override fun run() {
Toast.makeText(applicationContext, "Calling from runOnUiThread()", Toast.LENGTH_SHORT)
}
}
)
我遇到了同樣的問題:
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();
}
});
有效。
爪哇11:
var handler = new Handler(Looper.getMainLooper);
handler.post(() -> Toast.makeText(your_context, "Hi!", Toast.LENGTH_SHORT).show());
不過,在 Java 8 中可以使用 Lambda。 var
是在 Java 11 中引入的。
與此處幾乎所有答案相反, Toast#makeText
和Toast#show
不必在 UI 線程上運行。 唯一的要求是它在一個名為Looper#prepare
的線程上運行。
這是因為 toast 是由操作系統處理和呈現的,而不是應用程序。 在內部, Toast#show
調用系統服務以將 toast 排隊。
這意味着下面的代碼是有效的
private static class MyThread extends Thread {
public Handler handler;
@Override
public void run() {
Looper.prepare();
handler = new Handler(Looper.myLooper()) {
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
Looper.loop()
}
}
final private MyThread t = new MyThread();
// start and wait for t to start looping
private void onClick() {
t.handler.post(() -> Toast.makeText(this, "this works", Toast.LENGTH_SHORT).show());
}
onCreate 中的方法:
private void toastPublic(final String message){
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
Toast.makeText(getBaseContext(),""+message,
4 /*Toast.LENGTH_SHORT*/).show();
}});
}
下一步:在線程內部使用
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.