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
6 changes: 4 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DaggerHomework">
<activity android:name=".MainActivity"
android:theme="@style/Theme.DaggerHomework"
android:name=".App">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
9 changes: 8 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/App.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package ru.otus.daggerhomework

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

class App :Application()
class App : Application() {

val component: ApplicationComponent = DaggerApplicationComponent.factory().build(this)
}

val Application.component: ApplicationComponent get() = (this as App).component

This file was deleted.

30 changes: 30 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/ColorObserver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ru.otus.daggerhomework

import androidx.annotation.ColorInt
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow

interface ColorObserver {

val colorFlow: Flow<Int>

fun fireColorEvent(@ColorInt color: Int)

}

class ColorObserverImpl : ColorObserver {

private val _colorFlow = MutableSharedFlow<Int>(
extraBufferCapacity = 1,
replay = 1
)

override val colorFlow: Flow<Int>
get() = _colorFlow.asSharedFlow()

override fun fireColorEvent(color: Int) {
_colorFlow.tryEmit(color)
}

}
18 changes: 16 additions & 2 deletions app/src/main/java/ru/otus/daggerhomework/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
package ru.otus.daggerhomework

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.fragment.app.FragmentActivity
import ru.otus.daggerhomework.di.DaggerMainActivityComponent
import ru.otus.daggerhomework.di.MainActivityComponent

class MainActivity : FragmentActivity(), MainActivityComponentProvider {
private lateinit var component: MainActivityComponent

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

component = DaggerMainActivityComponent.factory().build(application.component)

}

override fun provideMainActivityComponent(): MainActivityComponent = component
}

interface MainActivityComponentProvider {
fun provideMainActivityComponent(): MainActivityComponent
}
17 changes: 15 additions & 2 deletions app/src/main/java/ru/otus/daggerhomework/ProducerFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,34 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import ru.otus.daggerhomework.di.DaggerProducerFragmentComponent
import ru.otus.daggerhomework.di.ProducerFragmentComponent

class ProducerFragment : Fragment() {

private lateinit var producerFragmentComponent: ProducerFragmentComponent

private lateinit var viewModel: ProducerViewModel

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_producer, container, true)
producerFragmentComponent = DaggerProducerFragmentComponent.factory()
.build(
contextActivity = requireActivity(),
appComponent = (requireActivity() as MainActivity).application.component,
mainActivityComponent = (requireActivity() as MainActivityComponentProvider).provideMainActivityComponent()
)
viewModel = producerFragmentComponent.producerVM()
return inflater.inflate(R.layout.fragment_producer, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.button).setOnClickListener {
//отправить результат через flow в другой фрагмент
viewModel.generateColor()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ package ru.otus.daggerhomework
import android.app.Activity
import android.content.Context
import android.widget.Toast
import javax.inject.Inject

class ProducerViewModel(
class ProducerViewModel @Inject constructor(
private val colorGenerator: ColorGenerator,
private val colorObserver: ColorObserver,
private val context: Context
) {

fun generateColor() {
if (context !is Activity) throw RuntimeException("Activity context is required")
Toast.makeText(context, "Color sent", Toast.LENGTH_LONG).show()
colorObserver.fireColorEvent(colorGenerator.generateColor())
}
}
34 changes: 33 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/ReceiverFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,57 @@ import android.view.View
import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.fragment.app.Fragment
import ru.otus.daggerhomework.di.DaggerReceiverFragmentComponent
import ru.otus.daggerhomework.di.ReceiverFragmentComponent

class ReceiverFragment : Fragment() {

private lateinit var frame: View
private lateinit var receiverFragmentComponent: ReceiverFragmentComponent
private lateinit var receiverViewModel: ReceiverViewModel
private var newBackgroundColor: Int? = null

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_receiver, container, true)
receiverFragmentComponent = DaggerReceiverFragmentComponent.factory()
.build(
appComponent = (requireActivity() as MainActivity).application.component,
mainActivityComponent = (requireActivity() as MainActivityComponentProvider).provideMainActivityComponent(),
contextActivity = (requireActivity() as MainActivity).application,
fragment = this,
)
receiverViewModel = receiverFragmentComponent.producerVM()
return inflater.inflate(R.layout.fragment_receiver, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
frame = view.findViewById(R.id.frame)
receiverViewModel.observeColors(this)
}

fun populateColor(@ColorInt color: Int) {
frame.setBackgroundColor(color)
newBackgroundColor = color
}

override fun onSaveInstanceState(outState: Bundle) {
newBackgroundColor?.let {
outState.putInt(BUNDLE_KEY_NEW_BACKGROUND_COLOR, it)
}
}

override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
savedInstanceState?.getInt(BUNDLE_KEY_NEW_BACKGROUND_COLOR)?.let {
populateColor(it)
}
}

companion object {
private const val BUNDLE_KEY_NEW_BACKGROUND_COLOR = "BUNDLE_KEY_NEW_BACKGROUND_COLOR"
}
}
19 changes: 15 additions & 4 deletions app/src/main/java/ru/otus/daggerhomework/ReceiverViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@ package ru.otus.daggerhomework
import android.app.Application
import android.content.Context
import android.widget.Toast
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import javax.inject.Inject

class ReceiverViewModel(
private val context: Context
class ReceiverViewModel @Inject constructor(
private val colorObserver: ColorObserver,
private val context: Context,
private val receiverFragment: ReceiverFragment,
) {

fun observeColors() {
fun observeColors(lifecycleOwner: LifecycleOwner) {
if (context !is Application) throw RuntimeException("Application context is required")
Toast.makeText(context, "Color received", Toast.LENGTH_LONG).show()
lifecycleOwner.lifecycleScope.launch {
colorObserver.colorFlow.collect {
Toast.makeText(context, "Color received", Toast.LENGTH_LONG).show()
receiverFragment.populateColor(it)
}
}
}
}
7 changes: 7 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/di/ActivityScope.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.otus.daggerhomework.di

import javax.inject.Scope

@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class ActivityScope()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.otus.daggerhomework.di

import android.content.Context
import dagger.BindsInstance
import dagger.Component
import javax.inject.Singleton

@Singleton
@Component
interface ApplicationComponent {

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

import dagger.Module
import dagger.Provides
import ru.otus.daggerhomework.ColorObserver
import ru.otus.daggerhomework.ColorObserverImpl

@Module
class ColorGeneratorFeatureModule {

@Provides
@ActivityScope
fun colorObserver(): ColorObserver = ColorObserverImpl()
}
7 changes: 7 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/di/FragmentScope.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.otus.daggerhomework.di

import javax.inject.Scope

@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class FragmentScope
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ru.otus.daggerhomework.di

import dagger.Component
import ru.otus.daggerhomework.ColorObserver


@ActivityScope
@Component(
modules = [ColorGeneratorFeatureModule::class],
dependencies = [ApplicationComponent::class]
)
interface MainActivityComponent {

@Component.Factory
interface Factory {
fun build(appComponent: ApplicationComponent): MainActivityComponent
}

fun colorObserver(): ColorObserver
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ru.otus.daggerhomework.di

import android.content.Context
import dagger.BindsInstance
import dagger.Component
import ru.otus.daggerhomework.ColorGenerator
import ru.otus.daggerhomework.ProducerViewModel

@FragmentScope
@Component(
modules = [ProducerFragmentModule::class],
dependencies = [MainActivityComponent::class, ApplicationComponent::class]
)
interface ProducerFragmentComponent {

@Component.Factory
interface Factory {
fun build(
@BindsInstance
contextActivity: Context,
appComponent: ApplicationComponent,
mainActivityComponent: MainActivityComponent,
): ProducerFragmentComponent
}
Comment on lines +9 to +24
Copy link
Collaborator

Choose a reason for hiding this comment

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

В целом так сделать можно и оно будет работать.
Но чаще делают так:

Для ProducerFragmentComponent делают
interface ProducerFragmentComponentDependencies
Который определяет просто методы или val что нужно для ProducerFragmentComponent.

И потом, кто-то, реализует этот компонент. Его может реализовать или MainActivityComponent, или это будет прямо новый отдельный класс, который создаст MainActivityComponent внутри себя.

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


fun colorGenerator(): ColorGenerator

fun producerVM(): ProducerViewModel
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ru.otus.daggerhomework.di

import dagger.Module
import dagger.Provides
import ru.otus.daggerhomework.ColorGenerator
import ru.otus.daggerhomework.ColorGeneratorImpl

@Module
class ProducerFragmentModule {

@Provides
@FragmentScope
fun colorGenerator(): ColorGenerator = ColorGeneratorImpl()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.otus.daggerhomework.di

import android.content.Context
import dagger.BindsInstance
import dagger.Component
import ru.otus.daggerhomework.ReceiverFragment
import ru.otus.daggerhomework.ReceiverViewModel

@FragmentScope
@Component(
dependencies = [MainActivityComponent::class, ApplicationComponent::class]
)
interface ReceiverFragmentComponent {

@Component.Factory
interface Factory {
fun build(
@BindsInstance
contextActivity: Context,
@BindsInstance
fragment: ReceiverFragment,
appComponent: ApplicationComponent,
mainActivityComponent: MainActivityComponent,
): ReceiverFragmentComponent
}

fun producerVM(): ReceiverViewModel
}
Loading