Pertanyaan Tidak dapat membuat handler di dalam thread yang tidak disebut Looper.prepare ()


Apa arti pengecualian berikut ini; bagaimana saya bisa memperbaikinya?

Ini kodenya:

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

Ini adalah pengecualian:

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)

767
2017-10-06 17:18


asal


Jawaban:


Anda menyebutnya dari utas pekerja. Anda perlu menelepon Toast.makeText() (dan sebagian besar fungsi lain yang berhubungan dengan UI) dari dalam utas utama. Anda bisa menggunakan handler, misalnya.

Lihatlah Berkomunikasi dengan Benang UI dalam dokumentasi. Pendeknya:

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

Pilihan lain:

Anda bisa menggunakan AsyncTask, yang berfungsi dengan baik untuk kebanyakan hal yang berjalan di latar belakang. Ini memiliki kait yang dapat Anda panggil untuk menunjukkan kemajuan, dan ketika itu selesai.

Anda juga bisa menggunakan Activity.runOnUiThread ().


541
2017-10-06 17:20



Anda perlu menelepon Toast.makeText(...) dari utas UI:

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

Ini copy-paste dari jawaban SO lain (duplikat).


750
2018-03-22 02:11



UPDATE - 2016

Alternatif terbaik adalah menggunakan RxAndroid (khusus untuk binding RxJava) Untuk P di MVP untuk mengambil alih data.

Mulai dengan kembali Observable dari metode Anda yang ada.

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

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

Gunakan ini dapat diamati seperti ini -

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

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

Saya tahu saya agak terlambat tapi begini. Android pada dasarnya bekerja pada dua jenis benang yaitu Utas UI dan utas latar belakang. Menurut dokumentasi android -

Jangan akses toolkit UI Android dari luar utas UI untuk memperbaiki masalah ini, Android menawarkan beberapa cara untuk mengakses utas UI dari utas lainnya. Berikut ini daftar metode yang dapat membantu:

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

Sekarang ada berbagai metode untuk memecahkan masalah ini.

Saya akan menjelaskannya dengan contoh kode:

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

Kelas yang digunakan untuk menjalankan loop pesan untuk utas. Threads secara default lakukan   tidak memiliki lingkaran pesan yang terkait dengan mereka; untuk membuatnya, panggil   siapkan () di thread yang menjalankan loop, dan kemudian loop () ke   memilikinya memproses pesan hingga loop berhenti.

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 memungkinkan Anda untuk melakukan pekerjaan asynchronous pada pengguna Anda   antarmuka. Ini melakukan operasi pemblokiran di thread pekerja dan   kemudian menerbitkan hasil pada utas UI, tanpa mengharuskan Anda   menangani utas dan / atau pawang sendiri.

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

A Handler memungkinkan Anda untuk mengirim dan memproses objek Message and Runnable   terkait dengan MessageQueue dari benang.

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

412
2018-06-02 19:32



Coba ini, ketika Anda melihat runtimeException karena Looper tidak siap sebelum pawang.

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

handler.postDelayed(new Runnable() {
  @override
  void run() {
  // Run your task here
  }
}, 1000 );

65
2018-06-13 07:26



Saya mengalami masalah yang sama, dan inilah cara saya memperbaikinya:

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

Untuk membuat UIHandler, Anda harus melakukan hal berikut:

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

Semoga ini membantu.


39
2017-11-30 19:35



Alasan untuk kesalahan:

Worker threads dimaksudkan untuk melakukan tugas-tugas latar belakang dan Anda tidak dapat menampilkan apa pun di UI dalam utas pekerja kecuali Anda memanggil metode seperti runOnUiThread. Jika Anda mencoba menampilkan apa pun pada utas UI tanpa memanggil runOnUiThread, akan ada a java.lang.RuntimeException.

Jadi, jika Anda berada di suatu activity tetapi menelepon Toast.makeText() dari utas pekerja, lakukan ini:

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

Kode di atas memastikan Anda menunjukkan pesan Toast dalam a UI thread karena Anda memanggilnya di dalam runOnUiThread metode. Jadi tidak lagi java.lang.RuntimeException.


32
2018-05-16 07:40



Toast.makeText() harus dipanggil dari utas Main / UI. Looper.getMainLooper() membantu Anda mencapainya:

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

Keuntungan dari metode ini adalah Anda dapat menggunakannya dalam kelas non-Aktivitas (atau tanpa Konteks) juga.


25
2018-01-24 00:27



Saya mendapatkan kesalahan ini sampai saya melakukan hal berikut.

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

Dan membuat ini menjadi kelas tunggal:

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

}

21
2017-11-20 13:09



itulah yang saya lakukan.

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

Komponen-komponen visual "dikunci" untuk berubah dari benang luar. Jadi, karena roti panggang menunjukkan hal-hal di layar utama yang dikelola oleh utas utama, Anda harus menjalankan kode ini di utas itu. Semoga bermanfaat :)


17
2018-03-16 16:13



Ini karena Toast.makeText () memanggil dari utas pekerja. Seharusnya panggilan dari utas UI utama seperti ini

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

8
2018-05-15 08:25



Jawabannya oleh ChicoBird bekerja untuk saya. Satu-satunya perubahan yang saya buat adalah dalam penciptaan UIHandler di mana saya harus melakukannya

HandlerThread uiThread = new HandlerThread("UIHandler");

Eclipse menolak menerima yang lain. Masuk akal saya kira.

Juga uiHandler jelas kelas global yang didefinisikan di suatu tempat. Saya masih tidak mengklaim untuk memahami bagaimana Android melakukan ini dan apa yang sedang terjadi tetapi saya senang itu berhasil. Sekarang saya akan melanjutkan untuk mempelajarinya dan melihat apakah saya dapat memahami apa yang Android lakukan dan mengapa seseorang harus melalui semua lingkaran dan loop ini. Terima kasih atas bantuan ChicoBird.


7
2017-12-23 13:47