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
16 changes: 11 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ plugins {
}

android {
compileSdkVersion 30
compileSdkVersion 31
buildToolsVersion "30.0.3"

defaultConfig {
applicationId "ru.otus.daggerhomework"
minSdkVersion 23
targetSdkVersion 30
targetSdkVersion 31
versionCode 1
versionName "1.0"

Expand All @@ -34,11 +34,17 @@ android {
}

dependencies {
def lifecycle_version = '2.4.0'

implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'com.google.dagger:dagger:2.38.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.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"
kapt 'com.google.dagger:dagger-compiler:2.38.1'
}
6 changes: 4 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
package="ru.otus.daggerhomework">

<application
android:allowBackup="true"
android:allowBackup="false"
android:name=".App"
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=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
11 changes: 10 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,15 @@
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() {

lateinit var applicationComponent: ApplicationComponent

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

This file was deleted.

4 changes: 2 additions & 2 deletions app/src/main/java/ru/otus/daggerhomework/ColorGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ package ru.otus.daggerhomework

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
17 changes: 16 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/FragmentProducer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,36 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import ru.otus.daggerhomework.di.DaggerFragmentProducerComponent
import ru.otus.daggerhomework.di.ViewModelFactory
import ru.otus.daggerhomework.di.injectViewModel
import javax.inject.Inject

class FragmentProducer : Fragment() {

@Inject
lateinit var factory: ViewModelFactory
private lateinit var producerViewModel: ViewModelProducer

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_a, container, true)
DaggerFragmentProducerComponent
.builder()
.mainActivityComponent((requireActivity() as MainActivity).activityComponent)
.build()
.inject(this)
producerViewModel = injectViewModel(factory)
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 в другой фрагмент
producerViewModel.generateColor()
}
}
}
36 changes: 33 additions & 3 deletions app/src/main/java/ru/otus/daggerhomework/FragmentReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,58 @@ import android.os.Bundle
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.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.launch
import ru.otus.daggerhomework.di.DaggerFragmentReceiverComponent
import ru.otus.daggerhomework.di.ViewModelFactory
import ru.otus.daggerhomework.di.injectViewModel
import javax.inject.Inject

class FragmentReceiver : Fragment() {

private lateinit var frame: View

@Inject
lateinit var factory: ViewModelFactory
private lateinit var receiverViewModel: ViewModelReceiver

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_b, container, true)
DaggerFragmentReceiverComponent
.builder()
.mainActivityComponent((requireActivity() as MainActivity).activityComponent)
.build()
.inject(this)
receiverViewModel = injectViewModel(factory)
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)
// with(viewLifecycleOwner) {
// lifecycleScope.launch {
// repeatOnLifecycle(Lifecycle.State.CREATED) {
// receiverViewModel.observeColors { populateColor(it) }
// }
// }
// }
receiverViewModel.observeColors { populateColor(it) }
}

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

override fun onDestroyView() {
super.onDestroyView()
receiverViewModel.stopObservingColors()
}
}
14 changes: 13 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@ package ru.otus.daggerhomework

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import ru.otus.daggerhomework.di.DaggerMainActivityComponent
import ru.otus.daggerhomework.di.MainActivityComponent

class MainActivity : AppCompatActivity() {

lateinit var activityComponent: MainActivityComponent

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
activityComponent = DaggerMainActivityComponent.factory()
.create(this, (application as App).applicationComponent)
supportFragmentManager
.beginTransaction()
.add(R.id.container, FragmentReceiver())
.add(R.id.container, FragmentProducer())
.commit()
}
}
}
14 changes: 10 additions & 4 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelProducer.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
package ru.otus.daggerhomework

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

class ViewModelProducer(
@SuppressLint("StaticFieldLeak")
class ViewModelProducer @Inject constructor(
private val colorGenerator: ColorGenerator,
private val context: Context
@Named("activity") private val context: Context,
private val state: MutableStateFlow<Int>
) : ViewModel() {

fun generateColor() {
if (context !is FragmentActivity) throw RuntimeException("Здесь нужен контекст активити")
Toast.makeText(context, "Color sent", Toast.LENGTH_LONG).show()
state.value = colorGenerator.generateColor()
}
}
}
32 changes: 26 additions & 6 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelReceiver.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
package ru.otus.daggerhomework

import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.lang.RuntimeException
import javax.inject.Inject
import javax.inject.Named

class ViewModelReceiver(
private val context: Context
@SuppressLint("StaticFieldLeak")
class ViewModelReceiver @Inject constructor(
@Named("application") private val context: Context,
private val state: MutableStateFlow<Int>
) : ViewModel() {

fun observeColors() {
private var colorUpdatesJob: Job? = null

fun observeColors(action: ((Int) -> Unit)?) {
if (context !is Application) throw RuntimeException("Здесь нужен контекст апликейшена")
Toast.makeText(context, "Color received", Toast.LENGTH_LONG).show()
colorUpdatesJob = viewModelScope.launch {
state.collect {
Toast.makeText(context, "Color received", Toast.LENGTH_LONG).show()
action?.invoke(it)
}
}
}

fun stopObservingColors() {
colorUpdatesJob?.cancel()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ru.otus.daggerhomework.di

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

@Singleton
@Component
interface ApplicationComponent {

@Named("application")
fun provideAppContext(): Context

@Component.Factory
interface Factory {
fun create(@BindsInstance @Named("application") appContext: Context): ApplicationComponent
}
}

@Scope
annotation class ActivityScope

@Scope
annotation class FragmentScope
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.otus.daggerhomework.di

import dagger.Component
import ru.otus.daggerhomework.FragmentProducer

@FragmentScope
@Component(dependencies = [MainActivityComponent::class], modules = [FragmentProducerModule::class])
interface FragmentProducerComponent {
fun inject(producer: FragmentProducer)
}



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

import androidx.lifecycle.ViewModel
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoMap
import ru.otus.daggerhomework.ColorGenerator
import ru.otus.daggerhomework.ColorGeneratorImpl
import ru.otus.daggerhomework.ViewModelProducer

@Module
interface FragmentProducerModule {
@Binds
@IntoMap
@ViewModelKey(ViewModelProducer::class)
fun bindViewModelProducer(viewModelProducer: ViewModelProducer): ViewModel

@Binds
fun bindColorGenerator(colorGenerator: ColorGeneratorImpl): ColorGenerator
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.otus.daggerhomework.di

import dagger.Component
import ru.otus.daggerhomework.FragmentReceiver

@FragmentScope
@Component(dependencies = [MainActivityComponent::class], modules = [FragmentReceiverModule::class])
interface FragmentReceiverComponent {
fun inject(receiver: FragmentReceiver)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ru.otus.daggerhomework.di

import androidx.lifecycle.ViewModel
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoMap
import ru.otus.daggerhomework.ViewModelReceiver

@Module
interface FragmentReceiverModule {
@Binds
@IntoMap
@ViewModelKey(ViewModelReceiver::class)
fun bindViewModelReceiver(viewModelReceiver: ViewModelReceiver): ViewModel
}
Loading