Aktualisieren Sie die Benutzeroberfläche von Thread in Android

Lesezeit: 6 Minuten

Aktualisieren Sie die Benutzeroberflache von Thread in Android
Stutfohlen

Ich möchte meine Benutzeroberfläche von einem Thread aktualisieren, der eine Fortschrittsleiste aktualisiert. Leider verschwindet der Fortschrittsbalken, wenn das Drawable des Fortschrittsbalkens vom “ausführbaren” aktualisiert wird! Ändern des einziehbaren Fortschrittsbalkens onCreate() auf der anderen Seite funktioniert!

Irgendwelche Vorschläge?

public void onCreate(Bundle savedInstanceState) {
    res = getResources();
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); //**Works**/
    handler.postDelayed(runnable, 1);       
}

private Runnable runnable = new Runnable() {
    public void run() {  
        runOnUiThread(new Runnable() { 
            public void run() 
            { 
                //* The Complete ProgressBar does not appear**/                         
                pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); 
            } 
        }); 
    }
}

Sie sollten dies mit Hilfe von tun AsyncTask (ein intelligenter Hintergrundthread) und ProgressDialog

AsyncTask ermöglicht die ordnungsgemäße und einfache Verwendung des UI-Threads. Diese Klasse ermöglicht das Ausführen von Hintergrundoperationen und das Veröffentlichen von Ergebnissen im UI-Thread, ohne Threads und/oder Handler bearbeiten zu müssen.

Eine asynchrone Aufgabe wird durch eine Berechnung definiert, die in einem Hintergrundthread ausgeführt wird und deren Ergebnis im UI-Thread veröffentlicht wird. Eine asynchrone Aufgabe wird durch 3 generische Typen namens Params, Progress und Result und 4 Schritte namens begin, doInBackground, processProgress und end definiert.

Die 4 Schritte

Wenn eine asynchrone Aufgabe ausgeführt wird, durchläuft die Aufgabe 4 Schritte:

onPreExecute(), die unmittelbar nach Ausführung der Aufgabe im UI-Thread aufgerufen wird. Dieser Schritt wird normalerweise verwendet, um die Aufgabe einzurichten, indem beispielsweise ein Fortschrittsbalken in der Benutzeroberfläche angezeigt wird.

doInBackground(Params...), die im Hintergrund-Thread unmittelbar nach Abschluss der Ausführung von onPreExecute() aufgerufen wird. Dieser Schritt wird verwendet, um Hintergrundberechnungen durchzuführen, die viel Zeit in Anspruch nehmen können. An diesen Schritt werden die Parameter der asynchronen Task übergeben. Das Ergebnis der Berechnung muss von diesem Schritt zurückgegeben werden und wird an den letzten Schritt zurückgereicht. Dieser Schritt kann auch publishProgress(Progress…) verwenden, um eine oder mehrere Fortschrittseinheiten zu veröffentlichen. Diese Werte werden im UI-Thread im Schritt onProgressUpdate(Progress…) veröffentlicht.

onProgressUpdate(Progress...), die im UI-Thread nach einem Aufruf von publishProgress(Progress…) aufgerufen wird. Der Zeitpunkt der Ausführung ist undefiniert. Diese Methode wird verwendet, um jede Form des Fortschritts in der Benutzeroberfläche anzuzeigen, während die Hintergrundberechnung noch ausgeführt wird. Beispielsweise kann es verwendet werden, um einen Fortschrittsbalken zu animieren oder Protokolle in einem Textfeld anzuzeigen.

onPostExecute(Result), die im UI-Thread aufgerufen wird, nachdem die Hintergrundberechnung abgeschlossen ist. Das Ergebnis der Hintergrundberechnung wird diesem Schritt als Parameter übergeben. Threading-Regeln

Es gibt ein paar Threading-Regeln, die befolgt werden müssen, damit diese Klasse richtig funktioniert:

Die Aufgabeninstanz muss im UI-Thread erstellt werden. execute(Params…) muss im UI-Thread aufgerufen werden. Rufen Sie onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…) nicht manuell auf. Die Aufgabe kann nur einmal ausgeführt werden (eine Ausnahme wird ausgelöst, wenn eine zweite Ausführung versucht wird).

Beispielcode

Was der Adapter in diesem Beispiel tut, ist nicht wichtig, wichtiger ist zu verstehen, dass Sie AsyncTask verwenden müssen, um ein Dialogfeld für den Fortschritt anzuzeigen.

private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
    ProgressDialog dialog;
    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(viewContacts.this);
        dialog.setMessage(getString(R.string.please_wait_while_loading));
        dialog.setIndeterminate(true);
        dialog.setCancelable(false);
        dialog.show();
    }
    /* (non-Javadoc)
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected ContactsListCursorAdapter doInBackground(Void... params) {
        cur1 = objItem.getContacts();
        startManagingCursor(cur1);

        adapter1 = new ContactsListCursorAdapter (viewContacts.this,
                R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});

        return adapter1;
    }

    protected void onPostExecute(ContactsListCursorAdapter result) {
        list.setAdapter(result);
        dialog.dismiss();
    }
}

Die einfachste Lösung, die ich gesehen habe, um dem UI-Thread eine kurze Ausführung zu liefern, ist über die Methode post() einer Ansicht. Dies ist erforderlich, da UI-Methoden nicht wiedereintrittsfähig sind. Die Methode dafür ist:

package android.view;

public class View;

public boolean post(Runnable action);

Die Methode post() entspricht SwingUtilities.invokeLater(). Leider habe ich nichts Einfaches gefunden, das dem SwingUtilities.invokeAndWait() entspricht, aber man kann das spätere basierend auf dem ersteren mit einem Monitor und einem Flag bauen.

Was Sie also sparen, ist das Erstellen eines Handlers. Sie müssen nur Ihre Ansicht finden und dann darauf posten. Sie können Ihre Ansicht über findViewById() finden, wenn Sie dazu neigen, mit ID-ed-Ressourcen zu arbeiten. Der resultierende Code ist sehr einfach:

/* inside your non-UI thread */

view.post(new Runnable() {
        public void run() {
            /* the desired UI update */
        }
    });
}

Hinweis: Im Vergleich zu SwingUtilities.invokeLater() gibt die Methode View.post() einen booleschen Wert zurück, der angibt, ob die Ansicht eine zugehörige Ereigniswarteschlange hat. Da ich den invokeLater() bzw. post() sowieso nur für fire and forget, ich habe den Ergebniswert nicht überprüft. Grundsätzlich sollten Sie post() erst aufrufen, nachdem onAttachedToWindow() für die Ansicht aufgerufen wurde.

Mit freundlichen Grüßen

  • Wenn die view ist ein Verweis auf ein tatsächliches Objekt wie progress bardas Verlassen einer Aktivität oder eines Fragments, das die gesamte Ansicht erstellt, würde das recyceln view Ressource, verursacht null.post(~);

    – Alston

    23. September 2014 um 2:33 Uhr

  • Wie Sie den Looper über einen Post beenden können, erfahren Sie hier: stackoverflow.com/a/30562809/502187

    Benutzer502187

    31. Mai 2015 um 21:25 Uhr

Aktualisieren Sie die Benutzeroberflache von Thread in Android
Vit Chudenko

Wenn du benutzt Handler (Ich sehe, dass Sie es tun und hoffentlich haben Sie seine Instanz im UI-Thread erstellt), dann verwenden Sie es nicht runOnUiThread() in deinem runnable. runOnUiThread() wird jedoch verwendet, wenn Sie etwas von einem Nicht-UI-Thread aus tun Handler wird Ihre bereits ausführen runnable im UI-Thread.

Versuchen Sie, so etwas zu tun:

private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    res = getResources();
    // pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); **//Works**
    mHandler.postDelayed(runnable, 1);
}

private Runnable runnable = new Runnable() {
    public void run() {
        pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
        pB.invalidate(); // maybe this will even not needed - try to comment out
    }
};

1646310788 451 Aktualisieren Sie die Benutzeroberflache von Thread in Android
pablochan

Verwenden Sie die AsyncTask Klasse (anstelle von Runnable). Es hat eine Methode namens onProgressUpdate, die sich auf die Benutzeroberfläche auswirken kann (sie wird im UI-Thread aufgerufen).

Sie müssen eine erstellen Handler im UI-Thread und verwenden Sie ihn dann zum Posten oder Senden einer Nachricht von Ihrem anderen Thread, um die UI zu aktualisieren

1646310788 423 Aktualisieren Sie die Benutzeroberflache von Thread in Android
tmho

Wenn Ihnen die AsyncTask nicht gefällt, können Sie die verwenden Beobachter Muster. Verwenden Sie in diesem Beispiel den ResponseHandler als innere Klasse in Ihrer Aktivität und geben Sie dann eine Zeichenfolgennachricht ein, die den Prozentsatz der Fortschrittsbalken festlegt … Sie müssen sicherstellen, dass alle Änderungen an der Benutzeroberfläche innerhalb des ResponseHandler vorgenommen werden, um ein Einfrieren zu vermeiden UI, dann kann Ihr Worker-Thread (im Beispiel EventSource) die erforderlichen Aufgaben ausführen.

Ich würde die AsyncTask verwenden, aber das Beobachtermuster kann aus Anpassungsgründen gut sein und ist leichter zu verstehen. Ich bin mir auch nicht sicher, ob dieser Weg allgemein akzeptiert wird oder zu 100% funktioniert. Ich lade jetzt das Android-Plugin herunter, um es zu testen

1646310788 138 Aktualisieren Sie die Benutzeroberflache von Thread in Android
Ravindra Babu

Wie vom Beamten empfohlen Dokumentationkönnen Sie verwenden AsyncTask um Arbeitselemente mit einer Dauer von weniger als 5 ms zu bearbeiten. Wenn Ihre Aufgabe mehr Zeit in Anspruch nimmt, suchen Sie nach anderen Alternativen.

HandlerThread ist eine Alternative zu Thread oder AsyncTask. Wenn Sie die Benutzeroberfläche von aktualisieren müssen HandlerThreadposten Sie eine Nachricht im UI-Thread Looper und UI-Thread Handler kann UI-Updates verarbeiten.

Beispielcode:

Android: Toast in einem Thread

923410cookie-checkAktualisieren Sie die Benutzeroberfläche von Thread in Android

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy