Nie można utworzyć procedury obsługi wewnątrz wątku, który nie wywołał loopera.przygotuj()
Co oznacza poniższy wyjątek; jak mogę go naprawić?
Oto kod:
Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
To jest wyjątek:
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)
28 answers
Dzwonisz z wątku roboczego. Musisz wywołać Toast.makeText()
(i większość innych funkcji zajmujących się interfejsem) z głównego wątku. Na przykład przydałby ci się opiekun.
Poszukaj komunikacji z wątkiem UI w dokumentacji. W skrócie:
// 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();
}
Inne opcje:
Możesz użyć AsyncTask , który działa dobrze dla większości rzeczy działających w tle. Posiada Hooki, które możesz wywołać, aby wskazać postęp, oraz kiedy to się skończy.
Możesz również użyć aktywności .runOnUiThread () .Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-16 16:22:56
Musisz wywołać Toast.makeText(...)
z wątku UI:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
To jest skopiowane z innego (duplikatu) więc odpowiedz .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:24
Aktualizacja - 2016
Najlepszą alternatywą jest użycie RxAndroid
(specyficznych wiązań dla RxJava
) dla P
w MVP
do przejmowania danych.
Zacznij od zwrócenia {[11] } z istniejącej metody.
private Observable<PojoObject> getObservableItems() {
return Observable.create(subscriber -> {
for (PojoObject pojoObject: pojoObjects) {
subscriber.onNext(pojoObject);
}
subscriber.onCompleted();
});
}
Użyj tego obserwowalnego w ten sposób-
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
}
});
}
----------------------------------------------------------------------------------------------------------------------------------
Wiem, że trochę się spóźniłem, ale tutaj idzie. Android zasadniczo działa na dwóch typach wątków a mianowicie UI thread i background thread. Według dokumentacji Androida -
Nie uzyskuj dostępu do zestawu narzędzi interfejsu użytkownika Androida spoza wątku interfejsu aby rozwiązać ten problem, Android oferuje kilka sposobów dostępu do wątku interfejsu użytkownika z innych wątków. Oto lista metod, które mogą pomóc:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Teraz istnieją różne metody rozwiązania tego problemu.
Wyjaśnię to kodem próbka:
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();
LOOPER
Klasa używana do uruchamiania pętli wiadomości dla wątku. Wątki domyślnie do nie mają pętli komunikatów powiązanych z nimi; aby ją utworzyć, wywołaj prepare () w wątku, który ma uruchomić pętlę, a następnie loop () do niech przetwarza wiadomości, dopóki pętla nie zostanie zatrzymana.
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();
}
}
AsyncTask
AsyncTask pozwala na wykonywanie pracy asynchronicznej na Twoim użytkowniku interfejs. Wykonuje blokowanie operacji w wątku roboczym i następnie publikuje wyniki w wątku UI, bez konieczności obsługiwać gwinty i / lub uchwyty samodzielnie.
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
}
}
Handler
Obsługa pozwala na wysyłanie i przetwarzanie wiadomości i obiektów uruchamianych związane z wiadomością wątku.
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;
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-23 06:16:03
Toast.makeText()
powinien być wywoływany tylko z głównego wątku / UI. Looper.getMainLooper () pomaga Ci to osiągnąć:
ANDROID
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
toast.show();
}
});
KOTLIN
Handler(Looper.getMainLooper()).post {
Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT).show()
}
Zaletą tej metody jest to, że można jej używać bez aktywności lub kontekstu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-06 08:12:29
Spróbuj tego, gdy zobaczysz runtimeException z powodu loopera nie przygotowanego przed obsługą.
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
// Run your task here
}
}, 1000 );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-03 13:10:57
Natknąłem się na ten sam problem i oto jak go naprawiłem:
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);
}
Aby utworzyć UIHandler, musisz wykonać następujące czynności:
HandlerThread uiThread = new HandlerThread("UIHandler");
uiThread.start();
uiHandler = new UIHandler((HandlerThread) uiThread.getLooper());
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-06 05:54:41
Powód błędu:
Wątki robocze są przeznaczone do wykonywania zadań w tle i nie możesz pokazywać niczego w interfejsie użytkownika w wątku roboczym, chyba że wywołasz metodę runOnUiThread. Jeśli spróbujesz pokazać cokolwiek w wątku UI bez wywołania runOnUiThread, pojawi się java.lang.RuntimeException
.
Więc, jeśli jesteś w activity
ale wywołujesz Toast.makeText()
z wątku roboczego, zrób to:
runOnUiThread(new Runnable()
{
public void run()
{
Toast toast = Toast.makeText(getApplicationContext(), "Something", Toast.LENGTH_SHORT).show();
}
});
Powyższy kod zapewnia, że wyświetlasz wiadomość Toast w UI thread
, ponieważ jesteś wywołanie wewnątrz metody runOnUiThread
. Więc koniec java.lang.RuntimeException
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-16 07:40:53
To właśnie zrobiłem.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast(...);
}
});
Komponenty wizualne są "zablokowane" na zmiany z zewnętrznych wątków. Tak więc, ponieważ toast pokazuje rzeczy na ekranie głównym, które są zarządzane przez główny wątek, musisz uruchomić ten kod w tym wątku. Mam nadzieję, że to pomoże:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-17 21:40:08
Otrzymywałem ten błąd, dopóki nie wykonałem następujących czynności.
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();
}
}
);
}
I przekształcił to w klasę singletonową:
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();
}
}
);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-12 11:49:43
Wspaniałe rozwiązanie Kotlina:
runOnUiThread {
// Add your ui thread code here
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-22 17:00:17
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(mContext, "Message", Toast.LENGTH_SHORT).show();
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-05 10:13:28
To dlatego, że Toast.makeText() wywołuje z wątku roboczego. Powinno to być wywołanie z głównego wątku UI w ten sposób
runOnUiThread(new Runnable() {
public void run() {
Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-16 14:43:08
Pierwsze wywołanie Looper.prepare()
a następnie wywołanie Toast.makeText().show()
ostatnie wywołanie Looper.loop()
Jak:
Looper.prepare() // to be able to make toast
Toast.makeText(context, "not connected", Toast.LENGTH_LONG).show()
Looper.loop()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-02 11:51:54
Odpowiedź Chicobirda zadziałała. Jedyną zmianą, jakiej dokonałem, było stworzenie Uihandlera, gdzie musiałem zrobić
HandlerThread uiThread = new HandlerThread("UIHandler");
Eclipse odmówił przyjęcia czegokolwiek innego. To chyba ma sens.
Również {[1] } jest wyraźnie zdefiniowaną gdzieś klasą globalną. Nadal nie twierdzę, że rozumiem, jak Android to robi i co się dzieje, ale cieszę się, że to działa. Teraz przejdę do badania i zobaczę, czy mogę zrozumieć, co robi Android i dlaczego trzeba przejść przez wszystkie te obręcze i pętle. Dzięki za pomoc ChicoBird.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-27 03:41:41
Dla użytkownika Rxjava i RxAndroid:
public static void shortToast(String msg) {
Observable.just(msg)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(message -> {
Toast.makeText(App.getInstance(), message, Toast.LENGTH_SHORT).show();
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-05 07:24:13
Natknąłem się na ten sam problem, gdy moje wywołania zwrotne próbowały pokazać okno dialogowe.
Rozwiązałem to za pomocą dedykowanych metod w aktywności - na poziomie instancji - które używają runOnUiThread(..)
public void showAuthProgressDialog() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAuthProgressDialog = DialogUtil.getVisibleProgressDialog(SignInActivity.this, "Loading ...");
}
});
}
public void dismissAuthProgressDialog() {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mAuthProgressDialog == null || ! mAuthProgressDialog.isShowing()) {
return;
}
mAuthProgressDialog.dismiss();
}
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-12 20:48:36
Handler handler2;
HandlerThread handlerThread=new HandlerThread("second_thread");
handlerThread.start();
handler2=new Handler(handlerThread.getLooper());
Teraz handler2 użyje innego wątku do obsługi wiadomości niż główny wątek.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-06 12:26:09
Aby wyświetlić okno dialogowe lub Toster w wątku, najbardziej zwięzłym sposobem jest użycie obiektu aktywności.
Na przykład:
new Thread(new Runnable() {
@Override
public void run() {
myActivity.runOnUiThread(new Runnable() {
public void run() {
myActivity.this.processingWaitDialog = new ProgressDialog(myActivity.this.getContext());
myActivity.this.processingWaitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
myActivity.this.processingWaitDialog.setMessage("abc");
myActivity.this.processingWaitDialog.setIndeterminate(true);
myActivity.this.processingWaitDialog.show();
}
});
expenseClassify.serverPost(
new AsyncOperationCallback() {
public void operationCompleted(Object sender) {
myActivity.runOnUiThread(new Runnable() {
public void run() {
if (myActivity.this.processingWaitDialog != null
&& myActivity.this.processingWaitDialog.isShowing()) {
myActivity.this.processingWaitDialog.dismiss();
myActivity.this.processingWaitDialog = null;
}
}
}); // .runOnUiThread(new Runnable()
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-26 19:07:59
Używając lambda:
activity.runOnUiThread(() -> Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-18 13:30:18
Coroutine zrobi to doskonale]}
CoroutineScope(Job() + Dispatchers.Main).launch {
Toast.makeText(context, "yourmessage",Toast.LENGTH_LONG).show()}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-15 04:35:49
Toast, AlertDialogs musi działać na wątku UI, możesz użyć Asynctask , aby poprawnie używać ich w rozwoju Androida.ale w niektórych przypadkach musimy dostosować czas out, więc używamy Threads , ale w wątkach nie możemy używać Toast,Alertdialogs jak używamy w AsyncTask.So potrzebujemy oddzielnego Handlera dla tych popup.
public void onSigned() {
Thread thread = new Thread(){
@Override
public void run() {
try{
sleep(3000);
Message message = new Message();
message.what = 2;
handler.sendMessage(message);
} catch (Exception e){
e.printStackTrace();
}
}
};
thread.start();
}
W powyższym przykładzie chcę spać mój wątek w 3sec i po chcę pokazać wiadomość Toast,za to w Twoim mainthread Obsługa implementacji.
handler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what){
case 1:
Toast.makeText(getActivity(),"cool",Toast.LENGTH_SHORT).show();
break;
}
super.handleMessage(msg);
}
};
Użyłem tutaj switch case, ponieważ jeśli chcesz pokazać inny komunikat w ten sam sposób, możesz użyć switch case w klasie obsługi...mam nadzieję, że to ci pomoże
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-07 16:53:53
Zwykle dzieje się tak, gdy coś w głównym wątku jest wywoływane z dowolnego wątku tła. Spójrzmy na przykład, na przykład.
private class MyTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
textView.setText("Any Text");
return null;
}
}
W powyższym przykładzie ustawiamy tekst na textview, który znajduje się w głównym wątku interfejsu z metody doInBackground (), która działa tylko na wątku roboczym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-20 06:15:45
Miałem ten sam problem i naprawiłem go po prostu umieszczając Toast w onpostexecute() override funkcji Asynctask i zadziałało.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-09 01:16:50
Musisz utworzyć toast na wątku UI. Poniższy przykład.
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "YOUR_MESSAGE", Toast.LENGTH_SHORT).show();
}
});
Aby wyświetlić wiadomość Toast, zapoznaj się z tym artykułem
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-27 05:26:45
Oto rozwiązanie dla Kotlina za pomocą Coroutine:
Rozszerz swoją klasę za pomocą CoroutineScope przez MainScope ():
class BootstrapActivity : CoroutineScope by MainScope() {}
Następnie po prostu zrób to:
launch {
// whatever you want to do in the main thread
}
Nie zapomnij dodać zależności dla coroutine:
org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}
org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.kotlinCoroutines}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-13 21:07:20
Java 8
new Handler(Looper.getMainLooper()).post(() -> {
// Work in the UI thread
};
Kotlin
Handler(Looper.getMainLooper()).post{
// Work in the UI thread
}
GL
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-15 10:10:56
Tworzenie obsługi poza wątkiem
final Handler handler = new Handler();
new Thread(new Runnable() {
@Override
public void run() {
try{
handler.post(new Runnable() {
@Override
public void run() {
showAlertDialog(p.getProviderName(), Token, p.getProviderId(), Amount);
}
});
}
}
catch (Exception e){
Log.d("ProvidersNullExp", e.getMessage());
}
}
}).start();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-27 06:09:02
Używam poniższego kodu do wyświetlania wiadomości z nie głównego wątku "context",
@FunctionalInterface
public interface IShowMessage {
Context getContext();
default void showMessage(String message) {
final Thread mThread = new Thread() {
@Override
public void run() {
try {
Looper.prepare();
Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
Looper.loop();
} catch (Exception error) {
error.printStackTrace();
Log.e("IShowMessage", error.getMessage());
}
}
};
mThread.start();
}
}
Następnie użyj jako:
class myClass implements IShowMessage{
showMessage("your message!");
@Override
public Context getContext() {
return getApplicationContext();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-08 07:15:05