Невозможно создать обработчик внутри потока, который не вызвал Looper.prepare ()

1093

Что означает следующее исключение; как я могу это исправить?

Это код:

Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);

Это исключение:

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)
6
  • 13
    проверьте эту библиотеку compile 'com.shamanland:xdroid-toaster:0.0.5', она не требует runOnUiThread()или Contextпеременной, все рутины пропали! просто вызовите Toaster.toast(R.string.my_msg);вот пример: github.com/shamanland/xdroid-toaster-exampleOleksii K. 17 июля '14 в 13: 132014-07-17 13:13
  • 152
    Что за глупое сообщение об ошибке! Это могло быть так просто, как - невозможно вызвать это из потока, не относящегося к пользовательскому интерфейсу, как это делается, когда к представлениям прикасаются из потока, не относящегося к пользовательскому интерфейсу. Dheeraj Bhaskar 25 авг.
  • 14
    Для тех, кто получает одно и то же сообщение об исключении из другого кода: сообщение об исключении означает, что вы вызываете код через поток, который не подготовил Looper. Обычно это означает, что вы не вызываете if из потока пользовательского интерфейса, но должны (случай OP) - обычный поток не подготавливает Looper, но поток пользовательского интерфейса всегда делает. Helin Wang 14 июля '15 в 21: 482015-07-14 18:48
  • 1
    @OleksiiKropachov, реализация упомянутой вами библиотеки очень похожа на выполнение runOnUiThread (). Helin Wang 14 июля '15 в 22: 212015-07-14 19:21
  • 1
    да, но это очень полезная оберткаOleksii K. 14 июля '15 в 22: 232015-07-14 19:23
775

Вы вызываете его из рабочего потока. Вам необходимо вызвать Toast.makeText()(и большинство других функций, связанных с пользовательским интерфейсом) из основного потока. Например, вы можете использовать обработчик.

Посмотрите в документации Связь с потоком пользовательского интерфейса . В двух словах:

// 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();
}

Другие варианты:

Вы могли бы использовать Activity.runOnUiThread(). Несложно, если у вас есть Activity:

@WorkerThread
void workerThread() {
    myActivity.runOnUiThread(() -> {
        // This is where your UI code goes.
    }
}

Вы также можете отправлять сообщения в главный лупер. Это отлично работает, если все, что у вас есть, - это файл Context.

@WorkerThread
void workerThread() {
    ContextCompat.getMainExecutor(context).execute(()  -> {
        // This is where your UI code goes.
    }
}

Устарело:

Вы можете использовать AsyncTask , который хорошо работает для большинства задач , выполняемых в фоновом режиме. У него есть хуки, которые вы можете вызывать, чтобы указать прогресс и когда он будет готов.

Это удобно, но при неправильном использовании может происходить утечка контекста. Он официально устарел, и вам больше не следует его использовать.

8
  • как насчет исходной проблемы (это не было связано с AlertDialog)? Ivan G. 05 июля '11 в 21: 292011-07-05 18:29
  • 5
    Просто добавляю свои два цента к тому, что сказал Клегги. Было бы предпочтительнее предоставить краткую демонстрацию того, что вы имеете в виду (какой бы надуманной она ни была), поскольку закодированный пример часто говорит сам за себя. cdata 01 марта '13 в 22:55
  • 5
    полный технический ответ см. на prasanta-paul.blogspot.kr/2013/09/…tony9099 26 сен.
  • 3
    Почти во всех языках программирования AFAIK, которые поддерживают графический интерфейс, если вы обновляете / меняете / отображаете / взаимодействуете с графическим интерфейсом напрямую, это должно выполняться в основном потоке программы. Ahmed 18 апр '14 в 0:50
  • (and most other functions dealing with the UI)Пример функции пользовательского интерфейса, которую можно использовать в фоновом режиме, android.support.design.widget.Snackbar- ее функциональность не уменьшается, если она не вызывается из потока пользовательского интерфейса. Scruffy 31 июл.
897

Вам нужно позвонить Toast.makeText(...)из потока пользовательского интерфейса:

activity.runOnUiThread(new Runnable() {
  public void run() {
    Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
  }
});

Это скопировано из другого (дублирующего) ответа SO .

2
  • 13
    Отличный ответ. Это меня на какое-то время смутило. Замечу, что эта активность мне не понадобилась. перед runOnUiThread. Cen92 11 мая '14 в 12:24
  • @ Cen92 на самом деле вам нужно> _ <. runOnUiThread - это метод действия. Eugene Troyanskii 19 июл в 18:18
454

ОБНОВЛЕНИЕ - 2016

Лучшая альтернатива - использовать RxAndroid(определенные привязки для RxJava), чтобы Pin MVPбрал на себя ответственность за данные.

Начните с возврата Observableиз существующего метода.

private Observable<PojoObject> getObservableItems() {
    return Observable.create(subscriber -> {

        for (PojoObject pojoObject: pojoObjects) {
            subscriber.onNext(pojoObject);
        }
        subscriber.onCompleted();
    });
}

Используйте это Observable вот так -

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
    }
});
}

-------------------------------------------------- -------------------------------------------------- ------------------------------

Я знаю, что немного опаздываю, но начнем. Android в основном работает с двумя типами потоков, а именно с потоком пользовательского интерфейса и фоновым потоком . Согласно документации Android -

Do not access the Android UI toolkit from outside the UI thread to fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:

Activity.runOnUiThread(Runnable)  
View.post(Runnable)  
View.postDelayed(Runnable, long)

Сейчас есть разные методы решения этой проблемы.

Я объясню это на примере кода:

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

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 prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

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 allows you to perform asynchronous work on your user interface. It performs the blocking operations in a worker thread and then publishes the results on the UI thread, without requiring you to handle threads and/or handlers yourself.

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
    }
}

Обработчик

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.

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;
    }
});
8
  • 8
    Это именно то , что я искал. Особенно первый пример сrunOnUiThreadNavin 3 ноя '13 в 2:19
  • 6
    Спасибо, 5 лет программирования Android, и я никогда не знал, Viewтакже есть методы post(Runnable)и postDelayed(Runnable, long)! Столько хендлеров напрасно. :)Fenix Voltres 15 апр '15 в 9:13
  • для тех, кого смущает пример Handler: к какому потоку привязан «new Handler (callback)»? Он привязан к потоку, создавшему обработчик. Helin Wang 14 июля '15 в 21: 442015-07-14 18:44
  • 1
    Почему это лучшая альтернатива ? IgorGanapolsky 2 фев '17 в 22:50
  • Я использую doInBackground и хочу вернуть ArrayList, но всегда получаю сообщение об ошибке: не могу создать обработчик внутри потока, который не вызвал Looper.prepare (). Смотрите, это мой вопрос stackoverflow.com/questions/45562615/… но я не могу получить решение из этого ответа здесьWeSt 08 авг.
164

Toast.makeText()должен вызываться только из потока Main / UI. Looper.getMainLooper () поможет вам в этом:

ANDROID

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
        toast.show();
    }
});

КОТЛИН

Handler(Looper.getMainLooper()).post {
        Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT).show()
}

Преимущество этого метода заключается в том, что вы можете запускать код пользовательского интерфейса без действия или контекста.

5
  • 3
    Спасибо, другие ответы не помогли мне. Я использую библиотечную сахарную запись для управления постоянством. А внутри у меня нет активности. Но это прекрасно работаетcabaji99 02 окт.
  • 1
    Не забудьте toast.show () ;-)dcarl661 5 фев в 21:57
  • @ dcarl661, спасибо, что заметили. исправление сделаноAyaz Alifov 18 февраля в 11:05
  • @AyazAlifov Вы говорите, что "контекст не требуется", так на что ссылается mContext? akhil nair 7 июня в 11:23
  • 1
    Привет @akhilnair. Контекст не требуется для запуска кода Android в потоке Main / UI. Основной поток / поток пользовательского интерфейса может содержать любой код. В этом конкретном примере есть метод Toast, для реализации которого требуется Context. Ayaz Alifov 7 июня в 17:42
97

Попробуйте это, когда вы видите runtimeException из-за того, что Looper не подготовлен перед обработчиком.

Handler handler = new Handler(Looper.getMainLooper()); 

handler.postDelayed(new Runnable() {
  @Override
  public void run() {
  // Run your task here
  }
}, 1000 );
3
  • Обработчик - это абстрактный класс. это не компилируетсяStealth Rabbi 11 дек.
  • 2
    @StealthRabbi импорта Handler из правильно имен т.е.android.os.HandlerNightFury 17 фев '15 в 7:58
  • Возможно, проблема не в этом. Петлитель может не существовать в вызывающем классе, точка. IgorGanapolsky 2 фев '17 в 22:51
43

Я столкнулся с той же проблемой, и вот как я ее исправил:

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);
}

Чтобы создать UIHandler, вам необходимо выполнить следующее:

    HandlerThread uiThread = new HandlerThread("UIHandler");
    uiThread.start();
    uiHandler = new UIHandler((HandlerThread) uiThread.getLooper());

Надеюсь это поможет.

2
  • Я пытался использовать ваш код, но я потерял и не знаю, как позвонить из onCreate methodили из AsyncTask в моей ситуации, не могли бы вы опубликовать весь код, чтобы узнать, как все работает? Nick Kahn 29 фев '12 в 3:41
  • 2
    Не следует ли читать эту последнюю строчку uiHandler = new UIHandler(uiThread.getLooper()); ? Beer Me 9 сен '13 в 16:42
39

Причина ошибки:

Рабочие потоки предназначены для выполнения фоновых задач, и вы не можете ничего показать в пользовательском интерфейсе внутри рабочего потока, если не вызовете такой метод, как runOnUiThread . Если вы попытаетесь показать что-либо в потоке пользовательского интерфейса без вызова runOnUiThread, появится файл java.lang.RuntimeException.

Итак, если вы activityзвоните Toast.makeText()из рабочего потока, сделайте следующее:

runOnUiThread(new Runnable() 
{
   public void run() 
   {
      Toast toast = Toast.makeText(getApplicationContext(), "Something", Toast.LENGTH_SHORT).show();    
   }
}); 

Приведенный выше код гарантирует, что вы показываете сообщение Toast в, UI threadпоскольку вы вызываете его внутри runOnUiThreadметода. Так что больше не надо java.lang.RuntimeException.

0
23

вот что я сделал.

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast(...);
    }
});

Визуальные компоненты «заблокированы» для изменений из внешних потоков. Итак, поскольку тост показывает материал на главном экране, которым управляет основной поток, вам необходимо запустить этот код в этом потоке. Надеюсь, это поможет:)

2
  • Я использовал тот же метод. Однако оставляет ли это возможность утечек, потому что анонимный внутренний класс Runnable будет содержать неявную ссылку на Activity? Peter G. Williams 27 мая '20 в 17:52
  • 1
    Это замечательный момент :) просто используйте getApplicationContext () или что-то в этом роде, на всякий случай. хотя у меня никогда не было проблем с этим кодом, о котором я знаюeiran 01 июн.
22

Я получал эту ошибку, пока не сделал следующее.

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();
            }
        }
    );
}

И превратил это в одноэлементный класс:

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();
                }
            }
        );
    }

}
4
  • Где вы используете тостер ? В вашем первом фрагменте он не используется ...IgorGanapolsky 2 фев '17 в 23:05
  • 1
    это был класс удобства, который я использовал Toaster.INSTANCE.postMessage(ResourceUtils.getString(R.string.blah));(долго, я знаю! мы сократили его позже), хотя я уже давно не использую тостыEpicPandaForce 2 фев '17 в 23:12
  • Так что же ApplicationHolder.INSTANCEоценивать? IgorGanapolsky 3 фев '17 в 14:23
  • Статическая переменная CustomApplicationустановлена CustomApplication.onCreate(), учитывая, что приложение всегда существует, пока существует процесс, этот контекст можно использовать глобальноEpicPandaForce 3 фев '17 в 14:23
14

Замечательное решение Kotlin:

runOnUiThread {
    // Add your ui thread code here
}
1
  • 5
    runOnUiThreadявляется частью Activity, т. е.activity?.runOnUiThread { ... }AtomicStrongForce 20 мая '19 в 3:18
12
 runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(mContext, "Message", Toast.LENGTH_SHORT).show();
            }
        });
1
  • 2
    Это сработало для меня, и я использую лямбдаrunOnUiThread(() -> { Toast toast = Toast.makeText(getApplicationContext(), "Message", Toast.LENGTH_SHORT); toast.show(); });Black_Zerg 06 янв.
11

Это потому, что Toast.makeText () вызывается из рабочего потока. Это должен быть вызов из основного потока пользовательского интерфейса, подобный этому

runOnUiThread(new Runnable() {
      public void run() {
        Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
      }
 });
0
9

первый звонок, Looper.prepare()а затем звонок Toast.makeText().show()последний звонок, Looper.loop()например:

Looper.prepare() // to be able to make toast
Toast.makeText(context, "not connected", Toast.LENGTH_LONG).show()
Looper.loop()
2
  • 1
    Почему этот ответ недооценен? DkPathak 22 апр '20 в 10:59
  • Я не знаю о текущем использовании, но это спасло меня при использовании файла jar в исполняемом файле, который содержал внутреннюю активность. John Lord 29 июня '20 в 18:39
8

Ответ ChicoBird сработал для меня. Единственное изменение, которое я внес, - это создание UIHandler, в котором мне нужно было сделать

HandlerThread uiThread = new HandlerThread("UIHandler");

Eclipse отказался принимать что-либо еще. Полагаю, это имеет смысл.

Также uiHandlerочевидно, что где-то определен глобальный класс. Я до сих пор не утверждаю, что понимаю, как Android это делает и что происходит, но я рад, что это работает. Теперь я перейду к его изучению и посмотрю, смогу ли я понять, что делает Android, и почему нужно проходить через все эти петли и петли. Спасибо за помощь ChicoBird.

5

Для пользователей Rxjava и RxAndroid:

public static void shortToast(String msg) {
    Observable.just(msg)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(message -> {
                Toast.makeText(App.getInstance(), message, Toast.LENGTH_SHORT).show();
            });
}
1
  • Эти скобки не нужныBorja 23 окт.
4

Я столкнулся с той же проблемой, когда мои обратные вызовы пытались показать диалог.

Я решил это с помощью специальных методов в Activity - на уровне члена экземпляра Activity - которые используют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();
        }
    });
}
2
Handler handler2;  
HandlerThread handlerThread=new HandlerThread("second_thread");
handlerThread.start();
handler2=new Handler(handlerThread.getLooper());

Теперь handler2 будет использовать другой поток для обработки сообщений, нежели основной поток.

2

Coroutine отлично с этим справится

CoroutineScope(Job() + Dispatchers.Main).launch {
                        Toast.makeText(context, "yourmessage",Toast.LENGTH_LONG).show()}
0
1

Чтобы отобразить диалоговое окно или тостер в потоке, наиболее кратким способом является использование объекта Activity.

Например:

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()
...
1

Использование лямбды:

activity.runOnUiThread(() -> Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show());
0

Тост, AlertDialogs должна работать на UI потоке, вы можете использовать AsyncTask использовать их должным образом в Android development.but некоторых случаях нам нужно настроить тайм - аутов, поэтому мы используем темы , но в потоках мы не можем использовать Toast, Alertdialogs как мы используем в AsyncTask, поэтому нам нужен отдельный обработчик для всплывающих окон .

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();
}

В приведенном выше примере я хочу засыпать свой поток через 3 секунды и после того, как я хочу показать сообщение Toast, для этого в вашем обработчике реализации основного потока .

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);
       }
};

Я использовал здесь случай переключателя, потому что, если вам нужно показать другое сообщение таким же образом, вы можете использовать случай переключателя в классе Handler ... надеюсь, это поможет вам

0

Обычно это происходит, когда что-то в основном потоке вызывается из любого фонового потока. Давайте, например, рассмотрим пример.

private class MyTask extends AsyncTask<Void, Void, Void> {


@Override
protected Void doInBackground(Void... voids) {
        textView.setText("Any Text");
        return null;
    }
}

В приведенном выше примере мы устанавливаем текст в текстовом представлении, которое находится в основном потоке пользовательского интерфейса, из метода doInBackground (), который работает только с рабочим потоком.

0

У меня была такая же проблема, и я исправил ее, просто поместив Toast в функцию переопределения onPostExecute () Asynctask <>, и это сработало.

0

Вам нужно создать тост в потоке пользовательского интерфейса. Найдите пример ниже.

runOnUiThread(new Runnable() {
  public void run() {
    Toast.makeText(activity, "YOUR_MESSAGE", Toast.LENGTH_SHORT).show();
  }
});

Для отображения сообщения Toast обратитесь к этой статье

0
0

Вот решение для Kotlin с использованием Coroutine:

Расширьте свой класс с помощью CoroutineScope с помощью MainScope ():

class BootstrapActivity :  CoroutineScope by MainScope() {}

Тогда просто сделайте это:

launch {
        // whatever you want to do in the main thread
    }

Не забудьте добавить зависимости для сопрограммы:

org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}
org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.kotlinCoroutines}
1
  • Или просто launch(Dispatchers.Main) { ... }. CoolMind 4 авг.
0

Java 8

new Handler(Looper.getMainLooper()).post(() -> {
    // Work in the UI thread

}; 

Котлин

Handler(Looper.getMainLooper()).post{
    // Work in the UI thread
}

GL

0

Создать обработчик вне потока

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();
0

У меня та же проблема, и это то, что теперь отлично работает со мной, в качестве примера это мой код для выполнения задачи в фоновом режиме и потока пользовательского интерфейса и посмотрите на петлитель, как используется

new Thread(new Runnable() {
              @Override
              public void run() {
              Looper.prepare();
                                
                                // your Background Task here

                runOnUiThread(new Runnable() {
                  @Override
                  public void run() {

                                // update your UI here      
                                
                  Looper.loop();
                                  }
                });
              }
            }).start();

я надеюсь, что это поможет вам или кому-то еще

0

Недавно я столкнулся с этой проблемой - это произошло из-за того, что я пытался вызвать функцию, которая должна была выполнять некоторые элементы пользовательского интерфейса из конструктора. Удаление инициализации из конструктора решило проблему для меня.

-2

Я использую следующий код, чтобы показать сообщение из "контекста" не основного потока,

@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();
    }
}

затем используйте следующее:

class myClass implements IShowMessage{

  showMessage("your message!");
 @Override
    public Context getContext() {
        return getApplicationContext();
    }
}
0