Как запустить фрагмент android kotlin

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 или новее:

Источник

Kotlin Android Extensions: полное руководство

Oct 9, 2018 · 7 min read

Если у вас уже есть опыт разработки приложений для Android, вероятно, вы уже устали использовать findViewById, чтобы восстанавливать view. Или, может быть, вы уже сдались и начали использовать известную библиотеку ― Butterknife. Если это ваш случай, то вы влюбитесь в Kotlin Android Extensions.

Что такое Kotlin Android Extensions?

Kotlin Android Extensions — это плагин для Kotlin, который включён в стандартный пакет. Он позволяет восстанавливать view из Activities, Fragments, и Views удивительно-бесшовным способом.

Плагин генерирует дополнительный код, который позволяет получить доступ к view в виде XML, так же, как если бы вы имели дело с properties с именем id, который вы использовали при определении структуры.

Т а кже он создаёт локальный кэш view. При первом использовании свойства, плагин выполнит стандартный findViewById. В последующем, view будет восстановлен из кэша, поэтому доступ к нему будет быстрее.

Как этим пользоваться

Посмотрим, насколько это просто. В первом примере рассмотрим activity:

Включаем Kotlin Android Extensions в наш код

Хотя плагин уже интегрирован (устанавливать новый не нужно), если вы хотите его использовать, вам нужно подключить плагин в модуль Android:

И это все что вам потребуется. Теперь вы можете начать работу с ним.

Восстанавливаем view из XML

С этого момента, восстановить view, также просто, как использовать view id, которое вы определили в XML, непосредственно в вашем activity.

Представьте, что у вас есть такой XML:

Как видно, в TextView есть id welcomeMessage .

Просто напишите следующий код в MainActivity:

Чтобы это работало, нужен специальный импорт (я написал его ниже), но IDE может автоматически импортировать его. Проще и быть не может!

Как я уже упоминал, сгенерированный код включает кэш view, поэтому, если вы повторно обратитесь к view, это не потребует выполнения findViewById снова.

Давайте посмотрим, что происходит под капотом.

Магия Kotlin Android Extensions

Когда начинаешь работать с Kotlin, действительно интересно понять байт-код, который генерируется при использовании той или иной функции. Это поможет вам понять скрытую цену ваших решений.

В меню Tools → Kotlin, вы найдёте мощный инструмент Show Kotlin Bytecode. Если кликнуть по нему, вы увидите байт-код, который будет сгенерирован, когда открытый файл класса будет скомпилирован.

Для большинства людей, байт-код не особенно полезен, но тут есть ещё одна опция: Decompile.

Эта опция покажет вам Java репрезентацию байт-кода, который был сгенерирован в Kotlin. Так, вы сможете более-менее понять, как будет выглядеть код Java, эквивалентный тому, что вы написали на Kotlin.

Я собираюсь использовать это на примере activity и посмотреть код, сгенерированный Kotlin Android Extensions.

Вот интересная часть:

Это и есть кэш view, о котором мы говорили.

При запросе view, его поиск начинается в кэше. Если view нет в кэше, то он туда будет добавлен, как только будет найден. Всё просто.

Кроме того, в код добавляется функция для очистки кэша: clearFindViewByIdCache. Её можно использовать, скажем, когда старые view уже не актуальны и вам нужно получить новые.

Тогда, эта строка:

Превращается в эту:

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

Kotlin Android Extensions ― работа с фрагментами

Этот плагин можно использовать с фрагментами.

Проблема с фрагментами заключается в том, что view может обновится, а экземпляр фрагмента останется прежним. Что произойдёт? А то, что view находящееся в кэше, перестанет быть валидным.

Давайте посмотрим код, который генерирует плагин, если мы используем его с фрагментом. Я создаю простой фрагмент, который использует тот же XML, который я написал выше:

Читайте также:  Параметры микрофона для андроид

В onViewCreated , я снова изменяю текст TextView . Что насчёт сгенерированного байт-кода?

Всё тоже самое, как и в activity, с небольшой разницей:

Когда view перестанет быть актуальным, этот метод вызовет clearFindViewByIdCache , так что мы в безопасности!

Kotlin Android extensions и Custom View

С custom view, плагин работает схожим образом. Скажем, у нас есть такой view:

Я создаю очень простое custom view и генерирую конструкторы с новым намерением, которое использует аннотацию @JvmOverloads :

В примере выше, я изменяю текст в itemTitle . Сгенерированный код должен искать view в кэше. Не имеет смысла снова копировать тот же код полностью. Вы можете наблюдать это в строке, которая изменяет текст:

Отлично! В custom views мы тоже вызываем findViewById только первый раз.

Восстанавливаем views из другого view

Последняя альтернатива, которую предлагает Kotlin Android Extensions: использовать свойства напрямую из другого view.

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

Вы также можете получить доступ к subviews напрямую, просто используя этот плагин:

Хотя плагин и может помочь заполнить import, здесь есть небольшое отличие:

Несколько вещей, которые вам нужно знать:

  • Во время компиляции, вы можете ссылаться на любое view из любого другого view. Это значит, вы можете ссылаться на view, которое не является его прямым потомком. Это плохо скажется на времени выполнения при попытке восстановить view, которого не существует.
  • В этом случае, view не кэшировано, как в случае с Activities и Fragments.

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

Если вы снова перечитаете код, который сгенерирован плагином, где вызываются свойства из view, вы увидите это:

Как видно, здесь нет запроса к кэшу. Будьте осторожны, если у вас комплексное view, и вы используете его в адаптере. Это может повлиять на производительность.

Также у вас есть альтернатива: Kotlin 1.1.4

Kotlin Android Extensions версии 1.1.4

Начиная с этой, новой версии Kotlin, в Android Extensions включили новые интересные функции: кэш в любом классе (включая ViewHolder ) и новая аннотация, названная @Parcelize . Также есть способ настраивать сгенерированный кэш.

Мы вернёмся к ним через минуту, но вам следует знать, что эти новые фичи ― не завершены, так что, вам нужно включить их с помощью build.gradle :

Применяем на ViewHolder (или любом пользовательском классе)

Теперь есть простой способ построить кэш для любого класса. Единственное требование заключается в том, чтобы класс имплементировал интерфейс LayoutContainer . Этот интерфейс предоставит view, которое плагин будет использовать, чтобы искать subviews. Представьте, что у вас есть ViewHolder, который содержит view со структурой, описанной в предыдущем примере. Всё что вам нужно сделать:

containerView ― единственное, что мы перезаписываем из интерфейса LayoutContainer . Это все что вам необходимо.

С этого момента, у вас есть доступ к views напрямую. Нет необходимости присоединять itemView, чтобы получить доступ к subviews.

Ещё раз, если вы посмотрите на сгенерированный код, вы увидите, что view берётся из кэша:

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

Kotlin Android Extension. Реализация Parcelable

С новой аннотацией @Parcelize , можно с лёгкостью имплементировать Parcelable c любым классом.

Вам нужно добавить аннотацию, а плагин сделает за вас всю сложную работу:

Далее, как вам должно быть известно, можно добавить объект к любому намерению:

И восстановить объект из намерения в любой точке (в этом случае: из activity):

Настройка кэша

В этот экспериментальный набор, включена новая фича ― аннотация @ContainerOptions . Она даёт возможность настраивать способ построения кэша, или даже предотвращать его создание классом.

По умолчанию, используется Hashmap , как мы видели ранее. Его можно заменить на SparseArray из Android framework, что может быть более эффективно в некоторых ситуациях. Или, если вам не нужен кэш для класса, по каким-то причинам, такая возможность тоже есть.

Читайте также:  Android compose image color

Вот как это использовать:

На данный момент существуют следующие варианты:

Заключение

Вы увидели, как легко работать с Android views в Kotlin. Благодаря простому плагину, можно забыть обо всём этом ужасном коде, связанном с восстановлением view. Этот плагин создаёт для нас необходимые свойства с приведением правильного типа, безо всяких проблем.

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

Источник

Урок 5. Kotlin. Добавление второго экрана в android-приложение. Передача данных через Intent

Продолжаем курс по обучению основам разработки мобильных приложений в Android Studio на языке Kotlin.

В этом уроке создадим второй экран в приложении, и настроим взаимодействие между экранами с передачей данных.

Предыдущий урок, в котором мы обрабатывали нажатия кнопок, здесь

Продолжаем разработку приложения на языке Kotlin, которое мы делали на прошлом уроке. Исходный код можно скачать на странице прошлого урока.
Пока что наше приложение имеет только один экран. В этом уроке мы добавим второе активити, которое будет отображать экран с данными, полученными на основе данных с первого экрана. При нажатии кнопки Random будет отображаться окно со случайным числом от нуля до текущего значения счетчика.

Вы узнаете

  • Как запустить новое активити с помощью интента
  • Как передать данные во второе активити через интент
  • Как получить данные, переданные через интент во втором активити

Создаем новое активити

  1. Раскройте пакет с именем com.example.android.myfirstapp по пути apps >java >com.example.android.myfirstapp.
  2. Правым кликом выберите команду File >New >Activity >Empty Activity.
  3. В окне настроек нового активити установите для него имя SecondActivity. Убедитесь, что в поле Source Language установлен Kotlin.

Также проверьте им пакета, оно должно соответствовать вашему приложению. Если вы не выделили имя пакета в меню при вызове команды добавления нового активити, установите в это поле android.example.com.myfirstapp.

4. Нажмите Finish. Android Studio создаст файл на языке Kotlin и файл макета на языке XML для нового активити.

5. Дождитесь синхронизации gradle в Android Studio.Gradle это система сборки, которая используется в Android Studio для компиляции и постройки приложения. Вы будете видеть сообщения от gradle о прогрессе сборки приложения внизу экрана.

Изучите файл манифеста

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

Изучите файл Kotlin нового активити

  1. Откройте файл SecondActivity.kt.
  2. Обратите внимание на метод onCreate(). Постмотрите на вызов setContentView(). Этот метод указывает файл макета activity_second.xml как разметку нового активити.

В этом активити мы добавим метод отображения случайного числа. Но сначала нам нужно определить поле в макете для его отображения.

Создаем макет для нового активити

Экран нового активити будет отображать заголовок и случайный номер. На вкладке дизайн редактора макетов можно увидеть, как будет выглядеть экран:


Добавьте TextView для заголовка

  1. Откройте файл activity_second.xml. Вы увидите пустой ConstraintLayout. Это макет по умолчанию для шаблона Empty Activity.
  2. Добавьте TextView из палитры компонентов. Этот TextView будет использовано для отображения заголовка вверху экрана.
  3. Ограничение верхнего края TextView установим по верхней границе окна, левый край по левой стороне, а правый край по правой стороне экрана. Нижний край не ограничиваем.
  4. Установите значение ширину match_parent, а высоту wrap_content, поэтому высота изменится в соответствии с высотой содержимого.
  5. Установите идентификатор @+id/textview_label.
  6. Установите верхний, левый и правый отступ 24dp. Левый и правый отступы могут также иметь значение «start» и «end» для поддержки локализации языков с написанием справа налево.
  7. Установите значение параметра цвета текста @color/colorPrimaryDark и размер текста 24sp.
  8. Поместите текст в TextView «Это случайное число между 0 и %1d.» Спецификатор %1dбудет заменен числом в процессе работы приложения.
  9. Поместите текст в ресурсы с именем random_heading.

Это код XML для TextView, которое отображает заголовок:

Источник

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