How do you display a Toast from a background thread on Android?
AndroidMultithreadingAndroid ToastAndroid Problem Overview
How can I display Toast messages from a thread?
Android Solutions
Solution 1 - Android
You can do it by calling an Activity
's runOnUiThread
method from your thread:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
Solution 2 - Android
I like to have a method in my activity called showToast
which I can call from anywhere...
public void showToast(final String toast)
{
runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}
I then most frequently call it from within MyActivity
on any thread like this...
showToast(getString(R.string.MyMessage));
Solution 3 - Android
This is similar to other answers, however updated for new available apis and much cleaner. Also, does not assume you're in an Activity Context.
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();
}
});
}
}
Solution 4 - Android
One approach that works from pretty much anywhere, including from places where you don't have an Activity
or View
, is to grab a Handler
to the main thread and show the 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();
}
});
}
The advantage of this approach is that it works with any Context
, including Service
and Application
.
Solution 5 - Android
Like this or this, with a Runnable
that shows the Toast
.
Namely,
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();
}
Solution 6 - Android
Sometimes, you have to send message from another Thread
to UI thread. This type of scenario occurs when you can't execute Network/IO operations on UI thread.
Below example handles that scenario.
- You have UI Thread
- You have to start IO operation and hence you can't run
Runnable
on UI thread. So post yourRunnable
to handler onHandlerThread
- Get the result from
Runnable
and send it back to UI thread and show aToast
message.
Solution:
- Create a HandlerThread and start it
- Create a Handler with Looper from
HandlerThread
:requestHandler
- Create a Handler with Looper from Main Thread:
responseHandler
and overridehandleMessage
method post
aRunnable
task onrequestHandler
- Inside
Runnable
task, callsendMessage
onresponseHandler
- This
sendMessage
result invocation ofhandleMessage
inresponseHandler
. - Get attributes from the
Message
and process it, update UI
Sample code:
/* 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);
}
Useful articles:
handlerthreads-and-why-you-should-be-using-them-in-your-android-apps
Solution 7 - Android
- Get UI Thread Handler instance and use
handler.sendMessage();
- Call
post()
methodhandler.post();
runOnUiThread()
view.post()
Solution 8 - Android
You can use Looper
to send Toast
message. Go through this link for more details.
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();
}
and it is called in your thread. Context may be Activity.getContext()
getting from the Activity
you have to show the toast.
Solution 9 - Android
I made this approach based on mjaggard answer:
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();
}
});
}
Worked well for me.
Solution 10 - Android
Kotlin Code with runOnUiThread
runOnUiThread(
object : Runnable {
override fun run() {
Toast.makeText(applicationContext, "Calling from runOnUiThread()", Toast.LENGTH_SHORT)
}
}
)
Solution 11 - Android
I encountered the same problem:
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.
Before: onCreate function
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
}
});
thread.start();
After: onCreate function
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
}
});
it worked.
Solution 12 - Android
java 11:
var handler = new Handler(Looper.getMainLooper);
handler.post(() -> Toast.makeText(your_context, "Hi!", Toast.LENGTH_SHORT).show());
Lambdas are available in java 8 though. var
is introduced in java 11.