#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, идентификаторы должны быть разными, если вы обращаетесь к одному и тому же потоку, то должны получать одинаковые идентификаторы