Внедрение зависимостей Android и использование Hilt

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

Оглавление

базовые знания

1. Что такое внедрение зависимостей?

2. Если внедрение зависимостей так просто, зачем нам разрабатывать специальный фреймворк?

3. Фреймворк внедрения зависимостей Dagger and Hilt в Android

4. Использование Эфеса

аннотации, связанные с рукоятью

основное использование рукояти

Необходимо настроить параметры

Подробное объяснение только примера кода ветки

Подробное объяснение кода ветки сложного теста (более сложное использование)

Сцены

Реализация сцены с рукоятью

код филиала провайдера

Расширенное использование Hilt

Использование ветки MultipleObjtest (один и тот же тип обеспечивает несколько реализаций)

Предопределенные квалификаторы (@ApplicationContext @ActivityContext)

Официально предоставленные компоненты генерации классов (официальная копия)

Объем компонента (официальная копия)

Привязка компонента по умолчанию (официальная копия)



базовые знания


1. Что такое внедрение зависимостей?

Классы часто должны ссылаться на другие классы. Например, Carклассу может потребоваться ссылка на Engineкласс. Эти обязательные классы называются зависимостями, и в этом примере Carкласс зависит от владения Engineэкземпляром класса для своего функционирования.

Класс может получить требуемые объекты тремя способами:

  1. Класс конструирует необходимые зависимости. В приведенном выше примере Carмы создаем и инициализируем собственный Engineэкземпляр .
  2. привезен из другого места. Вот как работают некоторые Android API, такие как Contextгеттеры и геттеры .getSystemService()
  3. Предоставляется в качестве параметра. Приложения могут предоставлять эти зависимости при создании классов или передавать их в функции, требующие индивидуальных зависимостей. В приведенном выше примере Carконструктор получит Engineв качестве параметра.

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

Ниже приведен пример. CarЧтобы выразить создание собственных Engineзависимостей без использования внедрения зависимостей, код будет выглядеть так:

class Car {

    private Engine engine = new Engine();

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-APaBp33c-1670170591309) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

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

Во-первых, после создания экземпляра класса Car он будет сопровождаться созданием экземпляра класса Engine, а это значит, что класс Car должен знать, какие условия необходимы для создания экземпляра класса Engine, в нашем примере это условия, необходимые для создания экземпляра класса PetrolEngine.

Во-вторых, Engineсильная зависимость от делает тестирование более сложным. CarИспользуйте Engineреальный экземпляр , чтобы вы не могли использовать тестовые двойники для модификации разных тестовых случаев Engine,. Чтобы уменьшить связанность, мы создаем

public class Car {   

    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }
}

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-RxW9ZHCW-1670170591311) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAAAAAICRAEAOw==)]

Теперь нам нужно только передать ссылку на объект Engine при создании экземпляра объекта Car, что означает, что связь между классом Car и классом Engine уменьшается. Классу Car больше не нужно знать, каковы условия создания экземпляра класса Engine, и класс Car может вызывать любой тип класса Engine. В этом примере, поскольку мы передаем (или внедряем) класс Engine в экземпляр Car через конструктор класса Car, мы завершили реализацию внедрения конструктора.Конечно, мы также можем напрямую внедрить в домен класса, используя метод среды внедрения зависимостей. Выше приведена концепция внедрения зависимостей. Идея состоит в том, чтобы передать зависимости непосредственно классу, вместо того, чтобы класс инициализировал зависимости.

2. Если внедрение зависимостей так просто, зачем нам разрабатывать специальный фреймворк?

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

В реальном проекте код может состоять из десятков тысяч строк и более.Разработкой занимаются одновременно несколько человек и несколько команд, а также кадровые перестановки, долгосрочное техническое обслуживание и другие факторы, усложняющие реализацию внедрения зависимостей: 1) Количество: существуют десятки или сотни зависимостей между большим количеством объектов, таких как моделирование и программирование для автомобилей
.
2) Отношения зависимости сложны: с точки зрения логики и времени существуют разные уровни зависимостей объектов в логике, такие как дочерние объекты и внучатые объекты); с точки зрения времени, как гарантировать, что входящие объекты были созданы. В сложных проектах несколько модулей часто разрабатываются разными людьми и командами, что усложняет взаимозависимости.
Чтобы углубиться, например, для управления циклом объявления объектов, для безопасности или восстановления ресурсов, объекты нужно вовремя уничтожать, чтобы контролировать сферу использования объектов. Как персоналу после обслуживания, а не первоначальным разработчикам, правильно использовать каждый объект и избежать введения ошибочной логики или избыточного кода (исходный код невозможно понять, поэтому идите и напишите новый код. Это тоже очень вредно).

Возвращаясь к предыдущему примеру, предположим, что класс Engine также имеет набор необходимых ему зависимостей, таких как: коленчатый вал, поршень, блок и головка. Если мы будем следовать принципу внедрения зависимостей, мы будем передавать экземпляры этих классов в класс Engine, и это нормально.Нам нужно только сначала создать эти объекты, а затем передать их в объект Engine при создании экземпляра класса Engine.Наконец, мы все еще можем передать экземпляр класса Engine в класс Car.

Теперь давайте усложним этот пример, если мы хотим создать классы для каждой части класса Engine, то мы можем легко создать из-за этого сотни классов.

изображение[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-mnVpbB66-1670170591311) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]Редактировать

Из нашего примера мы можем понять недостатки внедрения внедрения зависимостей простым способом: сложные зависимости, много шаблонного кода. Вот почему инъекция зависимостей не прижилась раньше. Но нельзя отрицать, что внедрение зависимостей действительно стоит использовать, и из-за этого несколько крупных коров разработали фреймворки внедрения зависимостей для решения проблем традиционного использования внедрения зависимостей. Эти фреймворки значительно упрощают процесс настройки зависимостей и создания объектов factory и builder, делая его интуитивно понятным и простым.

3. Фреймворк внедрения зависимостей Dagger and Hilt в Android

1. Dagger — популярная библиотека внедрения зависимостей для Java, Kotlin и Android, поддерживаемая Google. Dagger создает для вас графы зависимостей и управляет ими, упрощая использование внедрения зависимостей в вашем приложении. Он предоставляет полностью статические зависимости и зависимости времени компиляции, решая многие проблемы разработки и производительности решений на основе отражения, таких как Guice .

2. Hilt — рекомендуемая библиотека Jetpack для внедрения зависимостей в Android. Hilt определяет стандартный способ выполнения внедрения зависимостей в вашем приложении, предоставляя контейнер для каждого класса Android в вашем проекте и автоматически управляя его жизненным циклом.

Построенный на основе популярной библиотеки DI Dagger , Hilt обладает такими преимуществами, как точность во время компиляции, производительность во время выполнения, масштабируемость и поддержка Android Studio, которые предоставляет Dagger.

Ниже мы представим использование Hilt

4. Использование Эфеса

1. Добавьте подключаемый модуль hilt-android-gradle-plugin в файл build.gradle в корневом каталоге проекта.

plugins {
  
  id 'com.google.dagger.hilt.android' version '2.44' apply false
}

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-OGFPNYM0-1670170591312) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

2. Примените плагин Gradle и app/build.gradleдобавьте в файл следующие зависимости:

plugins {
  id 'kotlin-kapt'
  id 'com.google.dagger.hilt.android'
}

android {
  ..
}

dependencies {
  implementation "com.google.dagger:hilt-android:2.44"
  kapt "com.google.dagger:hilt-compiler:2.44"
}

//允许自动更新代码
kapt {
  correctErrorTypes true
}

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-0EAprxq4-1670170591313) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

аннотации, связанные с рукоятью

@HiltAndroidApp: все приложения, использующие рукоятку, должны использовать эту аннотацию, которая используется в классе Application.

@AndroidEntryPoint@AndroidEntryPoint: Hilt может предоставлять зависимости для других классов Android с аннотациями, @AndroidEntryPoint можно использовать для четырех основных компонентов и представления.

@Inject: получить зависимости

основное использование рукояти

Необходимо настроить параметры

Добавить аннотации к приложению

@HiltAndroidApp
class App: Application() {
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-Fo14hAvs-1670170591314) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

Подробное объяснение только примера кода ветки

Функция, реализованная этой ветвью, заключается в внедрении объекта Car в MainActivity.

1. Сначала добавьте необходимые параметры конфигурации

2. Код объекта автомобиля:

class Car @Inject constructor() {
    fun drive(name: String) {
        println("小汽车嘟嘟嘟")
    }
}
//Car的构造使用@Inject表示Car对象是一个可被注入的对象

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-fEqQ0njn-1670170591315) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

3. Код MainActivity:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var car: Car//Car对象使用@Inject注解,会自动被实例化,这里必须使用lateinit延迟初始化才会有效
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        car.drive("mage")
    }
}

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-4sj06GCP-1670170591316) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

Подробное объяснение кода ветки сложного теста (более сложное использование)

Сцены

В ветке onlysampletest мы просто внедрили Car в MainActivity, но фактический бизнес-сценарий, с которым мы сталкиваемся, должен быть гораздо более ответственным, чем этот. Например, теперь мы хотим назначить водителя для Car. В обычных обстоятельствах мы создадим объект Driver Driver, а затем передадим объект Driver Driver в конструктор объекта Car.

Но это явно не то, чего хочет рукоятка

Реализация сцены с рукоятью

Поговорим о реализации hilt:

Сначала нам нужно создать несколько классов

App Car Driver DriverImpl DriverModule MainActivity

В конструкции Car будет передана реализация Driver.

Драйвер — это абстрактная реализация драйвера и интерфейс.

DriverImple — это класс реализации Driver, который может быть любым конкретным драйвером.

DriverModule отвечает за предоставление правил внедрения класса Driver.

Вот отображение кода:

1. Добавьте обязательные параметры конфигурации

2. Реализация автомобиля

class Car @Inject constructor(val driver: Driver) {//Car的构造函数中增加了Driver司机对象的实现
    fun drive() {
        println("老司机${driver.name} 在线开车")
    }
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-tJ7HprRF-1670170591317) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

2. Интерфейс драйвера

interface Driver {
    val name :String
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-dh49Nq1D-1670170591317) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

3. Реализация интерфейса драйвера DriverImple

class DriverImpl @Inject constructor() : Driver {//因为DriverImpl需要被注入到Car的构造中,所以DriverImpl本身一个是被注入着,他的构造中也需要使用@Inject注解
    override val name: String
        get() = "mage"
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-1vqCh7Or-1670170591318) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

4. DriverModule настраивает правила внедрения драйверов

@Module//必须配置的注解,表示这个对象是Module的配置规则
@InstallIn(ActivityComponent::class)//表示这个module中的配置是用来注入到Activity中的
abstract class DriverModule {
    @Binds
    abstract fun bindDriver(driver: DriverImpl): Driver//形参中的DriverImple表示真实要注入Car构造方法中的Driver实现,返回值Driver表示DriverImple所实现的抽象接口
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-vtt8aMRr-1670170591319) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

5. Код основной активности

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var car: Car//这里必须使用lateinit延迟初始化才会有效
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        car.drive()
    }
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-umDgnbT0-1670170591320) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

код филиала провайдера

Ветка провайдера — это интерпретация аннотации @Provides.

В комплексном тесте мы используем аннотацию @Binds для совместного использования наших пользовательских объектов, поэтому что нам делать, если объекты для совместного использования не созданы нами (например, OkhttpClient и Request), а @Provides можно использовать в это время. Пример кода выглядит следующим образом:

1. Добавьте обязательные параметры конфигурации

2. Создайте OkhttpModule

@Module
@InstallIn(ActivityComponent::class)
object OkhttpModule {
    @Provides
    fun provideOkhttpClient(
        // Potential dependencies of this type
    ): OkHttpClient {
        return OkHttpClient()
    }

    @Provides
    fun providdeRequest():Request{
        return Request.Builder()
            .get()
            .url("https://developer.android.google.cn/training/dependency-injection/hilt-android")
            .build()
    }
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-vgOJXjgz-1670170591320) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

3. Код основной активности

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var client: OkHttpClient
    @Inject
    lateinit var request: Request
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btn.setOnClickListener {
            client.newCall(request).enqueue(object :Callback{
                override fun onFailure(call: Call, e: IOException) {
                    println("请求失败")
                }
                override fun onResponse(call: Call, response: Response) {
                    println("请求成功")
                }
            })
        }
    }
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-t1xaDGcI-1670170591321) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

Расширенное использование Hilt

Использование ветки MultipleObjtest (один и тот же тип обеспечивает несколько реализаций)

В некоторых сценариях мы можем предоставить несколько экземпляров одного и того же типа объекта, и в это время требуется особая обработка. Пример:

Например, теперь мы предоставляем абстракцию интерфейса Car, а затем предоставляем Car два интерфейса для реализации TruckCar и TaxtCar. Код в MainActivity выглядит следующим образом:

@Inject
lateinit var truck: Car

@Inject
lateinit var taxi: Car
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-QWHLo80Y-1670170591321) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

Поскольку все внедряемые типы объектов относятся к Car, в процессе компиляции невозможно отличить, хотим ли мы внедрить TruckCar или TaxtCar, поэтому код сообщит об ошибке в процессе компиляции. Чтобы решить эту проблему, вам нужно использовать пользовательские аннотации, Вот код:

1. Необходимо настроить параметры

2. Код автомобиля, TruckCar, TaxiCar

interface Car {
    fun drive(name:String)
}
class TruckCar @Inject  constructor():Car{
    override fun drive(name: String) {
        println("$name 卡车老司机开车,呜呜")
    }

}
class TaxiCar @Inject  constructor():Car{
    override fun drive(name: String) {
        println("$name 出租车老司机开车,呜呜")
    }

}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-FDzLva9x-1670170591322) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

3. Код CarModule

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class Truck//卡车类注入标记

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class Taxi//出租车类注入标记

@Module
@InstallIn(ActivityComponent::class)
class CarModule {

    @Truck//卡车类生成规则加上这个注解,注入的时候也是用该注解编译器就可以知道我们真实想注入的类型是TruckCar
    @Provides
    fun bindTruckCar(truckCar: TruckCar): Car {
        return TruckCar()
    }

    @Taxi//出租车类生成规则加上这个注解,注入的时候也是用该注解编译器就可以知道我们真实想注入的类型是TaxiCar
    @Provides
    fun bindTaxtCar(taxiCar: TaxiCar): Car {
        return TaxiCar()
    }
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-bVSS35qb-1670170591323) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAAAAAICRAEAOw==)]

Предопределенные квалификаторы (@ApplicationContext @ActivityContext)

Скопируйте официальное объяснение, Hilt предоставляет некоторые предопределенные квалификаторы. ContextНапример, Hilt предоставляет квалификаторы @ApplicationContextи , так как вам может понадобиться класс из вашего приложения или Activity .@ActivityContext

Пример кода:

1. Необходимо настроить параметры

2, категория Базовая информация

class BaseInfo @Inject constructor(@ActivityContext private val context: Context) {
    fun printPackageName(){
        println("应用包名 ${context.packageName}")
    }
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-xnTwShZA-1670170591324) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

3. Класс MainActivity

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var baseInfo: BaseInfo
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btn.setOnClickListener {
            baseInfo.printPackageName()
        }
    }
}
复制代码

[Не удалось передать изображение по внешней ссылке, исходный сайт может иметь механизм защиты от кражи ссылок, рекомендуется сохранить изображение и загрузить его напрямую (img-BFI0JKEE-1670170591324) (data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAAAAAICRAEAOw==)]

Официально предоставленные компоненты генерации классов (официальная копия)

Для каждого класса Android, из которого вы можете выполнять внедрение полей, существует связанный компонент Hilt, на который вы можете ссылаться в @InstallInаннотациях. Каждый компонент Hilt отвечает за внедрение своих привязок в соответствующий класс Android.

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

ApplicationComponent Application
ActivityRetainedComponent ViewModel Действуйте на ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent @WithFragmentBindingsАннотировано сView
ServiceComponent Service

Объем компонента (официальная копия)

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

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

Например, когда областью действия компонента является @Singleton, компонент является глобальным синглтоном.

Например, когда областью действия компонента является @ActivityScoped, этот компонент является тем же экземпляром объекта в том же действии.

Таким образом, компонент по умолчанию и область действия

Класс Android сгенерированные компоненты объем
Application ApplicationComponent @Singleton
View Model ActivityRetainedComponent @ActivityRetainedScope
Activity ActivityComponent @ActivityScoped
Fragment FragmentComponent @FragmentScoped
View ViewComponent @ViewScoped
@WithFragmentBindingsАннотировано сView ViewWithFragmentComponent @ViewScoped
Service ServiceComponent @ServiceScoped

Привязка компонента по умолчанию (официальная копия)

Каждый компонент Hilt поставляется с набором привязок по умолчанию, которые Hilt может внедрять в качестве зависимостей в ваши собственные настраиваемые привязки. Обратите внимание, что эти привязки соответствуют общим типам Activity и Fragment, а не какому-либо конкретному подклассу. Это связано с тем, что Hilt внедряет все действия, используя одно определение компонента действия. Каждое действие имеет отдельный экземпляр этого компонента.

Компоненты Android привязка по умолчанию
ApplicationComponent Application
ActivityRetainedComponent Application
ActivityComponent ApplicationиActivity
FragmentComponent Application, ActivityиFragment
ViewComponent Application, ActivityиView
ViewWithFragmentComponent Application, Activity, FragmentиView
ServiceComponent ApplicationиService

Автор: Li Xiaoxin
Исходная ссылка: внедрение зависимостей Android и использование блога Hilt_lixiaoxin-12 — блога CSDN

Guess you like

Origin blog.csdn.net/fjnu_se/article/details/128179765