Come si visualizza un avviso popup da un thread in background su Android?


Risposte:


246

Puoi farlo chiamando un Activity's runOnUiThreadmetodo dal tuo thread:

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

Non sono sicuro di aver capito come farlo. Ho il mio esistente public void run (). Ho provato a inserire questo codice lì. So che non è giusto perché non ha funzionato, ma sono davvero bloccato.
SwimBikeRun

14
L '"attività" è passata al thread non ui nel suo costruttore? Qual è il modo giusto per ottenere l'oggetto attività che stai utilizzando dall'interno del thread separato?
snapfractalpop

Imposta il Threadriferimento dell'oggetto a Activityin Activity's onResume. Disinseriscilo in Activity's onPause. Fare entrambe le cose sotto un synchronizedblocco che sia la Activitye Threadrispetto.
JohnnyLambada

5
a volte non c'è accesso Activityall'istanza, puoi invece usare la semplice classe helper, vedi qui: stackoverflow.com/a/18280318/1891118
Oleksii K.

5
Di solito ho scoperto che MyActivity.this.runOnUiThread()funziona bene dall'interno di un file Thread/ AsyncTask.
Anthony Atkinson

62

Mi piace avere un metodo nella mia attività chiamato showToastche posso chiamare da qualsiasi luogo ...

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

Quindi lo chiamo più spesso dall'interno MyActivitysu qualsiasi thread come questo ...

showToast(getString(R.string.MyMessage));

3
Grazie, sto aggiungendo questa maggior parte delle attività ora.
Gene Myers

1
Per TOAST, usa sempre il contesto dell'applicazione, non il contesto dell'attività!
Yousha Aleayoub

1
@YoushaAleayoub why?
OneWorld

1
@OneWorld, prove: 1- Per un messaggio di brindisi, la Google Dev Guide utilizza il contesto dell'applicazione e dice esplicitamente di usarlo. 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 Ci sono molte discussioni e supposizioni nei link che hai fornito. Ad esempio, RomainGuy dice che non ci sono perdite di memoria nella tua prova no. 4. Alcuni collegamenti risalgono ai primi giorni di Android nel 2009. Anche negli altri collegamenti si dice che è possibile utilizzare entrambi i contesti. Attività e applicazione. Forse hai una prova basata su prove reali più aggiornata? Hai un link per 1?
OneWorld

28

Questo è simile ad altre risposte, tuttavia aggiornato per le nuove API disponibili e molto più pulito. Inoltre, non presume che ti trovi in ​​un contesto di attività.

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

Quando il contesto che hai non è un'attività, questa è la risposta perfetta. Molte grazie!
franchi

17

Un approccio che funziona praticamente da qualsiasi luogo, anche da luoghi in cui non hai un Activityo View, è quello di prendere un Handleral thread principale e mostrare il brindisi:

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

Il vantaggio di questo approccio è che funziona con qualsiasi Context, inclusi Servicee Application.


10

Come questo o questo , con un Runnableche mostra il file Toast. Vale a dire,

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

6

A volte, devi inviare un messaggio da un altro Threadal thread dell'interfaccia utente. Questo tipo di scenario si verifica quando non è possibile eseguire operazioni di rete / I / O sul thread dell'interfaccia utente.

L'esempio seguente gestisce quello scenario.

  1. Hai il thread dell'interfaccia utente
  2. È necessario avviare l'operazione di I / O e quindi non è possibile eseguire Runnableil thread dell'interfaccia utente. Quindi pubblica il tuo Runnableal gestore suHandlerThread
  3. Ottieni il risultato da Runnablee invialo di nuovo al thread dell'interfaccia utente e mostra un Toastmessaggio.

Soluzione:

  1. Crea un HandlerThread e avviarlo
  2. Crea un gestore con Looper da HandlerThread:requestHandler
  3. Crea un gestore con Looper dal thread principale: responseHandlere sovrascrivi il handleMessagemetodo
  4. postun RunnablecompitorequestHandler
  5. All'interno Runnablecompito, chiamare sendMessageilresponseHandler
  6. Questa sendMessageinvocazione del risultato di handleMessagein responseHandler.
  7. Ottieni attributi da Messageed elaboralo, aggiorna l'interfaccia utente

Codice di esempio:

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

Articoli utili:

handlerthreads-e-perché-si-deve-essere-utilizzando-li-in-your-android-apps

Android-crochet-gestore-handlerthread-i


5
  1. Ottieni l'istanza del gestore thread dell'interfaccia utente e usa handler.sendMessage();
  2. post()Metodo di chiamatahandler.post();
  3. runOnUiThread()
  4. view.post()

3

È possibile utilizzare Looperper inviare un Toastmessaggio. Passare attraverso questo collegamento per maggiori dettagli.

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

ed è chiamato nel tuo thread. Il contesto potrebbe derivare Activity.getContext()dal fatto che Activitydevi mostrare il brindisi.


2

Ho creato questo approccio basato sulla risposta di 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();
        }
    });
}

Ha funzionato bene per me.


0

Ho riscontrato lo stesso problema :

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.

Prima: funzione onCreate

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

Dopo: funzione onCreate

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

ha funzionato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.