Dans un service Android, j'ai créé des threads pour effectuer une tâche d'arrière-plan.
J'ai une situation où un thread doit publier certaines tâches dans la file d'attente de messages du thread principal, par exemple a Runnable
.
Existe-t-il un moyen d'obtenir Handler
le fil principal et de le poster Message
/ Runnable
à partir de mon autre fil?
Merci,
Réponses:
REMARQUE: Cette réponse a suscité tellement d'attention que j'ai besoin de la mettre à jour. Depuis que la réponse originale a été publiée, le commentaire de @dzeikei a reçu presque autant d'attention que la réponse originale. Voici donc 2 solutions possibles:
1. Si votre thread d'arrière-plan a une référence à un
Context
objet:Assurez-vous que vos threads de travail d'arrière-plan ont accès à un objet Context (peut être le contexte Application ou le contexte Service). Ensuite, faites-le dans le thread de travail en arrière-plan:
2. Si votre thread d'arrière-plan n'a pas (ou n'a pas besoin) d'
Context
objet(suggéré par @dzeikei):
la source
Handler
(ou utilisez l'Handler.Callback
interface), votrehandleMessage()
méthode sera UNIQUEMENT appelée pour les messages qui ont été publiés à l'aide de votre gestionnaire. Le thread principal utilise un gestionnaire différent pour publier / traiter les messages afin qu'il n'y ait pas de conflit.Handler mainHandler = new Handler(Looper.getMainLooper());
new Runnable(){@Override public void run() {....}};
Comme un commentateur ci-dessous l'a indiqué correctement, il ne s'agit pas d'une solution générale pour les services, uniquement pour les threads lancés à partir de votre activité (un service peut être un tel thread, mais pas tous). Sur le sujet compliqué de la communication activité-service, veuillez lire l'intégralité de la section Services du document officiel - c'est complexe, il serait donc avantageux de comprendre les bases: http://developer.android.com/guide/components/services.html #Notifications
La méthode ci-dessous peut fonctionner dans les cas les plus simples.
Si je vous comprends bien, vous avez besoin d'un peu de code à exécuter dans le thread GUI de l'application (ne pouvez penser à rien d'autre appelé thread "principal"). Pour cela, il existe une méthode sur
Activity
:Doc: http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
J'espère que c'est ce que vous recherchez.
la source
Service
. Vous ne pouvez pas utiliserrunOnUiThread()
dans un fichierService
. Cette réponse est trompeuse et ne répond pas à la question posée.Il existe un autre moyen simple, si vous n'avez pas accès au contexte.
1). Créez un gestionnaire à partir du looper principal:
2). Implémentez une interface exécutable:
3). Publiez votre Runnable sur uiHandler:
C'est tout ;-) Amusez-vous avec les threads, mais n'oubliez pas de les synchroniser.
la source
Si vous exécutez du code dans un thread, par exemple en retardant une action, vous devez invoquer à
runOnUiThread
partir du contexte. Par exemple, si votre code est dans laMainActivity
classe, utilisez ceci:Si votre méthode peut être invoquée à partir du principal (thread d'interface utilisateur) ou d'autres threads, vous avez besoin d'une vérification comme:
la source
Service
. Vous ne pouvez pas utiliserrunOnUiThread()
dans un fichierService
.Activity
documentation,runOnUiThread()
est une méthode deActivity
. Ce n'est pas une méthodeService
, vous ne pouvez donc pas l'utiliser. Quoi de plus clair que ça?Un bloc de code condensé est le suivant:
Cela n'implique pas de transmettre la référence d'activité ou la référence d'application.
Équivalent Kotlin:
la source
Versions de Kotlin
Lorsque vous êtes sur une activité , utilisez
Lorsque vous avez un contexte d'activité , mContext puis utilisez
Lorsque vous êtes dans un endroit où aucun contexte n'est disponible , utilisez
la source
runOnUiThread(){...}
La manière la plus simple, surtout si vous n'avez pas de contexte, si vous utilisez RxAndroid, vous pouvez faire:
la source
Code Kotlin plus précis à l'aide du gestionnaire:
la source
Une méthode à laquelle je peux penser est la suivante:
1) Laissez l'interface utilisateur se lier au service.
2) Exposez une méthode comme celle ci-dessous par le
Binder
qui enregistre votreHandler
:3) Dans le thread d'interface utilisateur, appelez la méthode ci-dessus après la liaison au service:
4) Utilisez le gestionnaire dans le fil du service pour publier votre tâche:
la source
HandlerThread
est une meilleure option pour les threads Java normaux dans Android.requestHandler
post
uneRunnable
tâche surrequestHandler
Communication avec l'interface utilisateur depuis
HandlerThread
Handler
avecLooper
pour le thread principal:responseHandler
et remplacer lahandleMessage
méthodeRunnable
tâche d'autre thread (HandlerThread
dans ce cas), appelezsendMessage
leresponseHandler
sendMessage
invocation de résultat dehandleMessage
inresponseHandler
.Message
et traitez-le, mettez à jour l'interface utilisateurExemple : mise
TextView
à jour avec des données reçues d'un service Web. Étant donné que le service Web doit être appelé sur un thread non UI, crééHandlerThread
pour le fonctionnement du réseau. Une fois que vous avez obtenu le contenu du service Web, envoyez un message à votre gestionnaire de thread principal (thread d'interface utilisateur) etHandler
gérera le message et mettra à jour l'interface utilisateur.Exemple de code:
Articles utiles:
handlerthreads-and-why-you-should-be-using-them-in-your-android-apps
android-looper-handler-handlerthread-i
la source
Je sais que c'est une vieille question, mais je suis tombé sur une ligne principale à fil unique que j'utilise à la fois dans Kotlin et Java. Ce n'est peut-être pas la meilleure solution pour un service, mais pour appeler quelque chose qui changera l'interface utilisateur à l'intérieur d'un fragment, c'est extrêmement simple et évident.
Java (8):
Kotlin:
la source
Suivez cette méthode. De cette façon, vous pouvez simplement mettre à jour l'interface utilisateur à partir d'un thread d'arrière-plan. runOnUiThread fonctionne sur le thread principal (UI). Je pense que cet extrait de code est moins complexe et facile, surtout pour les débutants.
dans le cas d'un service
créer un gestionnaire dans le oncreate
puis utilisez-le comme ça
la source
pour Kotlin, vous pouvez utiliser les corountines Anko :
mettre à jour
obsolète
la source
Le plus pratique est donc de faire en quelque sorte:
Et après:
la source
Cela peut également fonctionner dans une classe de service sans problème.
la source
Avec Kotlin, c'est comme ça dans n'importe quelle fonction:
la source
Activity
.