getFragmentManager.findFragmentById(R.id…) возвращает null

240
03 августа 2017, 23:29

Есть две кнопки. По нажатию первой кнопки добавляется динамически фрагмент с помощью BeginTransaction(). При нажатии на вторую кнопку находится TextView с помощью getFragmentManager().getFragmentById(id...).getView()..., и меняется текст. Факт в том, что это работает. Но если объединить оба действия в одной кнопке, то фрагмент не находится, и вернётся null в getFragmentManager().getFragmentById(id...).getView().

Есть ли какие-нибудь подводные камни, которые могут быть причиной такого поведения?

Answer 1

По умолчанию (и это рекомендуемое и правильное поведение) все транзакции с фрагментами происходят асинхронно. Засим после вызова commit у транзакции добавления фрагмента он не добавляется мгновенно и при попытке обращения к нему его ещё не будет в стэке активити в активированном состоянии.

Вам надо переделать логику изменения текста в фрагменте с учётом этого поведения. В принципе пытаться трогать разметку фрагмента напрямую - плохая практика.

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

  1. Если вам надо просто задать начальный текст для фрагмента единожды - передавайте данные во фрагмент при его создании через Fragment#setArguments(Bundle args) с последующим вытаскиванием оных во фрагменте в методе onCreate через Fragment#getArguments() и устанавливайте текст в TextView в методе onCreateView фрагмента.

  2. Если вам надо менять что-то по нажатию на кнопку, например, или по к-л другому событию, то вам надо создать во фрагменте метод, который будет изменять текст в текстовом поле и вызывать этот метод из активити, получив фрагмент из FragmentManager-а, проверив, что фрагмент в активном состоянии (Fragment#isAdded() == true), чтобы не нарваться на ситуации его открепления от активити.

Если хочется прямо совсем одну за другой вызывать строки и ожидать, что фрагмент будет добавлен синхронно и к его разметке можно сразу обращаться, то можно попробовать вместо commit() у транзакции добавления фрагмента вызвать commitNow(). В теории, это даст нужный эффект. Но никто этого точно не знает, т.к. делать так - очень плохо и неправильно и засим так никто не делает, так что может это и не сработает.

Answer 2

Как тупо. Я бы мог и удалить этот запрос, но все же вдруг кому то понадобится. Вообщем. После того как добавили фрагмент и сделали commit(), как я понял, нужно" чтобы код вернулся к активити"(отрежьте мне язык), поэтому создаёте поток и запускайте его. В потоке создайте сообщение и отправьте его handler'у активити. В хендлере при нужном в сообщении выполнитея по изменению текста. Все. Ps не минусьте пожалуйста, я много не понимаю, и к такому решению на проблем пришел методом экспериментов. И ещё раз повторюсь, не удаляю потому что может пригодится кому то. Если не поймет какой бред у меня написан, то хотябы точно поймет как действовать дальше.

READ ALSO
Как работать с HashMap в JSP

Как работать с HashMap в JSP

При попытке собрать HashMap со значениями Long - ключ , Boolean - значение выскакивает ошибка "Invalid property '45' of bean class [javautil

242
Не работает Alt + insert в Android Studio

Не работает Alt + insert в Android Studio

Для генерации метода в студии нажимаю Alt + insert, на что студия вообще не реагируетХоткей использую между методами в MainActivity

223
Как преобразовать String параметр в нужный тип?

Как преобразовать String параметр в нужный тип?

Есть метод, который принимает в качестве параметра имя класса, но как StringКак можно преобразовать этот String в нужный класс?

192
Принцип работы контроллера

Принцип работы контроллера

Добрый день, так как только начал изучать Spring и даже по аналогии сделал первое web-приложение, но все равно есть вопросы, и описание в инете...

225