Du point de vue de l'exécution de code dans le thread d'interface utilisateur, y a-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");
}
}
Réponses:
Aucun de ces éléments n'est exactement le même, bien qu'ils aient tous le même effet net.
La différence entre le premier et le second est que si vous vous trouvez sur le thread principal de l'application lors de l'exécution du code, le premier (
runOnUiThread()
) exécuteraRunnable
immédiatement. Le second (post()
) place toujours leRunnable
à la fin de la file d'attente des événements, même si vous êtes déjà sur le thread d'application principal.Le troisième, en supposant que vous créez et exécutez une instance de
BackgroundTask
, perdra beaucoup de temps à extraire un thread du pool de threads, pour exécuter un no-op par défautdoInBackground()
, avant de finalement faire ce qui équivaut à apost()
. C'est de loin le moins efficace des trois. À utiliserAsyncTask
si vous avez réellement du travail à faire dans un fil d'arrière-plan, pas seulement pour l'utilisation deonPostExecute()
.la source
AsyncTask.execute()
vous devez de toute façon appeler à partir du thread d'interface utilisateur, ce qui rend cette option inutile pour le cas d'utilisation de simplement exécuter du code sur le thread d'interface utilisateur à partir d'un thread d'arrière-plan, sauf si vous déplacez tout votre travail d'arrière-plandoInBackground()
et l'utilisezAsyncTask
correctement.AsyncTask
partir d'un thread d'interface utilisateur?boolean isUiThread = (Looper.getMainLooper().getThread() == Thread.currentThread());
Looper.getMainLooper().isCurrentThread
J'aime celui du commentaire HPP , il peut être utilisé n'importe où sans aucun paramètre:
la source
Il existe une quatrième façon d'utiliser
Handler
la source
new Handler(Looper.getMainLooper()).post(r)
, ce qui est la manière préférée de faireLooper.getMainLooper()
un appel statique à main, alors quepostOnUiThread()
doit avoir une instance deMainActivity
in scope.La réponse de Pomber est acceptable, mais je ne suis pas un grand fan de la création de nouveaux objets à plusieurs reprises. Les meilleures solutions sont toujours celles qui tentent d'atténuer le manque de mémoire. Oui, il existe une collecte automatique des déchets, mais la conservation de la mémoire dans un appareil mobile entre dans les limites des meilleures pratiques. Le code ci-dessous met à jour un TextView dans un service.
Il peut être utilisé de n'importe où comme ceci:
la source
The best solutions are always the ones that try to mitigate memory hog
. Il existe de nombreux autres critèresbest
, et cela a une légère odeur depremature optimization
. Autrement dit, sauf si vous savez que vous l'appelez suffisamment pour que le nombre d'objets créés soit un problème (par rapport aux dix mille autres façons dont votre application crée probablement des ordures), ce qui peut êtrebest
d'écrire le plus simple (le plus facile à comprendre ) et passez à une autre tâche.textViewUpdaterHandler
serait mieux nommé quelque chose commeuiHandler
oumainHandler
, car il est généralement utile pour n'importe quel message dans le thread d'interface utilisateur principal; il n'est pas du tout lié à votre classe TextViewUpdater. Je l'éloignerais du reste de ce code, et je préciserais qu'il peut être utilisé ailleurs ... Le reste du code est douteux, car pour éviter de créer un objet dynamiquement, vous cassez ce qui pourrait être un seul appel dans deux étapessetText
etpost
, qui reposent sur un objet à longue durée de vie que vous utilisez comme temporaire. Complexité inutile et non thread-safe. Pas facile à entretenir.uiHandler
ettextViewUpdater
, puis améliorer votre classe en changeant depublic void setText(String txt, Handler uiHandler)
et en ajoutant la ligne de la méthodeuiHandler.post(this);
Ensuite , l' appelant peut faire en une seule étape:textViewUpdater.setText("Hello", uiHandler);
. À l'avenir, si elle doit être sécurisée pour les threads, la méthode peut encapsuler ses instructions dans un verrouuiHandler
et l'appelant reste inchangé.Depuis Android P, vous pouvez utiliser
getMainExecutor()
:À partir des documents des développeurs Android :
Du CommonsBlog :
la source
Si vous devez utiliser dans Fragment, vous devez utiliser
au lieu de
Parce qu'il y aura une exception de pointeur nul dans certaines situations comme un fragment de pager
la source
salut les gars celui-ci est une question de base tout de suite je dis
utiliser le gestionnaire
la source
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
s'il n'est pas appelé à partir du thread d'interface utilisateur.