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: 6 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,11 @@ dependencies {
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'com.google.dagger:dagger:2.38.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.2.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.2.0'
kapt 'com.google.dagger:dagger-compiler:2.38.1'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package="ru.otus.daggerhomework">

<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
17 changes: 15 additions & 2 deletions app/src/main/java/ru/otus/daggerhomework/App.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
package ru.otus.daggerhomework

import android.app.Application
import android.content.Context

class App :Application() {
}
class App: Application() {
lateinit var applicationComponent: ApplicationComponent

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

val Context.applicationComponent: ApplicationComponent
get() = when (this) {
is App -> applicationComponent
else -> this.applicationContext.applicationComponent
}
42 changes: 41 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/ApplicationComponent.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,44 @@
package ru.otus.daggerhomework

import android.content.Context
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Qualifier
import javax.inject.Scope
import javax.inject.Singleton

@AppScope
@Component(modules = [ApplicationModule::class])
interface ApplicationComponent {
}

@AppContext
fun provideContext(): Context

fun providesStateFlow(): MutableStateFlow<Int>

@Component.Factory
interface Factory {
fun create(
@AppContext
@BindsInstance context: Context
): ApplicationComponent
}
}

@Module()
class ApplicationModule {
@AppScope
@Provides
fun provideMutableStateFlow(): MutableStateFlow<Int> {
return MutableStateFlow(0)
}
}

@Qualifier
annotation class AppContext

@Scope
annotation class AppScope
3 changes: 2 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/ColorGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import java.util.*
import javax.inject.Inject

interface ColorGenerator {

@ColorInt
fun generateColor(): Int
}

class ColorGeneratorImpl : ColorGenerator {
class ColorGeneratorImpl @Inject constructor(): ColorGenerator {

override fun generateColor(): Int {
val rnd = Random()
Expand Down
44 changes: 42 additions & 2 deletions app/src/main/java/ru/otus/daggerhomework/FragmentProducer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,61 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import dagger.Binds
import dagger.Component
import dagger.Module
import javax.inject.Inject
import javax.inject.Scope

class FragmentProducer : Fragment() {

@Inject
lateinit var viewModelProducerFactory: ViewModelProducerFactory
private val viewModelProducer by viewModels<ViewModelProducer> { viewModelProducerFactory }

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_a, container, true)
DaggerFragmentProducerComponent
.factory()
.create((requireActivity() as MainActivity).mainActivityComponent)
.inject(this)
return inflater.inflate(R.layout.fragment_a, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.button).setOnClickListener {
//отправить результат через livedata в другой фрагмент
viewModelProducer.generateColor()
}
}
}
}

@FragmentScope
@Component(
dependencies = [MainActivityComponent::class],
modules = [FragmentProducerModule::class]
)
interface FragmentProducerComponent {

@Component.Factory
interface Factory {
fun create(mainActivityComponent: MainActivityComponent): FragmentProducerComponent
}
fun provideColorGenerator(): ColorGenerator
fun inject(fragment: FragmentProducer)
}

@Module
interface FragmentProducerModule {
@FragmentScope
@Binds
fun colorGenerator(colorGeneratorImpl: ColorGeneratorImpl): ColorGenerator
}

@Scope
annotation class FragmentScope
38 changes: 35 additions & 3 deletions app/src/main/java/ru/otus/daggerhomework/FragmentReceiver.kt
Original file line number Diff line number Diff line change
@@ -1,31 +1,63 @@
package ru.otus.daggerhomework

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.annotation.ColorInt
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import dagger.Component
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

class FragmentReceiver : Fragment() {

private lateinit var frame: View

@Inject
lateinit var viewModelReceiverFactory: ViewModelReceiverFactory
private val viewModelReceiver by viewModels<ViewModelReceiver> { viewModelReceiverFactory }

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_b, container, true)
DaggerFragmentReceiverComponent
.factory()
.create((requireActivity() as MainActivity).mainActivityComponent)
.inject(this)
return inflater.inflate(R.layout.fragment_b, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
frame = view.findViewById(R.id.frame)
lifecycleScope.launch {
viewModelReceiver.color.collectLatest { populateColor(it) }
}
}

fun populateColor(@ColorInt color: Int) {
private fun populateColor(@ColorInt color: Int) {
Log.d("COLOR_VALUE", color.toString())
frame.setBackgroundColor(color)
}
}

@FragmentScope
@Component(dependencies = [MainActivityComponent::class])
interface FragmentReceiverComponent {

@Component.Factory
interface Factory {
fun create(
appComponent: MainActivityComponent
): FragmentReceiverComponent
}

fun inject(fragment: FragmentReceiver)
}
39 changes: 38 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,48 @@
package ru.otus.daggerhomework

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import dagger.BindsInstance
import dagger.Component
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Qualifier
import javax.inject.Scope

class MainActivity : AppCompatActivity() {
lateinit var mainActivityComponent: MainActivityComponent

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainActivityComponent = DaggerMainActivityComponent.factory().create(this, applicationComponent)
setContentView(R.layout.activity_main)
}
}
}

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

@AppContext
fun providesAppContext(): Context
@ActivityContext
fun provideActivityContext(): Context
fun providesStateFlow(): MutableStateFlow<Int>

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

@Scope
annotation class ActivityScope

@Qualifier
annotation class ActivityContext

25 changes: 22 additions & 3 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelProducer.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,38 @@
package ru.otus.daggerhomework

import android.app.Activity
import android.content.Context
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import java.lang.RuntimeException
import javax.inject.Inject

class ViewModelProducer(
private val colorGenerator: ColorGenerator,
private val context: Context
@ActivityContext private val context: Context,
private val eventFlow: MutableStateFlow<Int>
) : ViewModel() {

fun generateColor() {
if (context !is FragmentActivity) throw RuntimeException("Здесь нужен контекст активити")
Toast.makeText(context, "Color sent", Toast.LENGTH_LONG).show()
viewModelScope.launch {
val color = colorGenerator.generateColor()
eventFlow.value = color
Toast.makeText(context, "Color sent", Toast.LENGTH_LONG).show()
}
}
}

class ViewModelProducerFactory @Inject constructor(
private val colorGenerator: ColorGenerator,
@ActivityContext private val context: Context,
private val eventFlow: MutableStateFlow<Int>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return ViewModelProducer(colorGenerator, context, eventFlow) as T
}
}
31 changes: 26 additions & 5 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,38 @@ package ru.otus.daggerhomework

import android.app.Application
import android.content.Context
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.lang.RuntimeException
import javax.inject.Inject

class ViewModelReceiver(
private val context: Context
@AppContext private val context: Context,
private val eventFlow: MutableStateFlow<Int>
) : ViewModel() {
private val _color = MutableStateFlow(0)
val color: StateFlow<Int> = _color

init {
observeColors()
}

fun observeColors() {
if (context !is Application) throw RuntimeException("Здесь нужен контекст апликейшена")
Toast.makeText(context, "Color received", Toast.LENGTH_LONG).show()
viewModelScope.launch {
eventFlow.collectLatest { _color.value = it }
}
}
}

class ViewModelReceiverFactory @Inject constructor(
@AppContext private val context: Context,
private val eventFlow: MutableStateFlow<Int>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return ViewModelReceiver(context, eventFlow) as T
}
}
Loading