Android runonuithread from fragment

Полный список

— рассмотрим еще пару способов запуска Runnable в UI-потоке

Мы подробно рассмотрели Handler и увидели, что он умеет. Главное его достоинство – это умение выполнять код в UI-потоке. Существует еще пара способов выполнять Runnable в UI-потоке. Это методы:

Первые два похожи и отправляют Runnable на немедленную обработку. Я не знаю в чем их принципиальное отличие. Если у вас есть соображения на этот счет, пишите на форуме в ветке этого урока. А третий метод позволяет указать задержку выполнения Runnable.

Создадим приложение и опробуем эти методы.

Project name: P0851_RunnableUIThread
Build Target: Android 2.3.3
Application name: RunnableUIThread
Package name: ru.startandroid.develop.p0851runnableuithread
Create Activity: MainActivity

TextView, которое будем обновлять из нового потока.

В onCreate создаем новый поток. В нем мы через паузы выполняем runn1 и runn2, и планируем runn3 с задержкой в 2000 мсек, используя вышеупомянутые методы.

runn1, runn2 и runn3 – это просто Runnable, которые обновляют текст в TextView. Они должны быть выполнены в UI-потоке.

Все сохраним и запустим. Экран пустой.

Через 2 сек выполняется runn1

Еще через секунду runn2

И еще через 2 секунды срабатывает runn3, который был отложен на 2 сек.

Тем самым, если ваши алгоритмы не особо сложны, можно использовать эти методы для выполнения кода в UI-потоке. Если же нужны навороты и алгоритм достаточно сложен, то используем Handler.

На следующем уроке:

— создаем несложный пример с AsyncTask

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

runOnUiThread in fragment

Posted by: admin December 2, 2017 Leave a comment

I’m trying to convert an Activity to fragment. The error mark on runOnUiThread .
on the past:

GoogleActivityV2 extends from Activity. runOnUiThread in class
ExecuteTask. class ExecuteTask nested on activity.

GoogleActivityV2 extends from Fragment. runOnUiThread in class
ExecuteTask. class ExecuteTask nested on activity. (Error on
runOnUiThread)

here is my code

the error says:

how can I fix this error?

Try this: getActivity().runOnUiThread(new Runnable.

1) the implicit this in your call to runOnUiThread is referring to AsyncTask, not your fragment.

2) Fragment doesn’t have runOnUiThread

however Activity does:

Note that this just executes the Runnable if you’re already on the main thread, and uses a Handler if you aren’t on the main thread. You can implement a Handler in your fragment if you don’t want to worry about the context of this , it’s actually very easy:

EDIT: @rciovati is right, you are in onPostExecute , that’s already on the main thread.

android – How do I display a CalendarView in an AlertDialog?

Questions: I’m trying to display the CalendarView in an Alert Dialog, but all that shows up is the month/year and the days of the week. These are the contents of the layout file:

Читайте также:  Для чего андроид систем вебвью что это такое

How do I convert a PSD design to Android xml?

Questions: Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers. Want to improve this question? Update the question so it’s on-topic for Stack Over.

Источник

Полный список

— динамически работаем с фрагментами

Размещать статические фрагменты мы уже умеем. Но, ясно дело, что гораздо интереснее работать с ними динамически. Система позволяет нам добавлять, удалять и заменять фрагменты друг другом. При этом мы можем сохранять все эти манипуляции в BackStack и кнопкой Назад отменять. В общем, все удобно и красиво.

Создадим простое приложение с двумя фрагментами, которое будет уметь:

— добавлять первый фрагмент
— удалять первый фрагмент
— заменять первый фрагмент вторым фрагментом
— переключать режим сохранения в BackStack операций с фрагментами

Project name: P1051_FragmentDynamic
Build Target: Android 4.1
Application name: FragmentDynamic
Package name: ru.startandroid.develop.p1051fragmentdynamic
Create Activity: MainActivity

В strings.xml добавим строки:

Создаем фрагменты. Как мы помним из прошлого урока, для этого нам нужны будут layout-файлы и классы, наследующие android.app.Fragment

Все почти аналогично прошлому уроку, только убрали вызовы кучи lifecycle методов с логами.

Рисуем основное Activity.

Три кнопки для добавления, удаления и замены фрагментов. Чекбокс для включения использования BackStack. И FrameLayout – это контейнер, в котором будет происходить вся работа с фрагментами. Он должен быть типа ViewGroup. А элементы Fragment, которые мы использовали на прошлом уроке для размещения фрагментов, нам не нужны для динамической работы.

В onCreate создаем пару фрагментов и находим чекбокс.

В onClick мы получаем менеджер фрагментов с помощью метода getFragmentManager. Этот объект является основным для работы с фрагментами. Далее, чтобы добавить/удалить/заменить фрагмент, нам необходимо использовать транзакции. Они аналогичны транзакциям в БД, где мы открываем транзакцию, производим операции с БД, выполняем commit. Здесь мы открываем транзакцию, производим операции с фрагментами (добавляем, удаляем, заменяем), выполняем commit.

Итак, мы получили FragmentManager и открыли транзакцию методом beginTransaction. Далее определяем, какая кнопка была нажата:

если Add, то вызываем метод add, в который передаем id контейнера (тот самый FrameLayout из main.xml) и объект фрагмента. В итоге, в контейнер будет помещен Fragment1

если Remove, то вызываем метод remove, в который передаем объект фрагмента, который хотим убрать. В итоге, фрагмент удалится с экрана.

если Replace, то вызываем метод replace, в который передаем id контейнера и объект фрагмента. В итоге, из контейнера удалится его текущий фрагмент (если он там есть) и добавится фрагмент, указанный нами.

Далее проверяем чекбокс. Если он включен, то добавляем транзакцию в BackStack. Для этого используем метод addToBackStack. На вход можно подать строку-тэг. Я передаю null.

Ну и вызываем commit, транзакция завершена.

Давайте смотреть, что получилось. Все сохраняем, запускаем приложение.

появился первый фрагмент.

Еще раз добавим первый фрагмент – жмем Add. И жмем Replace

первый фрагмент заменился вторым.

Жмем кнопку Назад. Приложение закрылось, т.к. все эти операции с фрагментами не сохранялись в BackStack. Давайте используем эту возможность.

Снова запускаем приложение и включаем чекбокс add to Back Stack

Выполняем те же операции: Add, Remove, Add, Replace. У нас добавится первый фрагмент, удалится первый фрагмент, добавится первый фрагмент, заменится вторым. В итоге мы снова видим второй фрагмент. Теперь жмем несколько раз кнопку Назад и наблюдаем, как выполняются операции, обратные тем, что мы делали. Когда транзакции, сохраненные в стеке закончатся, кнопка Назад закроет приложение.

Т.е. все достаточно просто и понятно. Скажу еще про пару интересных моментов.

Я в этом примере выполнял всего одну операцию в каждой транзакции. Но, разумеется, их может быть больше.

Читайте также:  Как сделать свои живые обои для андроид хонор

Когда мы удаляем фрагмент и не добавляем транзакцию в BackStack, то фрагмент уничтожается. Если же транзакция добавляется в BackStack, то, при удалении, фрагмент не уничтожается (onDestroy не вызывается), а останавливается (onStop).

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

На следующем уроке:

— рассмотрим взаимодействие между Activity и ее фрагментами

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Как мы используем runOnUiThread в Android?

Я новичок в Android и пытаюсь использовать UI-Thread, поэтому я написал простое тестовое задание. Но я думаю, что что-то неправильно понял, потому что при нажатии на кнопку — приложение больше не отвечает

Ниже приведен исправленный фрагмент runThread функции.

Просто оберните его как функцию, затем вызовите эту функцию из фонового потока.

У вас есть это задом наперед. Ваше нажатие кнопки приводит к вызову runOnUiThread() , но в этом нет необходимости, поскольку обработчик щелчков уже запущен в потоке пользовательского интерфейса. Затем ваш код runOnUiThread() запускает новый фоновый поток, в котором вы пытаетесь выполнить операции пользовательского интерфейса, которые затем не выполняются.

Вместо этого просто запустите фоновый поток прямо из вашего обработчика кликов. Затем оберните звонки btn.setText() внутри звонка runOnUiThread() .

Существует несколько методов использования runOnUiThread (), позволяет увидеть все

Это мой основной поток (поток пользовательского интерфейса) под названием AndroidBasicThreadActivity, и я собираюсь обновить его из рабочего потока различными способами —

1.) Передав экземпляр Activity в качестве аргумента в рабочий поток

2.) С помощью метода представления Post (Runnable runnable) в рабочем потоке

3.) Используя класс Handler из пакета android.os. Если у нас нет контекста (this / getApplicationContext ()) или экземпляра Activity (AndroidBasicThreadActivity.this), мы должны использовать класс Handler, как показано ниже:

Если вы используете фрагмент, просто напишите

Мы используем Worker Thread, чтобы сделать приложения более плавными и избегать ANR. Возможно, нам придется обновить пользовательский интерфейс после тяжелого процесса в рабочем Tread. Пользовательский интерфейс может быть обновлен только из потока пользовательского интерфейса. В таких случаях мы используем Handler или runOnUiThread, и оба имеют метод runnable run, который выполняется в потоке пользовательского интерфейса. Метод onClick выполняется в потоке пользовательского интерфейса, поэтому здесь не нужно использовать runOnUiThread.

Использование Kotlin

В то время как в деятельности,

Используя Java ,

Вы можете использовать из этого образца:

В следующем примере мы собираемся использовать эту возможность для публикации результата поиска по синониму, который был обработан фоновым потоком.

Для достижения цели во время обратного вызова действия OnCreate мы настроим onClickListener для запуска searchTask в созданном потоке.

Когда пользователь нажимает кнопку «Поиск», мы создаем анонимный класс Runnable, который ищет слово, набранное в R.id.wordEt EditText, и запускает поток для выполнения Runnable.

Когда поиск завершится, мы создадим экземпляр Runnable SetSynonymResult, чтобы опубликовать результат обратно в синониме TextView через поток пользовательского интерфейса.

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

Читайте также:  Лучшие виртуальные машины для андроид

Источник

Android Fragment Result Listener

В Android передача данных между фрагментами может осуществляться разными способами: передача через родительскую Activity, используя ViewModel или даже Fragments API. Fragment Target API с недавних пор получил статус Deprecated и вместо него Google рекомендует использовать Fragment result API.

Что такое Fragment result API? Это новый инструмент от Google который позволяет передавать данные между фрагментами по ключу. Для этого используется FragmentManager, который в свою очередь реализует интерфейс FragmentResultOwner. FragmentResultOwner выступает в качестве центрального хранилища для данных, которые мы передаем между фрагментами.

Как это работает?

Как упоминалось выше, наш FragmentManager реализует интерфейс FragmentResultOwner, который хранит в себе ConcurrentHashMap . Эта HashMap хранит наши Bundle-ы по строковому ключу. Как только один из фрагментов подписывается (или уже подписан) то он получает результат по тому самому ключу.

Что важно знать:

  • Если какой-либо фрагмент подписывается на результат методом setResultFragmentListener() после того, как отправляющий фрагмент вызовет setFragmentResult() , то он немедленно получит результат
  • Каждую связку “Key + Result (Bundle)“ фрагмент получает только 1 раз
  • Фрагменты которые находятся в бек стеке получат результат только после того как перейдут в состояние STARTED
  • После того как фрагмент перейдет в состояние DESTROYED мы больше не сможем подписываться на ResultListener

Как это выглядит в коде?

Передача данных

Для передачи данных в другой фрагмент нам необходимо вызвать метод:

В параметры метода мы кладем ключ, который и будет нашим идентификатором для получения данных и сам Bundle. Этот Bundle будет содержать в себе передаваемые данные.

Получение данных

Для получения данных через FragmentManager мы регистрируем наш FragmentResultListener и задаем ключ по которому мы будем получать данные. Тот самый ключ который мы указывали в методе FragmentManager.setFragmentResult()

Здесь мы видим 2 аргумента: key: String и bundle: Bundle.
Первый — это тот самый ключ, по которому мы передаем сюда данные. Второй — Bundle, в котором лежат переданные данные.

Parent Fragment Manger

Выбор FragmentManager-а для передачи данных между фрагментами зависит от принимающего фрагмента:

  • Если оба фрагмента находятся в одном и том же FragmentManager (например оба фрагмента находятся в Activity), то мы должны использовать родительский FragmentManager, который хранит в себе Activity
  • Если у нас один фрагмент вложен в другой фрагмент, то для передачи данных мы используем childFragmentManager (он же родительский фрагмент для принимающего фрагмента)

Важно понимать, что наш FragmentResultListener должен находиться в общем для двух фрагментов FragmentManager-е.

Тестирование

Для тестирования отправки/получения данных через FragmentResultListener, мы можем использовать FragmentScenario API, который предоставляет нам все преимущества тестирования фрагментов в изоляции.

Передача данных

Как мы можем протестировать, что наш фрагмент корректно отправляет данные через родительский FragmentManager? Для этого нам необходимо внутри теста отправить результат и проверить, что наш FragmentResultListener получил корректные данные:

Получение данных

Для проверки корректности получения данных мы можем симулировать отправку данных, используя родительский FragmentManager. Если в отправляющем фрагменте корректно установлен FragmentResultListener мы должны получить корректные данные проверяя сам листенер или последствие их получения.

Вывод

В данный момент FragmentResultListener находится в альфе, а это значит что возможно еще будут изменения со стороны Google. Но уже сейчас видно, что это достаточно крутой инструмент, для передачи данных между фрагментами, не создавая дополнительных интерфейсов и классов. Единственным нюансом остается, пожалуй то, что не совсем понятно, как и где лучше хранить ключи где, но это не кажется таким уж большим минусом.

Для того чтоб получить возможность использовать FragmentResultListener нам нужно подключить в зависимостях версию фрагментов 1.3.0-alpha04 или новее:

Источник

Оцените статью