Русский
Русский
English
Статистика
Реклама

Android app development

Перевод Практическое руководство по использованию Hilt с Kotlin

09.12.2020 18:14:11 | Автор: admin

Будущих учащихся на курсе "Android Developer. Professional" приглашаем посетить открытый урок на тему "Пишем Gradle Plugin"


А также делимся переводом полезной статьи.


Простой способ использовать внедрение зависимостей в приложениях для Android

Hilt это новая библиотека для внедрения зависимостей, построенная на основеDagger. Она позволяет использовать возможности Dagger в приложениях для Android упрощенным способом. В этом руководстве описаны основные функциональные возможности библиотеки и приведено несколько фрагментов кода, которые помогут вам начать использовать Hilt в своих проектах.

Настройка Hilt

Чтобы настроить Hilt в своем приложении, сначала выполните указания из руководства: Установка Gradle Build.

После установки всех необходимых элементов и подключаемых модулей, чтобы использовать Hilt, задайте своему классуApplicationаннотацию@HiltAndroidApp. Больше ничего делать не нужно, а также не нужно вызывать Hilt напрямую.

Определение и внедрение зависимостей

При написании кода, в котором используется внедрение зависимостей, есть два основных компонента, которые следует учитывать:

  1. Классы, имеющие зависимости, которые вы собираетесь внедрить.

  2. Классы, которые могут быть внедрены как зависимости.

Они не являются взаимоисключающими: во многих случаях класс одновременно является внедряемым и имеет зависимости.

Как сделать зависимость внедряемой

Чтобы в Hilt сделать объект внедряемым, необходимо указать для Hilt способ создания экземпляра этого объекта. Такие инструкции называютсяпривязками.

Есть три способа определения привязки в Hilt.

  1. Добавить к конструктору аннотацию@Inject

  2. Использовать@Bindsв модуле

  3. Использовать@Providesв модуле

Добавление к конструктору аннотации@Inject

У любого класса может быть конструктор с аннотацией@Inject, что позволяет использовать его в качестве зависимости в любом месте проекта.

Использование модуля

Два других способа преобразования объектов во внедряемые в Hilt связаны с использованием модулей.

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

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

Модули устанавливаются вкомпонент Hilt, который указывается с помощью аннотации@InstallIn. Я дам более подробное объяснение ниже.

Вариант 1: использовать@Binds, чтобы создать привязку для интерфейса

Если вы хотите использовать в своем кодеOatMilk, когда требуетсяMilk, создайте абстрактный метод внутри модуля и задайте ему аннотацию@Binds. Обращаю внимание, чтобы этот вариант работал, сам OatMilk должен быть внедряемым. Для этого его конструктору необходимо задать аннотацию@Inject.

Вариант 2: создать функцию-фабрику с помощью@Provides

Когда экземпляр нельзя сконструировать напрямую, можно создать поставщик. Поставщик это функция-фабрика, которая возвращает экземпляр объекта.

В качестве примера можно привести системную службу, скажемConnectivityManager, которую необходимо получить из контекста.

ОбъектContextявляется внедряемым по умолчанию, если задать ему аннотацию@ApplicationContextлибо@ActivityContext.

Внедрение зависимости

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

  1. Как параметры конструктора

  2. Как поля

Как параметры конструктора

Если пометить конструктор аннотацией @Inject, Hilt внедрит все параметры в соответствии с привязками, которые вы определили для этих типов.

Как поля

Если класс является точкой входа, указанной с использованием аннотации@AndroidEntryPoint (подробнее об этом рассказано в следующем разделе), внедрены будут все поля, помеченные аннотацией@Inject.

Поля, помеченные аннотацией@Inject,должны быть общедоступными. Также удобно пометить их модификатором lateinit, чтобы не пришлось обеспечивать поддержку ими пустого значения, поскольку перед внедрением они имеют исходное значениеnull.

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

Прочие важные понятия

Точка входа

Помните, я сказал, что во многих случаях класс создается путем внедренияиимеет зависимости, внедренные в него? В некоторых случаях у вас будет класс, который несоздаетсяпутем внедрения зависимости, но имеет зависимости, внедренные в него. Хорошим примером этого являются активности, которые в стандартной ситуации создаются платформой Android, а не библиотекой Hilt.

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

Точка входа Android

Большинство ваших точек входа будут так называемымиточками входа Android:

  • Activity

  • Fragment

  • View

  • Service

  • BroadcastReceiver

Если это так, такой точке входа следует задать аннотацию@AndroidEntryPoint.

Другие точки входа

Большинству приложений обычно нужны только точки входа Android, но если вы взаимодействуете с библиотеками, не работающими с Dagger, или с компонентами Android, которые пока не поддерживаются в Hilt, то вам может потребоваться создать собственную точку входа для доступа к графику Hilt вручную. Можете ознакомиться с инструкциями по преобразованию произвольных классов в точки входа.

ViewModel

ViewModel это особый случай: экземпляры этого класса не создаются напрямую, так как они должны создаваться платформой, при этом он также не является точкой входа Android. Вместо этого с классамиViewModel используют специальную аннотацию@ViewModelInject, которая позволяет Hilt внедрять в них зависимости, когда они создаются с помощью выраженияby viewModels(). Это похоже на то, как@Injectработает для других классов.

Если вам требуется доступ к состоянию, сохраняемому в классе ViewModel, внедритеSavedStateHandleв качестве параметра конструктора, добавив аннотацию@Assisted.

Чтобы использовать@ViewModelInject, вам нужно будет добавить еще несколько зависимостей. Дополнительные сведения см. в статье: Интеграции Hilt и Jetpack.

Компоненты

Каждый модуль устанавливается внутрикомпонента Hilt, который указывается с помощью аннотации@InstallIn(<компонент>). Компонент модуля используется главным образом для предотвращения случайного внедрения зависимости не в том месте. Например, аннотация @InstallIn(ServiceComponent.class) не позволит использовать привязки и поставщики, имеющиеся в соответствующем модуле, внутри активности.

Кроме того, использование привязки можно ограничить пределами компонента, в котором находится модуль. Что приводит меня к

Области

По умолчанию у привязок нет областей. В приведенном выше примере это означает, что каждый раз, когда вы внедряетеMilk, вы получаете новый экземплярOatMilk. Если добавить аннотацию@ActivityScoped,область использования привязки будет ограничена пределами ActivityComponent.

Теперь, когда у модуля есть область действия, Hilt будет создавать только одинOatMilkна экземпляр активности. Кроме того, этот экземплярOatMilkбудет привязан к жизненному циклу этой активности он будет создаваться при вызовеonCreate()активности и уничтожаться при вызовеonDestroy()активности.

В этом случае иmilk, иmoreMilkбудут указывать на один и тот же экземплярOatMilk. Однако, если у вас несколько экземпляровLatteActivity, у каждого из них будет собственный экземплярOatMilk.

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

Область зависит от компонента, в который установлен ваш модуль. Например,@ActivityScopedможно применить только к привязкам, находящимся внутри модуля, который установлен внутриActivityComponent.

Область также определяет жизненный цикл внедренных экземпляров: в данном случае одиночный экземплярMilk, используемыйFridgeиLatteActivity, создается, когдаonCreate()вызывается дляLatteActivity, и уничтожается в егоonDestroy(). Это также означает, что нашMilkне переживет изменение конфигурации, поскольку при этом вызываетсяonDestroy()для активности. Преодолеть это можно путем использования области с более длительным жизненным циклом, например@ActivityRetainedScope.

Список имеющихся областей, компонентов, которым они соответствуют, и жизненных циклов, которым они следуют, приведен в статье:Компоненты Hilt.

Внедрение поставщика

Иногда требуется более прямой контроль над созданием внедренных экземпляров. Например, вам требуется, чтобы один или несколько экземпляров какого-то объекта внедрялись только тогда, когда они нужны, в соответствии с бизнес-логикой. В этом случае можно использоватьdagger.Provider.

Внедрение поставщика можно использовать независимо от того, чем является зависимость и как она внедряется. Любой объект, который можно внедрить, можно обернуть вProvider<>, чтобы для него использовалось внедрение поставщика.

Фреймворки внедрения зависимостей (такие как Dagger иGuice) обычно применяются в крупномасштабных, сложных проектах. В то же время библиотека Hilt, будучи простой в освоении и настройке, предоставляет все возможности Dagger в пакете, который можно использовать в приложениях любого типа, независимо от размеров кодовой базы.

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


Узнать подробнее о курсе "Android Developer. Professional"

Записаться на открытый урок "Пишем Gradle Plugin"


Прямо сейчас вOTUSстартовалановогодняя распродажа. Скидка распространяется абсолютно на все курсы. Сделайте подарок себе или близким -переходите на сайти забирайте курс со скидкой. А в качестве бонуса предлагаем зарегистрироваться на абсолютнобесплатные демо-уроки:

ЗАБРАТЬ СКИДКУ

Подробнее..

Перевод Полируем UI в Android StateListAnimator

08.09.2020 18:17:15 | Автор: admin
Привет, хабр! В преддверии старта курса Android Developer. Professional мы подготовили для вас перевод еще одного интересного материала.




Большую часть времени разработки нашего Android-приложения мы тратим отнюдь не на работу над пользовательским интерфейсом мы просто накидываем вьюх и начинаем писать код. Я заметил, что большинство из нас не особо заботится о пользовательском интерфейсе. И я считаю, что это в корне неправильно. Разработчики мобильных приложений должны заботиться также и о UI/UX. Я не говорю будьте экспертом в мобильном UI, но вы должны понимать язык дизайна и его концепции.

Ранее я написал статью о тенях в материальном дизайне и получил много хороших отзывов. Я хочу поблагодарить всех вас. Освоение теней в Android рассказывает о высоте (elevation) и тени (shadow) в Android. Там же я показал, как дополнял ими свою UI библиотеку с открытым исходным кодом. (Scaling Layout).

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

Содержание


В этой статье рассматриваются следующие темы:


Состояния Drawable


В Android есть 17 различных состояний для Drawable.



Возможно, мы даже никогда не встречали некоторые из них. Я не собираюсь углубляться в каждое состояние. В большинстве случаев мы используем pressed, enabled, windows focused, checked и т. д. Если мы не объявляем состояние для drawable, то подразумевается, что это состояние по умолчанию в Android.

Нам нужно понимать эти состояния, чтобы написать наш собственный StateListDrawable.

StateListDrawable


Это, по сути, список drawable элементов, где каждый элемент имеет свое собственное состояние. Для создания StateListDrawable нам нужно создать XML-файл в папке res/drawable.

<item android:drawable="@drawable/i" android:state_pressed="true"/>


Это элемент (item). Он имеет два свойства. Drawable и State.

<selector>   <item       android:drawable="@drawable/p"       android:state_pressed="true"/>   <item       android:drawable="@drawable/default"/></selector>


Это StateListDrawable. Если мы не объявляем состояние (state) для элемента, как я уже упоминал ранее, это означает, что это состояние по умолчанию.

Могу ли я использовать ShapeDrawable?


Да. Вместо использования android:drawable вы можете добавить к своему элементу произвольную форму. Вот элемент с ShapeDrawable.


StateListDrawable

Вы можете использовать StateListDrawable с уровня API 1. Таким образом, для StateListDrawable нет ограничений уровня API.

<View   android:layout_width="50dp"   android:layout_height="50dp"   android:foreground="@drawable/state_list_drawable"   android:clickable="true"/>


Вот и все. Теперь у нашего вью есть состояние. Когда пользователь нажимает на него, его цвет будет изменен. Когда пользователь отпустит его, он будет иметь состояние и цвет по умолчанию.

Но погодите секундочку. Clickable? Зачем мы добавили этот атрибут? Нам что, еще и его добавлять нужно? Да. Но только для пользовательских вью. Чтобы это выяснить, нужно время. Кнопки отлично работают без добавления clickable, потому что они по умолчанию clickable. Но если вы хотите использовать StateListDrawable для View, ImageView, Custom View и т. д., вам необходимо добавить атрибут clickable.



StateListDrawable

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

StateListAnimator


Помните, что когда вы нажимаете FloatingActionButton, его Z значение увеличивается из-за анимации. Это StateListAnimator так сказать за кадром. У некоторых виджетов материального дизайна есть собственный StateListAnimator внутри.

Давайте проясним это с помощью вопроса на StackOverflow.



(Как удалить границу/тень с кнопок lollipop).

Если у виджетов материального дизайна есть собственный StateListAnimator внутри, мы можем установить для них значение null, чтобы удалить эти функцию (не рекомендую, она разработана не просто так.) И сейчас ответ звучит куда более логично.


(Lollipop имеет небольшую неприятную функцию, называемую stateListAnimator, которая обрабатывает высоту кнопок, производя тени.

Удалите stateListAnimator, чтобы избавиться от теней.

У вас есть несколько вариантов как сделать это:

В коде:

button.setStateListAnimator(null);)




Итак, а как мы можем создать его?

Чтобы понять StateListAnimator, нам нужно понять анимацию свойств объекта (property animation). Я не собираюсь углубляться в анимацию свойств в этой статье. Но по крайней мере, я хочу показать вам основы.

Анимация свойств


Вот самый простой пример свойства в объекте. X это свойство.

class MyObject{    private int x;    public int getX() {       return x;   }    public void setX(int x) {       this.x = x;   }}


Система property animation это надежный фреймворк, который позволяет анимировать практически все. Вы можете определить анимацию для изменения любого свойства объекта с течением времени, независимо от того, отображается ли он на экране или нет. Анимация свойства изменяет значение свойства (поля в объекте) в течение заданного периода времени.



X это свойство. Т время. Во время анимации свойство X обновляется в заданное время. В целом так работает анимация свойств. Вместо коробки может быть вью или любой объект.

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

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

  • У вас есть объект (любой класс с каким-нибудь свойством).
  • Вы не хотите наблюдать за слушателем ValueAnimator.
  • Вы хотите обновлять свойство объекта автоматически.


Итак, если у нас есть вью (которое является объектом), и мы хотим обновить свойство вью (координата x, координата y, rotation, translation или любое другое свойство, для которого у вью есть геттер/сеттер), мы можем использовать ObjectAnimator. Продолжим создание StateListAnimator.

<selector>    <item android:state_pressed="true">      <objectAnimator           android:duration="200"           android:propertyName="translationZ"           android:valueTo="6dp"           android:valueType="floatType" />   </item>    <item>      <objectAnimator           android:duration="200"           android:propertyName="translationZ"           android:valueTo="0dp"           android:valueType="floatType"/>   </item> </selector>



Кнопка FAB анимирует свое свойство translationZ при нажатии и разжатии.

Как я сказал ранее, мы можем использовать свойство объекта напрямую, не наблюдая за изменениями в аниматоре. Каждый View имеет свойство translationZ. Таким образом, мы можем напрямую анимировать translationZ с помощью ObjectAnimator.

Мы можем также объединить несколько <objectAnimator>-ов в <set>. Изменим еще одно свойство View. Scale X и Scale Y.

Вот результат! Теперь она также увеличивается при нажатии пользователем. А вот коммит.



Вы также можете определить другие свойства в своем animator.xml. Здесь вы можете найти больше информации об использовании ObjectAnimator.

Вот и все. Я планирую написать еще что-нибудь о ValueAnimator и ObjectAnimator. Это отличное API для анимации объекта.

Успешного вам кодинга!
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru