it-swarm.com.de

Android Grundlagen: Code im UI-Thread ausführen

Gibt es im Hinblick auf die Ausführung von Code im UI-Thread einen Unterschied zwischen:

MainActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

oder

MainActivity.this.myView.post(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

und

private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
    protected void onPostExecute(Bitmap result) {
        Log.d("UI thread", "I am the UI thread");
    }
}
423
Luky

Keines davon ist genau das gleiche, obwohl alle den gleichen Nettoeffekt haben werden.

Der Unterschied zwischen dem ersten und dem zweiten besteht darin, dass der erste (runOnUiThread()) den Runnable ausführt, wenn Sie zufällig on der Hauptanwendungsthread sind, wenn Sie den Code ausführen. sofort. Die zweite (post()) setzt immer das Runnable am Ende der Ereigniswarteschlange, auch wenn Sie sich bereits im Hauptanwendungsthread befinden.

Die dritte Methode geht davon aus, dass Sie eine Instanz von BackgroundTask erstellen und ausführen. Sie verschwendet viel Zeit damit, einen Thread aus dem Thread-Pool zu holen, um ein standardmäßiges no-op doInBackground() auszuführen, bevor Sie irgendwann was tun entspricht einem post(). Dies ist bei weitem die am wenigsten effiziente der drei. Verwenden Sie AsyncTask, wenn Sie tatsächlich in einem Hintergrund-Thread arbeiten müssen, nicht nur für die Verwendung von onPostExecute().

276
CommonsWare

Ich mag das von HPP-Kommentar , es kann überall ohne Parameter verwendet werden:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});
234
pomber

Es gibt einen vierten Weg mit Handler

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});
56
vasart

Die Antwort von Pomber ist akzeptabel, aber ich bin kein großer Fan davon, wiederholt neue Objekte zu erstellen. Die besten Lösungen sind immer diejenigen, die versuchen, das Gedächtnisproblem zu lindern. Ja, es gibt eine automatische Speicherbereinigung, aber die Speichererhaltung in einem mobilen Gerät fällt unter die bewährten Methoden. Der folgende Code aktualisiert eine Textansicht in einem Dienst.

TextViewUpdater textViewUpdater = new TextViewUpdater();
Handler textViewUpdaterHandler = new Handler(Looper.getMainLooper());
private class TextViewUpdater implements Runnable{
    private String txt;
    @Override
    public void run() {
        searchResultTextView.setText(txt);
    }
    public void setText(String txt){
        this.txt = txt;
    }

}

Es kann von überall wie folgt verwendet werden:

textViewUpdater.setText("Hello");
        textViewUpdaterHandler.post(textViewUpdater);
18
Joe

Ab Android P können Sie getMainExecutor() verwenden:

getMainExecutor().execute(new Runnable() {
  @Override public void run() {
    // Code will run on the main thread
  }
});

Aus dem Android Developer Docs :

Geben Sie einen Executor zurück, der in der Warteschlange befindliche Tasks im diesem Kontext zugeordneten Hauptthread ausführt. Dies ist der Thread, der zum Weiterleiten von Aufrufen an Anwendungskomponenten (Aktivitäten, Dienste usw.) verwendet wird.

Aus dem CommonsBlog :

Sie können getMainExecutor () im Kontext aufrufen, um einen Executor zu erhalten, der seine Jobs im Hauptanwendungsthread ausführt. Es gibt andere Möglichkeiten, dies mit Looper und einer benutzerdefinierten Executor-Implementierung zu erreichen, dies ist jedoch einfacher.

7
Dick Lucas

Wenn Sie in Fragment verwenden müssen, sollten Sie verwenden

private Context context;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }


    ((MainActivity)context).runOnUiThread(new Runnable() {
        public void run() {
            Log.d("UI thread", "I am the UI thread");
        }
    });

anstatt von

getActivity().runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

Weil es in einigen Situationen wie dem Pager-Fragment eine Nullzeiger-Ausnahme gibt

6
Beyaz

hallo Leute, das ist eine grundlegende Frage, die ich dir sage

benutze Handler

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});
2
raghu kambaa