2016-04-01 1 views
2

Je souhaite créer un nouveau fil dans onCreate et communiquer avec le fil d'interface utilisateur à l'aide de post sur un View. Cependant, les instructions ed post ne semblent jamais être exécutées. Voici un petit exemple:Publication sur le fil d'interface utilisateur

import android.app.Activity 
import android.os.Bundle 
import android.widget.TextView  
import kotlin.concurrent.* 
import org.jetbrains.anko.* 

class MainActivity: Activity(), AnkoLogger { 
    protected override fun onCreate(savedInstanceState: Bundle?) { 
    super.onCreate(savedInstanceState) 

    val view = TextView(this) 
    setContentView(view) 

    thread() { 
     info("before post") 
     view.post({ info("inside post") }) 
     info("after post") 
    } 
    } 
} 

En regardant le journal, je ne peux voir before post et after post, mais jamais inside post.

Qu'est-ce que je fais mal?

+0

mb quelque chose dans l'implémentation 'info()'? – AndroidEx

Répondre

5

La question sous-jacente n'a en fait rien à voir avec Kotlin.

Le problème est que View.post() planifie uniquement son travail avec succès sur le thread principal si la vue est actuellement attachée à la hiérarchie de vue. L'attachement final de la vue ne se produit pas au moment de setContentView(). Cela arrive quelque temps plus tard.

Dans le cas où la vue du sujet de la post() n'est pas fixé actuellement (comme cela est le cas indiqué dans le problème), le View crée un RunQueue pour le thread courant (stocké comme fil local) et les horaires des travaux sur que RunQueue. Ainsi, le problème pour l'échantillon donné est le suivant. Puisque View.post() n'est pas appelé sur le thread principal, il créera un nouveau RunQueue pour le thread non-principal en cours, sans vérifier s'il est dirigé par un Looper (comme le thread principal). Cela signifie que le Runnable planifié va essentiellement dans un RunQueue qui n'est pas traité jusqu'à ce qu'un commence. Dans le cas illustré ici, n'est jamais démarré, le nouveau thread se termine et le travail n'est jamais exécuté.

Si le nouveau thread avec post a été retardé jusqu'à ce que la vue ait été attachée, par exemple, lorsqu'un clic est enregistré dessus, le post sera probablement en mesure de planifier le travail sur le thread principal. Mais ce n'est pas le cas ici car le message se produit 1) avant que la vue ne soit attachée, et 2) sur un autre thread non- qui se termine immédiatement.

+0

Quel serait le bon moment pour démarrer le 'thread()' sans compter sur l'interaction de l'utilisateur comme le clic dans votre exemple? – Cactus

+1

Je devinerais au cours de la vue onAttachedToWindow(), ou un View.OnAttachStateChangeListener enregistré. –

+0

Oh et BTW Je n'ai jamais pensé que ce serait spécifique à Kotlin, mais je l'ai étiqueté comme Kotlin pour que quelqu'un qui regarde l'exemple de repro minimal puisse comprendre quelle langue c'est. – Cactus

0

j'ai pu travailler autour de cela en lançant le fil lui-même d'un post, à savoir

view.post({ 
    thread() { 
    info("before post") 
    view.post({ info("inside post") }) 
    info("after post") 
    } 
}) 

mais je voudrais comprendre pourquoi je devais le faire.

0

Je vous recommande de jeter un oeil à Handlers. C'est un moyen plus sûr de mettre à jour les objets de l'interface utilisateur lors de l'exécution d'opérations sur un thread différent. Fondamentalement, il vous suffit de passer dans l'objet de gestionnaire à votre fil afin de mettre à jour le Ui

Plus d'infos ici http://developer.android.com/intl/pt-br/reference/android/os/Handler.html