Як я можу відобразити повідомлення з Toast із потоку?
Як я можу відобразити повідомлення з Toast із потоку?
Відповіді:
Ви можете зробити це, зателефонувавши методу Activity
' runOnUiThread
із своєї нитки:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
Thread
посилання об'єкта до Activity
в Activity
«з onResume
. Зніміть його в Activity
's onPause
. Робіть обидва під synchronized
замком, що Activity
і Thread
поважають.
Activity
примірника, ви можете використовувати простий клас помічників, дивіться тут: stackoverflow.com/a/18280318/1891118
MyActivity.this.runOnUiThread()
працює чудово зсередини внутрішнього Thread
/ AsyncTask
.
Мені подобається, що у своїй діяльності є метод, під назвою showToast
якого я можу зателефонувати з будь-якого місця ...
public void showToast(final String toast)
{
runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}
Тоді я найчастіше називаю це зсередини MyActivity
на будь-якій такій темі ...
showToast(getString(R.string.MyMessage));
Це схоже на інші відповіді, однак оновлені для нових доступних apis та набагато чистіших. Крім того, не передбачає, що ви перебуваєте в контексті активності.
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
до головної нитки і показати тост:
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
.
Як це чи це , з a, Runnable
що показує Toast
. А саме,
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
до потоку інтерфейсу користувача. Цей тип сценарію виникає, коли ви не можете виконати операції Network / IO на потоці інтерфейсу.
Нижче на прикладі обробляється цей сценарій.
Runnable
по потоку інтерфейсу користувача Тож опублікуйте свій Runnable
обробник наHandlerThread
Runnable
і відправте його назад у потік інтерфейсу та покажіть Toast
повідомлення.Рішення:
HandlerThread
:requestHandler
responseHandler
та замініть їїhandleMessage
методpost
Runnable
задача поrequestHandler
Runnable
завдання, виклик sendMessage
наresponseHandler
sendMessage
результат виклику handleMessage
в responseHandler
.Message
та обробити його, оновити інтерфейс користувачаПриклад коду:
/* 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-і-чому-ви-повинні-використовуєте-їм-у-ваших андроїд
Ви можете використовувати 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();
}
і це називається у вашій нитці. Контекст може Activity.getContext()
отримуватись від того, що Activity
ви повинні показати тост.
Я зробив такий підхід, грунтуючись на відповіді міжард:
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();
}
});
}
Добре працював для мене.
Я зіткнувся з тією ж проблемою:
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();
}
});
це спрацювало.