Я только что обновил пользовательский интерфейс в рабочем потоке без проблем, и я не знаю почему

#android #kotlin

#Android #kotlin

Вопрос:

Я знаю, что обновление пользовательского интерфейса в рабочем потоке не рекомендуется Google. Я попытался написать демонстрационную версию с использованием Java, и она разбилась, как и ожидалось. Однако, когда я переключился на Kotlin, я обнаружил, к своему удивлению, что даже я не в потоке пользовательского интерфейса, я могу обновлять пользовательский интерфейс без сбоев. Как это происходит?

Мой код в Kotlin:

 class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Thread {
            Thread.sleep(5000)
            myText.text = "updated text"
        }.start()
    }
}
  

Основной файл макета содержит только обычный TextView с идентификатором «myText».
Моя версия Android sdk 29.

Я думаю, может быть, Kotlin выполняет какое-то переключение потоков за сценой или Google изменил правила (маловероятно), но это только мое предположение.

Любая помощь приветствуется!

Комментарии:

1. И если вы создадите сборку выпуска и запустите этот код, ваше приложение выйдет из строя

2. Можете ли вы попробовать напечатать идентификатор потока вне блока и внутри блока? В идеале это должно быть по-другому. Я попытался запустить этот фрагмент и обнаружил, что он выдает идентификатор потока как 1 как снаружи, так и внутри блока, что означает, что сдвиг потока не произошел (не каждый раз, когда это происходило).

3. Вы уверены, что он обновляется ??. я попытался запустить то же самое, но ничего не произошло. Сбой не произошел, но был выполнен вход в лямбда-блок. Я также установил все на 29.

4. @PrashantJha Я попытался напечатать идентификатор потока внутри и снаружи блока Thread {}, используя Thread.currentThread().id и получил 2 разных идентификатора. Обновление пользовательского интерфейса произошло в рабочем потоке.

5. @RishabhRitweek Да, textview был обновлен здесь за 5 секунд, и приложение не вылетело. Вы поместили инструкцию update в лямбда-блок, и текстовое представление не обновлялось? странно

Ответ №1:

Если вы хотите обновить поток пользовательского интерфейса с помощью Java. Вы можете продолжить эту логику следующим образом.

Выполняет указанное действие в потоке пользовательского интерфейса. Если текущий поток является потоком пользовательского интерфейса, то действие выполняется немедленно. Если текущий поток не является потоком пользовательского интерфейса, действие отправляется в очередь событий потока пользовательского интерфейса.

для java

 getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // Do something on UiThread
    }
});
  

для kotlin

 runOnUiThread({
    Log.i(TAG, "This is run")
    object : Runnable {                    // This whole expression
        override fun run() {               // returns an object which
            Log.i(TAG, "runOnUiThread")    // is a Runnable, but does
        }                                  // not at any point invoke
    }                                      // its "run" method
    Log.i(TAG, "And so is this")
})
  

Комментарии:

1. Полезная информация! Но я все еще не понимаю, почему код не сработал при обновлении пользовательского интерфейса в рабочем потоке…

Ответ №2:

Логически поток связан с текущим основным потоком, поэтому не должно возникнуть проблем, если вы измените элемент пользовательского интерфейса в потоке, тогда как если вы создадите другой дочерний поток, используя handler или runnable, это не позволит вам изменять элементы пользовательского интерфейса внутри этих потоков. текущий поток, о котором вы упомянули, на самом деле является основным потоком, а не другим. Точно так же, как сопрограмма, есть ДИСПЕТЧЕР.ОСНОВНОЙ ваш код именно такой

Комментарии:

1. Я напечатал идентификаторы потоков внутри и снаружи блока Thread {} и получил 2 разных идентификатора. Я думаю, это означает, что они работают в разных потоках?

2. Если вы не выполняете thread = new thread, идентификаторы должны быть разными, если вы обращаетесь к одному и тому же потоку, то должны получать одинаковые идентификаторы