7 votes

Comment utiliser Thread.sleep() en Kotlin

Ceci provient de la fin du codelab que l'on trouve ici :

Introduction au débogage - Exemple de débogage : accès à une valeur qui n'existe pas

Tout cela se trouve dans le fichier MainActivity.kt

Voici mon onCreate

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val helloTextView: TextView = findViewById(R.id.division_textview)
    helloTextView.text = "Hello, debugging!"

    division()
}
//...

Voici la fonction de division fournie par Google, mais avec 2 changements que j'expliquerai dans un instant...

fun division() {
  val numerator = 60
  var denominator = 4
    repeat(4) {
     Thread.sleep(3000)
     findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
     Log.v(TAG, "${numerator / denominator}")
     denominator--
    }
  }

Les instructions donnent l'impression que l'on s'attend à ce que sleep() pour accepter les secondes, mais AS indique qu'il attend des millis, j'ai donc changé leur 3 en 3000. J'ai ajouté Log.v(TAG, "${numerator / denominator}") pour voir ce qui se passait, car il ne fonctionnait pas comme prévu.

L'objectif était de faire en sorte que l'émulateur crée un gif des quotients mis à jour. Cela est censé être utile lors du débogage.

Rien ne s'affiche à l'écran, pas même le nom de l'application, jusqu'à ce que le bouton repeat() finitions. Les enregistrements se produisent à intervalles de 3 secondes, comme prévu.

Pourquoi la mise en page attend-elle, et comment puis-je la mettre à jour à chaque itération de la boucle ?

5voto

cactustictacs Points 4293

Honnêtement, je n'ai aucune idée de ce que fait ce Codelab, d'après le code qu'il fournit. L'application ne va rien rendre (ni la présentation, ni les modifications de la présentation) avant le début de l'application. onCreate les finitions, et onCreate ne se terminera pas tant qu'il n'aura pas exécuté tout son code, y compris cette repeat dans le bloc division qu'il appelle.

division ne démarre pas de threads de travail, de sorte que tous les Thread.sleep bloque le fil d'exécution principal - il bloque l'application. Et vous avez raison, sleep prend une valeur en millis, et non en secondes - J'ai l'impression qu'ils n'ont pas réellement exécuté ce code, il est plein d'autres erreurs et d'incohérences qui rendent honnêtement difficile de comprendre ce que l'on est censé faire. Changement qui Log.d appel ? Ceux de onCreate ? (Il s'agit en fait de l'appel Log.v appeler division , Je suppose que )


Voici comment vous utilisez un thread en Kotlin - vous devez en créer un nouveau (de manière à ce que le thread principal puisse terminer la création de l'activité et exécuter l'interface utilisateur) :

fun division() {
    // create a new thread (and start it immediately)
    thread(start=true) {
        repeat(4) { i ->
            Thread.sleep(3000L)
            // assuming you've done the ``findViewById`` and assigned it to a variable
            runOnUiThread { divisionTextView.text = "$i" }
        }
    }
}

Il s'agit simplement d'une mise à jour avec le numéro de répétition actuel ( i ) par souci de concision, mais les points importants sont les suivants :

  • vous créez un nouveau fil de discussion pour faire le travail (et dormir)
  • vous utilisez runOnUiThread (qui est une méthode de l'activité) pour effectuer la mise à jour du texte sur le thread principal/UI (même chose). Si vous essayez de toucher l'interface utilisateur à partir d'un autre thread il va s'écraser

Une autre façon de procéder consiste à post un exécutable vers le thread de l'interface utilisateur par le biais d'une vue, autant l'utiliser. TextView :

divisionTextView.post { divisionTextView.text = "$i" }

Les coroutines seraient une meilleure idée ici (vous pouvez les exécuter sur le thread principal sans qu'il se bloque, donc vous n'avez pas à vous soucier de changer de thread pour mettre à jour l'interface utilisateur, ou tout autre truc de sécurité de thread) mais c'est la base de l'exécution d'un thread. Je n'ai vraiment aucune idée de ce qui se passe dans ce codelab.

2voto

KatiaDehbia Points 11

Rien ne s'affiche à l'écran, pas même le nom de l'application, tant que la fonction repeat() n'est pas terminée. Les logs se produisent à intervalles de 3 secondes, comme prévu. Pourquoi la mise en page attend-elle ?

Elle est due à Cycle de vie de l'activité

  • Lorsque l'activité est dans l'état Créé, vous ne pouvez pas voir l'interface utilisateur.
  • Lorsque l'activité est dans l'état Démarré, l'interface utilisateur devient visible mais vous ne pouvez pas interagir avec elle.
  • Lorsque l'activité est dans l'état Reprise, l'interface utilisateur est visible et vous pouvez interagir avec elle.

Comme vous appelez la fonction division() dans le callback onCreate(), vous ne verrez pas l'interface utilisateur de l'activité.

Comment faire pour qu'il soit mis à jour à chaque itération de la boucle ?

Une façon d'y parvenir est d'exécuter la fonction division() dans un nouveau fil de discussion. Ce faisant, le thread principal affiche l'interface utilisateur (vous pourrez la voir). Utilisez ensuite runOnUiThread pour mettre à jour votre texte division_textview.

    fun division() {
    val numerator = 60
    var denominator = 4
    thread(start=true) {
        /* The loop only repeat 4 times to avoid a crash*/
        repeat(4) {
            Log.v(TAG, "$denominator")
            // Set division_textview text to the quotient.
            runOnUiThread { findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}") }
            // Wait for 1 second
            Thread.sleep(1000L)
            denominator--
        }
    }
}

1voto

tadev Points 172

Vous pouvez utiliser Corountines. La fonction de retard est très facile à utiliser.

lifecycleScope.launch {
    myTextView.text = "Starting"
    delay(1000L)
    myTextView.text = "Processing"
    delay(2000L)
    myTextView.text = "Done"
}

0voto

Essayez d'utiliser des coroutines. Voici un lien : https://kotlinlang.org/docs/coroutines-basics.html

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