Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Dagger2

## Задача

### Реализуйте ApplicationComponent
Это корень нашего дерева компонентов. Инициализируется в классе App, прокидывает в граф через Component Dependencies/Subcomponents ниже по графу следующие сущности:
- Context(Application) до FragmentProducerComponent и FragmentReceiverComponent.
Expand All @@ -12,3 +16,8 @@
Коммуникацию между Producer и Receiver осуществите через канал/StateFlow/Subject либо другую реализацию обсервера которая уже есть в графе. ViewModelProducer должна отправлять эвенты, ViewModelReceiver должна получать эвенты. Обсерверы должны прокидываться в конструкторы вьюмоделей и существовать в единственном экземпляре в Activity.
Флоу отправки эвента выглядит следующим образом:
Клик на кнопку button в FragmentProducer -> вызов метода вьюмодели -> проброс евента в обсервер -> евент ловится на стороне ViewModelReceiver -> евент передается FragmentReceiver и вызывается функция ru.otus.daggerhomework.FragmentReceiver#populateColor

## Решение

Решение базируется на Component Dependencies.
В качестве канала коммуникации между франментами использован Channel.
16 changes: 16 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'

// dagger2
implementation 'com.google.dagger:dagger:2.42'
kapt 'com.google.dagger:dagger-compiler:2.42'

// coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'

//
/* lifecircle */
def lifecycle_version = "2.5.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

/* extensions to simplify the fragment API */
implementation "androidx.fragment:fragment-ktx:1.5.5"
}
8 changes: 5 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ru.otus.daggerhomework">

<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DaggerHomework">
<activity android:name=".MainActivity">
<activity
android:name=".presentation.Activity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
22 changes: 21 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/App.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
package ru.otus.daggerhomework

import android.app.Application
import android.content.Context
import ru.otus.daggerhomework.di.ApplicationComponent
import ru.otus.daggerhomework.di.DaggerApplicationComponent

class App :Application() {
/**
* `Custom application` приложения
*/
class App : Application() {

private lateinit var applicationComponent: ApplicationComponent

override fun onCreate() {
super.onCreate()
applicationComponent = DaggerApplicationComponent.factory().create(this)
}

companion object {

/** Получить [applicationComponent] на основе [context] */
fun appComponent(context: Context) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не понял зачем тут в параметрах контекст, у тебя же во монолит, доступ к App есть везде, просто можно геттер на ApplicationComponent написать

(context.applicationContext as App).applicationComponent
}
}

This file was deleted.

20 changes: 0 additions & 20 deletions app/src/main/java/ru/otus/daggerhomework/ColorGenerator.kt

This file was deleted.

26 changes: 0 additions & 26 deletions app/src/main/java/ru/otus/daggerhomework/FragmentProducer.kt

This file was deleted.

31 changes: 0 additions & 31 deletions app/src/main/java/ru/otus/daggerhomework/FragmentReceiver.kt

This file was deleted.

12 changes: 0 additions & 12 deletions app/src/main/java/ru/otus/daggerhomework/MainActivity.kt

This file was deleted.

16 changes: 0 additions & 16 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelProducer.kt

This file was deleted.

15 changes: 0 additions & 15 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelReceiver.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package ru.otus.daggerhomework.di

import android.content.Context
import dagger.BindsInstance
import dagger.Component
import ru.otus.daggerhomework.di.utils.qualifiers.ApplicationContext

/**
* `Dagger` [Component] приложения
*/
@Component
interface ApplicationComponent {

/** `Application` контекст */
@ApplicationContext
fun context(): Context

@Component.Factory
interface Factory {
fun create(@BindsInstance @ApplicationContext context: Context): ApplicationComponent
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package ru.otus.daggerhomework.di.main

import android.content.Context
import dagger.BindsInstance
import dagger.Component
import kotlinx.coroutines.channels.Channel
import ru.otus.daggerhomework.App
import ru.otus.daggerhomework.di.ApplicationComponent
import ru.otus.daggerhomework.di.utils.qualifiers.ActivityContext
import ru.otus.daggerhomework.di.utils.qualifiers.ApplicationContext
import ru.otus.daggerhomework.di.utils.scopes.ActivityScope
import ru.otus.daggerhomework.presentation.Activity
import ru.otus.daggerhomework.presentation.color.ColorGenerator

/**
* `Dagger` [Component] главного экрана
*/
@ActivityScope
@Component(
modules = [MainActivityModule::class],
dependencies = [ApplicationComponent::class]
)
interface MainActivityComponent {

/** `Application` контекст */
@get:ApplicationContext
val appContext: Context
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А почему проперти а не метод?)


/** `Activity` контекст */
@get:ActivityContext
val activityContext: Context

/** Генератор цветов */
val colorGenerator: ColorGenerator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А этот класс нужен в MainActivityComponent?


/** Канал числовых значений в виде [Int] */
val channel: Channel<Int>

@Component.Factory
interface Factory {
fun create(
component: ApplicationComponent,
@BindsInstance @ActivityContext context: Context
): MainActivityComponent
}

companion object {

/** Создать `Dagger` [Component] главного экрана на основе соответствующей [Activity] */
fun create(activity: Activity): MainActivityComponent =
DaggerMainActivityComponent.factory()
.create(
component = App.appComponent(activity.applicationContext),
context = activity
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.otus.daggerhomework.di.main

import dagger.Binds
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.channels.Channel
import ru.otus.daggerhomework.di.utils.scopes.ActivityScope
import ru.otus.daggerhomework.presentation.color.ColorGenerator
import ru.otus.daggerhomework.presentation.color.ColorGeneratorImpl

/**
* `Dagger` [Module] главного экрана
*/
@Module
interface MainActivityModule {

@Binds
fun bindColorGenerator(colorGenerator: ColorGeneratorImpl): ColorGenerator

companion object {

@ActivityScope
@Provides
fun provideChannel(): Channel<Int> = Channel(Channel.CONFLATED)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ru.otus.daggerhomework.di.producer

import dagger.Component
import ru.otus.daggerhomework.di.main.MainActivityComponent
import ru.otus.daggerhomework.di.utils.scopes.FragmentScope
import ru.otus.daggerhomework.presentation.producer.FragmentProducer

/**
* `Dagger` [Component] `Fragment`-а поставления цветов
*/
@FragmentScope
@Component(
modules = [FragmentProducerModule::class],
dependencies = [MainActivityComponent::class]
)
interface FragmentProducerComponent {

/** Внедрить зависимости [FragmentProducer]-а */
fun inject(producer: FragmentProducer)

companion object {

/** Создать `Dagger` [Component] `Fragment`-а поставления цветов на основе [MainActivityComponent] */
fun create(mainActivityComponent: MainActivityComponent): FragmentProducerComponent =
DaggerFragmentProducerComponent.builder()
.mainActivityComponent(mainActivityComponent)
.build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.otus.daggerhomework.di.producer

import dagger.Binds
import dagger.Module
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.SendChannel

/**
* `Dagger` [Module] `Fragment`-а поставления цветов
*/
@Module
interface FragmentProducerModule {

@Binds
fun bindSendChannel(channel: Channel<Int>): SendChannel<Int>
}
Loading