Skip to content
Closed
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: 5 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'com.google.dagger:dagger:2.38.1'
kapt 'com.google.dagger:dagger-compiler:2.38.1'
}

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
}
3 changes: 2 additions & 1 deletion 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 All @@ -19,4 +20,4 @@
</activity>
</application>

</manifest>
</manifest>
16 changes: 14 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,18 @@
package ru.otus.daggerhomework

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

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

private var appComponent: ApplicationComponent? = null

override fun onCreate() {
super.onCreate()
appComponent = ApplicationComponent.create(this)
}

fun getAppComponent() = appComponent ?: ApplicationComponent.create(this).also {
appComponent = it
}
}

This file was deleted.

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

import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import java.util.*
import java.util.Random
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()
return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
}
}
}
13 changes: 13 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/FlowObserver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.otus.daggerhomework

import kotlinx.coroutines.flow.Flow

/**
* @author Юрий Польщиков on 08.08.2021
*/
interface FlowObserver<T> {

val valueFlow: Flow<T>

suspend fun emitValue(value: T)
}
18 changes: 16 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,35 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import ru.otus.daggerhomework.di.FragmentProducerComponent

class FragmentProducer : Fragment() {

private lateinit var viewModel: ViewModelProducer

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_a, container, true)
return inflater.inflate(R.layout.fragment_a, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val fragmentProducerComponent = FragmentProducerComponent.create(requireActivity())
viewModel = ViewModelProvider(viewModelStore, fragmentProducerComponent.getViewModelProducerFactory())
.get(ViewModelProducer::class.java)

view.findViewById<Button>(R.id.button).setOnClickListener {
//отправить результат через livedata в другой фрагмент
viewLifecycleOwner.lifecycleScope.launch {
viewModel.generateColor()
}
}
}
}
}
24 changes: 20 additions & 4 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,44 @@ 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.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import ru.otus.daggerhomework.di.FragmentReceiverComponent

class FragmentReceiver : Fragment() {

private lateinit var frame: View
private lateinit var viewModel: ViewModelReceiver

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_b, container, true)
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)

val fragmentReceiverComponent = FragmentReceiverComponent.create(requireActivity())

viewModel = ViewModelProvider(viewModelStore, fragmentReceiverComponent.getViewModelReceiverFactory())
.get(ViewModelReceiver::class.java)

viewLifecycleOwner.lifecycleScope.launch {
viewModel.color.collect {
populateColor(it)
}
}
}

fun populateColor(@ColorInt color: Int) {
private fun populateColor(@ColorInt color: Int) {
frame.setBackgroundColor(color)
}
}
}
19 changes: 19 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/IntFlowObserver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.otus.daggerhomework

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import javax.inject.Inject

/**
* @author Юрий Польщиков on 08.08.2021
*/
class IntFlowObserver @Inject constructor() : FlowObserver<Int> {

private val eventFlow = MutableSharedFlow<Int>()

override val valueFlow: Flow<Int> = eventFlow

override suspend fun emitValue(value: Int) {
eventFlow.emit(value)
}
}
20 changes: 17 additions & 3 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 androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import ru.otus.daggerhomework.di.MainActivityComponent
import ru.otus.daggerhomework.di.MainActivityComponentProvider

class MainActivity : AppCompatActivity(), MainActivityComponentProvider {

private var mainActivityComponent: MainActivityComponent? = null

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

supportFragmentManager.beginTransaction()
.add(R.id.receiverFragment, FragmentReceiver())
.add(R.id.producerFragment, FragmentProducer())
.commit()
}

override fun getMainActivityComponent() = mainActivityComponent ?: MainActivityComponent.create(this).also {
mainActivityComponent = it
}
}
}
13 changes: 7 additions & 6 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelProducer.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
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 java.lang.RuntimeException

class ViewModelProducer(
private val colorGenerator: ColorGenerator,
private val context: Context
private val flowObserver: FlowObserver<Int>,
private val context: Context,
) : ViewModel() {

fun generateColor() {
suspend fun generateColor() {
flowObserver.emitValue(colorGenerator.generateColor())

if (context !is FragmentActivity) throw RuntimeException("Здесь нужен контекст активити")
Toast.makeText(context, "Color sent", Toast.LENGTH_LONG).show()
Toast.makeText(context, "Color sent", Toast.LENGTH_SHORT).show()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package ru.otus.daggerhomework

import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import ru.otus.daggerhomework.di.ActivityContext

/**
* @author Юрий Польщиков on 08.08.2021
*/
class ViewModelProducerFactory(
private val colorGenerator: ColorGenerator,
private val flowObserver: FlowObserver<Int>,
@ActivityContext private val context: Context
) : ViewModelProvider.Factory {

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return ViewModelProducer(colorGenerator, flowObserver, context) as T
}
}
32 changes: 25 additions & 7 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,34 @@ 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 java.lang.RuntimeException
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import ru.otus.daggerhomework.di.AppContext

class ViewModelReceiver(
private val context: Context
private val flowObserver: FlowObserver<Int>,
@AppContext private val context: Context
) : ViewModel() {

fun observeColors() {
if (context !is Application) throw RuntimeException("Здесь нужен контекст апликейшена")
Toast.makeText(context, "Color received", Toast.LENGTH_LONG).show()
private val colorFlow = MutableSharedFlow<Int>()
val color: Flow<Int> = colorFlow

init {
observeColors()
}

private fun observeColors() {
viewModelScope.launch {
flowObserver.valueFlow.collect {
colorFlow.emit(it)

if (context !is Application) throw RuntimeException("Здесь нужен контекст апликейшена")
Toast.makeText(context, "Color received", Toast.LENGTH_SHORT).show()
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ru.otus.daggerhomework

import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import ru.otus.daggerhomework.di.AppContext

/**
* @author Юрий Польщиков on 08.08.2021
*/
class ViewModelReceiverFactory(
private val flowObserver: FlowObserver<Int>,
@AppContext private val context: Context
) : ViewModelProvider.Factory {

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return ViewModelReceiver(flowObserver, context) as T
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/di/ActivityContext.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.otus.daggerhomework.di

import javax.inject.Qualifier

/**
* @author Юрий Польщиков on 08.08.2021
*/
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ActivityContext
10 changes: 10 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,10 @@
package ru.otus.daggerhomework.di

import javax.inject.Scope

/**
* @author Юрий Польщиков on 08.08.2021
*/
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class ActivityScope
10 changes: 10 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/di/AppContext.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.otus.daggerhomework.di

import javax.inject.Qualifier

/**
* @author Юрий Польщиков on 08.08.2021
*/
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class AppContext
Loading