Bagaimana Anda menampilkan Toast dari thread latar belakang di Android?

Jawaban:

246

Anda dapat melakukannya dengan memanggil Activity's runOnUiThreadmetode dari thread Anda:

activity.runOnUiThread(new Runnable() {
    public void run() {
        Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
    }
});
Lauri Lehtinen
sumber
Saya tidak yakin saya mengerti bagaimana melakukan ini. Saya sudah memiliki public void run (). Saya mencoba meletakkan kode ini di sana. Saya tahu itu tidak benar karena tidak berhasil, tetapi saya benar-benar terjebak.
SwimBikeRun
14
Apakah "aktivitas" diteruskan ke non-utas ui dalam konstruktornya? Apa cara yang benar untuk mendapatkan objek aktivitas yang Anda gunakan dari dalam utas terpisah?
snapfractalpop
Setel Threadreferensi objek ke Activitydalam Activity's onResume. Batalkan pengaturan di Activity's onPause. Lakukan keduanya di bawah synchronizedkunci yang menghormati Activitydan Threadmenghormati.
JohnnyLambada
5
terkadang tidak ada akses ke Activityinstance, Anda dapat menggunakan kelas helper sederhana, lihat di sini: stackoverflow.com/a/18280318/1891118
Oleksii K.
5
Saya biasanya menemukan bahwa MyActivity.this.runOnUiThread()bekerja dengan baik dari dalam Thread/ dalam / AsyncTask.
Anthony Atkinson
62

Saya suka memiliki metode dalam aktivitas saya yang disebut showToastyang dapat saya panggil dari mana saja ...

public void showToast(final String toast)
{
    runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}

Saya kemudian paling sering menyebutnya dari dalam MyActivitypada utas apa pun seperti ini ...

showToast(getString(R.string.MyMessage));
mjaggard.dll
sumber
3
Terima kasih, saya menambahkan sebagian besar aktivitas ini sekarang.
Gene Myers
1
Untuk TOAST, selalu gunakan Konteks Aplikasi, bukan Konteks Aktivitas!
Yousha Aleayoub
1
@YoushaAleayoub kenapa?
OneWorld
1
@OneWorld, bukti: 1- Untuk pesan bersulang, Panduan Pengembang Google menggunakan konteks aplikasi dan secara eksplisit mengatakan untuk menggunakannya. 2- stackoverflow.com/a/4128799/1429432 3- stackoverflow.com/a/10347346/1429432 4- groups.google.com/d/msg/android-developers/3i8M6-wAIwM/…
Yousha Aleayoub
@YoushaAleayoub Ada banyak diskusi dan tebakan di tautan yang Anda berikan. Misalnya RomainGuy mengatakan tidak ada kebocoran memori dalam bukti Anda tidak. 4. Beberapa link berasal dari masa-masa awal Android tahun 2009. Juga orang mengatakan di link lain bahwa Anda dapat menggunakan kedua konteks tersebut. Aktivitas dan aplikasi. Mungkin Anda memiliki bukti berbasis bukti nyata yang lebih terkini? Apakah Anda memiliki link untuk 1?
OneWorld
28

Ini mirip dengan jawaban lain, namun diperbarui untuk aplikasi baru yang tersedia dan jauh lebih bersih. Juga, jangan menganggap Anda berada dalam Konteks Aktivitas.

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();
            }
        });
    }
}
ChrisCM
sumber
Ketika konteks yang Anda miliki bukanlah aktivitas, itu adalah jawaban yang sempurna. Terima kasih banyak!
francas
17

Salah satu pendekatan yang bekerja dari mana saja, termasuk dari tempat di mana Anda tidak memiliki Activityatau View, adalah dengan mengambil a Handlerke utas utama dan menunjukkan 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();
    }
  });
}

Keuntungan dari pendekatan ini adalah ia bekerja dengan apa saja Context, termasuk Servicedan Application.

Mike Laren
sumber
10

Seperti ini atau ini , dengan a Runnableyang menunjukkan Toast. Yaitu,

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

Terkadang, Anda harus mengirim pesan dari yang lain Threadke thread UI. Jenis skenario ini terjadi ketika Anda tidak dapat menjalankan operasi Jaringan / IO di thread UI.

Contoh di bawah menangani skenario itu.

  1. Anda memiliki UI Thread
  2. Anda harus memulai operasi IO dan karenanya Anda tidak dapat berjalan Runnabledi thread UI. Jadi posting Anda Runnableke handlerHandlerThread
  3. Dapatkan hasilnya Runnabledan kirimkan kembali ke thread UI dan tampilkan Toastpesan.

Larutan:

  1. Buat HandlerThread dan mulai
  2. Buat Handler dengan Looper dari HandlerThread:requestHandler
  3. Buat Handler dengan Looper dari Main Thread: responseHandlerdan handleMessagemetode timpa
  4. postsebuah Runnabletugas direquestHandler
  5. Di dalam Runnabletugas, panggilan sendMessagediresponseHandler
  6. Ini sendMessagehasil permintaan handleMessagedalam responseHandler.
  7. Dapatkan atribut dari Messagedan proses, perbarui UI

Kode sampel:

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

Artikel yang berguna:

handlerthreads-and-why-you-should-be-using-them-in-your-android-apps

android-looper-handler-handlerthread-i

Ravindra babu
sumber
5
  1. Dapatkan instance UI Thread Handler dan gunakan handler.sendMessage();
  2. post()Metode panggilanhandler.post();
  3. runOnUiThread()
  4. view.post()
Kerwin You
sumber
3

Anda dapat menggunakan Looperuntuk mengirim Toastpesan. Buka tautan ini untuk lebih jelasnya.

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

dan itu disebut di utas Anda. Konteks mungkin didapat Activity.getContext()dari ActivityAnda harus bersulang.

Vinoj John Hosan
sumber
2

Saya melakukan pendekatan ini berdasarkan jawaban mjaggard:

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

Bekerja dengan baik untuk saya.

Ângelo Polotto
sumber
0

Saya mengalami masalah yang sama :

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.

Sebelum: fungsi onCreate

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
    }
});
thread.start();

Sesudah: fungsi onCreate

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
    }
});

itu berhasil.

Languoguang
sumber