96 votes

Accès au gestionnaire de threads de l'interface utilisateur à partir d'un service

Je suis en train d'essayer quelque chose de nouveau sur Android pour lequel j'ai besoin d'accéder au gestionnaire du thread de l'interface utilisateur.

Je sais ce qui suit :

  1. Le thread UI a son propre gestionnaire et de boucles
  2. Tout message sera placé dans la file d'attente des messages de l'interface utilisateur
  3. Le looper récupère l'événement et le transmet au gestionnaire
  4. Le gestionnaire traite le message et envoie l'événement spécifique à l'interface utilisateur.

Je veux avoir mon service qui doit obtenir le gestionnaire de fil de l'interface utilisateur et mettre un message dans ce gestionnaire. Ainsi, ce message sera traité et sera envoyé à l'interface utilisateur. Ici, le service sera un service normal qui sera lancé par une application.

J'aimerais savoir si cela est possible. Dans l'affirmative, veuillez me suggérer quelques extraits de code pour que je puisse l'essayer.

Salutations Girish

187voto

volley Points 3229

Ce bout de code construit un Handler associé au thread principal (UI) :

Handler handler = new Handler(Looper.getMainLooper());

Vous pouvez alors envoyer des éléments à exécuter dans le fil principal (UI) comme suit :

handler.post(runnable_to_call_from_main_thread);

Si le gestionnaire lui-même est créé à partir du thread principal (interface utilisateur), l'argument peut être omis pour des raisons de brièveté :

Handler handler = new Handler();

El Guide du développeur Android sur les processus et les threads contient plus d'informations.

3 votes

Je l'ai testé et il fonctionne parfaitement ! Un exemple de cas d'utilisation : J'ai une interface web qui est servie par un serveur fonctionnant directement sur l'appareil. Comme l'interface peut être utilisée pour interagir directement avec l'interface utilisateur, et comme le serveur doit fonctionner sur son propre thread, j'avais besoin d'un moyen de toucher le thread de l'interface utilisateur depuis l'extérieur d'une activité. La méthode que vous avez décrite a très bien fonctionné.

2 votes

Brillant. Fonctionne comme un charme, et très utile. MERCI.

0 votes

Parfait ^^ je viens de l'utiliser pour mettre à jour mon interface depuis un StreamingService. exactement ce dont j'avais besoin merci !

28voto

CommonsWare Points 402670

Créer un Messenger attaché à votre Handler et passer que Messenger à la Service (par exemple, dans un Intent supplémentaire pour startService() ). Le site Service peut alors envoyer un Message à la Handler via le Messenger . Voici un exemple d'application démontrant ceci.

0 votes

Merci pour ce conseil. Cela a été utile. Veuillez consulter la pile suivante pour un flux d'événements tactiles vers mon activité MyDemo.dispatchTouchEvent(MotionEvent) line : 20 PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line : 1696 ViewRoot.handleMessage(Message) line : 1658 ViewRoot(Handler).dispatchMessage(Message) line : 99 Looper.loop() line : 123 /La gestion des événements commence ici ActivityThread.main(String[]) line : 4203 Ici, le ViewRoot est un Handler. Je veux obtenir la référence de ce Handler... est-il possible de l'obtenir depuis mon application ?

0 votes

@iLikeAndroid : Si vous n'avez pas créé le Handler vous ne pouvez pas y accéder, AFAIK.

0 votes

Merci. J'ai essayé de créer une instance de ViewRoot. Ce n'est rien d'autre qu'un gestionnaire. Maintenant, je suis capable d'envoyer les messages à ce gestionnaire. Le handler reçoit le message. Mais le ViewRoot n'est pas capable de traiter le message car il n'est pas initialisé correctement. Je dois appeler ViewRoot.setView() pour initialiser les données appropriées à ViewRoot. Je veux savoir s'il existe une vue par défaut ou une vue de base, etc., que je peux utiliser pour initialiser ?

5voto

user2983041 Points 444

Je vous suggère d'essayer le code suivant :

    new Handler(Looper.getMainLooper()).post(() -> {

        //UI THREAD CODE HERE

    });

4voto

pram Points 645

Pour l'instant, je préfère utiliser une bibliothèque de bus d'événements telle que Otto pour ce genre de problème. Il suffit de souscrire les composants (activité) souhaités :

protected void onResume() {
    super.onResume();
    bus.register(this);
}

Fournissez ensuite une méthode de rappel :

public void onTimeLeftEvent(TimeLeftEvent ev) {
    // process event..
}

et ensuite quand votre service exécute une déclaration comme celle-ci :

bus.post(new TimeLeftEvent(340));

Ce POJO sera transmis à votre activité ci-dessus et à tous les autres composants d'abonnement. Simple et élégant.

2voto

Melbourne Lopes Points 505

Vous pouvez obtenir des valeurs par l'intermédiaire du récepteur de diffusion...... de la manière suivante : créez d'abord votre propre IntentFilter comme,

Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");

Ensuite, créez la classe interne BroadcastReceiver comme,

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    /** Receives the broadcast that has been fired */
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction()=="YOUR_INTENT_FILTER"){
           //HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW///////////
           String receivedValue=intent.getStringExtra("KEY");
        }
    }
};

Maintenant, enregistrez votre récepteur de diffusion dans onResume() comme,

registerReceiver(broadcastReceiver, intentFilter);

Et enfin, désenregistrer BroadcastReceiver dans onDestroy() comme,

unregisterReceiver(broadcastReceiver);

Maintenant, la partie la plus importante... Vous devez lancer la diffusion à partir de l'endroit où vous avez besoin d'envoyer des valeurs..... donc faites comme,

Intent i=new Intent();
i.setAction("YOUR_INTENT_FILTER");
i.putExtra("KEY", "YOUR_VALUE");
sendBroadcast(i);

....cheers :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X