web-dev-qa-db-fra.com

Android bases: exécution de code dans le fil de l'interface utilisateur

Du point de vue de l'exécution du code dans le thread d'interface utilisateur, existe-t-il une différence entre:

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

ou

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

et

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

Aucune de celles-ci n'est exactement la même, bien qu'elles aient toutes le même effet net.

La différence entre le premier et le second est que si vous êtes on le thread principal de l'application lors de l'exécution du code, le premier (runOnUiThread()) exécutera immédiatement le Runnable. Le second (post()) place toujours le Runnable à la fin de la file d'attente des événements, même si vous êtes déjà sur le thread principal de l'application.

Le troisième, en supposant que vous créez et exécutiez une instance de BackgroundTask, perdra beaucoup de temps à saisir un thread du pool de threads pour exécuter une doInBackground() no-op par défaut, avant de finalement effectuer ce qui équivaut à une post() . C'est de loin le moins efficace des trois. Utilisez AsyncTask si vous avez du travail à faire dans un fil d’arrière-plan, pas seulement pour l’utilisation de onPostExecute().

276
CommonsWare

J'aime celui de commentaire HPP , il peut être utilisé n’importe où sans paramètre:

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

Il existe une quatrième méthode utilisant Handler

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

La réponse de Pomber est acceptable, mais je ne suis pas un grand fan de la création répétée de nouveaux objets. Les meilleures solutions sont toujours celles qui tentent d'atténuer les problèmes de mémoire. Oui, il y a une récupération automatique des ordures, mais la conservation de la mémoire dans un appareil mobile relève des meilleures pratiques. Le code ci-dessous met à jour un TextView dans un service.

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

}

Il peut être utilisé n'importe où comme ceci:

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

À partir de Android P, vous pouvez utiliser getMainExecutor():

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

À partir du documentation pour développeurs Android :

Renvoie un exécuteur qui exécutera les tâches en file d'attente sur le thread principal associé à ce contexte. C'est le fil utilisé pour distribuer les appels aux composants de l'application (activités, services, etc.).

De la CommonsBlog :

Vous pouvez appeler getMainExecutor () on Context pour obtenir un exécuteur qui exécutera ses travaux sur le thread principal de l'application. Il existe d'autres moyens d'accomplir cela, en utilisant Looper et une implémentation personnalisée d'Executor, mais cela est plus simple.

7
Dick Lucas

Si vous devez utiliser Fragment, vous devez utiliser

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

au lieu de

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

Parce qu'il y aura une exception de pointeur nul dans certaines situations comme un fragment de pageur

6
Beyaz

salut les gars celui-ci est la question de base tout de suite je dis

utiliser gestionnaire

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