Можно ли считывать данные из элементов пользовательского интерфейса в другом потоке?

#android #multithreading

#Android #многопоточность

Вопрос:

Я только что узнал, что часть моего кода (неиндентированно) выполняется в рабочем потоке и считывает некоторые данные из элементов пользовательского интерфейса:
например checkbox.isChecked() , textView.getText()

и, к моему удивлению, это работает просто отлично…
Я ожидал, что произойдет сбой с исключением (например, следующее исключение, которое я получаю, когда хочу записать в элементы пользовательского интерфейса):

 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
 

Согласно документам Android:

Только объекты, запущенные в потоке пользовательского интерфейса, имеют доступ к другим объектам в этом потоке. Поскольку задачи, которые вы запускаете в потоке из пула потоков, не выполняются в вашем потоке пользовательского интерфейса, они не имеют доступа к объектам пользовательского интерфейса.

Итак, действительно ли можно читать данные из элементов пользовательского интерфейса из других потоков?
Если нет: почему нет исключения?

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

1. коснуться его представлений означает изменить

Ответ №1:

действительно ли можно считывать данные из элементов пользовательского интерфейса из других потоков?

Нет, но не по тем причинам, о которых вы можете подумать.

Во-первых, как только вы разветвляете фоновый поток, пользователь может нажать НАЗАД или иным образом сделать что-то, что разрушит вашу активность. Небезопасно пытаться использовать виджеты уничтоженной активности.

Во-вторых, в View классе или его подклассах практически отсутствует логика синхронизации потоков. Основной поток приложения может изменять данные одновременно с тем, как вы пытаетесь их использовать, что приводит к возможным проблемам параллелизма.

Я бы передал данные из виджетов в поток (например, конструктор потоков).

почему нет исключения?

AFAIK, это конкретное исключение выдается только для установщиков или других вещей, которые изменяют содержимое виджета. Это не означает, что любой код, который не вызывает это исключение, гарантированно безопасен.

Ответ №2:

Вы не можете перерисовать (аннулировать) свой View внешний основной поток, который также является потоком пользовательского интерфейса. Установка текста для TextView также вызывает перерисовку вида ofc… Но получение текста просто возвращает String (или Editable ?), Поэтому он работает…

Обратите внимание, что существуют некоторые другие ограничения и ограничения, например, когда вы переходите EditText к некоторым AsyncTask , но пока он работает с завершением main Activity (удерживая переданный просмотр), вы можете получить NPE, потому что view также исчез… В этом и подобных случаях WeakReferences очень полезны