Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
18 changes: 12 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.kapt'
}

android {
compileSdkVersion 31
compileSdkVersion 34

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

Expand All @@ -30,6 +30,7 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
namespace 'ru.otus.daggerhomework'
}

dependencies {
Expand All @@ -38,6 +39,11 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'com.google.dagger:dagger:2.42'
kapt 'com.google.dagger:dagger-compiler:2.42'
implementation 'com.google.dagger:dagger:2.48'
kapt 'com.google.dagger:dagger-compiler:2.48'

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
implementation 'androidx.fragment:fragment-ktx:1.6.2'
}
9 changes: 5 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="ru.otus.daggerhomework">
xmlns:android="http://schemas.android.com/apk/res/android">

<application
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">
android:theme="@style/Theme.DaggerHomework"
android:name=".di.app.App">
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
6 changes: 0 additions & 6 deletions app/src/main/java/ru/otus/daggerhomework/App.kt

This file was deleted.

This file was deleted.

6 changes: 3 additions & 3 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 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()
Expand Down
27 changes: 25 additions & 2 deletions app/src/main/java/ru/otus/daggerhomework/FragmentProducer.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
package ru.otus.daggerhomework

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import ru.otus.daggerhomework.di.activity.ActivityComponentHolder
import ru.otus.daggerhomework.di.app.appComponent
import ru.otus.daggerhomework.di.fragments.FragmentProducerComponent
import ru.otus.daggerhomework.di.fragments.ViewModelFactory
import javax.inject.Inject

class FragmentProducer : Fragment() {


@Inject
lateinit var vmFactory: ViewModelFactory
private val viewModel: ViewModelProducer by lazy {
ViewModelProvider(this, vmFactory)[ViewModelProducer::class.java]
}

override fun onAttach(context: Context) {
super.onAttach(context)
FragmentProducerComponent
.getFragComponent(
ActivityComponentHolder
.getActivityComponent(context.appComponent, requireActivity())
).inject(this)
}

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)
view.findViewById<Button>(R.id.button).setOnClickListener {
//отправить результат через livedata в другой фрагмент
viewModel.generateColor()
}
}
}
48 changes: 45 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,73 @@
package ru.otus.daggerhomework

import android.content.Context
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 ru.otus.daggerhomework.di.activity.ActivityComponentHolder
import ru.otus.daggerhomework.di.app.appComponent
import ru.otus.daggerhomework.di.fragments.FragmentReceiverComponent
import ru.otus.daggerhomework.di.fragments.ViewModelFactory
import javax.inject.Inject

class FragmentReceiver : Fragment() {

private lateinit var frame: View

@Inject
lateinit var vmFactory: ViewModelFactory
private val viewModel: ViewModelReceiver by lazy {
Copy link
Contributor

Choose a reason for hiding this comment

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

Не думаю что в lazy тем более потокобезопасном есть смысл

ViewModelProvider(this, vmFactory)[ViewModelReceiver::class.java]
}

private var currentColor: Int = 0xFFFFFF

override fun onAttach(context: Context) {
super.onAttach(context)
FragmentReceiverComponent
.getFragComponent(
ActivityComponentHolder
.getActivityComponent(context.appComponent, requireActivity())
).inject(this)
}

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)

viewModel.observeColors(::populateColor)
}

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

override fun onSaveInstanceState(outState: Bundle) {
outState.putInt(COLOR_KEY, currentColor)
super.onSaveInstanceState(outState)
}

override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
if (savedInstanceState != null) {
populateColor(savedInstanceState.getInt(COLOR_KEY, currentColor))
}
}

companion object {
private const val COLOR_KEY = "color"
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/ru/otus/daggerhomework/LocalEvent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.otus.daggerhomework

import androidx.annotation.ColorInt

sealed interface LocalEvent {
data class ColorData(
@ColorInt val color: Int
): LocalEvent
data class Error(
val e: Exception
): LocalEvent
}
13 changes: 12 additions & 1 deletion app/src/main/java/ru/otus/daggerhomework/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
package ru.otus.daggerhomework

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import ru.otus.daggerhomework.di.activity.ActivityComponentHolder
import ru.otus.daggerhomework.di.app.appComponent

class MainActivity : AppCompatActivity() {

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

// supportFragmentManager.beginTransaction()
// .add(R.id.fragment_producer_container, FragmentProducer())
// .add(R.id.fragment_receiver_container, FragmentReceiver())
// .commit()

ActivityComponentHolder
.getActivityComponent(application.appComponent, this)
.inject(this)
}
}
28 changes: 26 additions & 2 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelProducer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,38 @@ package ru.otus.daggerhomework
import android.content.Context
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import ru.otus.daggerhomework.di.activity.ActivityContextQualifier
import java.lang.ref.WeakReference
import javax.inject.Inject

class ViewModelProducer(
class ViewModelProducer @Inject constructor(
private val observer: Channel<LocalEvent>,
private val colorGenerator: ColorGenerator,
@ActivityContextQualifier
activityContext: Context
) : ViewModel() {

private val weakContextRef = WeakReference(activityContext)
private val context: Context
) {
get() = weakContextRef.get()!!

fun generateColor() {
if (context !is FragmentActivity) throw RuntimeException("Здесь нужен контекст активити")
Toast.makeText(context, "Color sent", Toast.LENGTH_LONG).show()

viewModelScope.launch {
try {
observer.send(LocalEvent.ColorData(colorGenerator.generateColor()))
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
observer.send(LocalEvent.Error(e))
}
}
}
}
29 changes: 26 additions & 3 deletions app/src/main/java/ru/otus/daggerhomework/ViewModelReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,36 @@ package ru.otus.daggerhomework
import android.app.Application
import android.content.Context
import android.widget.Toast
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import ru.otus.daggerhomework.di.app.ApplicationContextQualifier
import javax.inject.Inject

class ViewModelReceiver(
class ViewModelReceiver @Inject constructor(
private val observer: Channel<LocalEvent>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Не очень правильно что ты можешь в приемники эмитить события в Channel, сделай здесь ReceiveChannel, а в другой ВМ SendChannel

@ApplicationContextQualifier
private val context: Context
) {
) : ViewModel() {

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

viewModelScope.launch {
observer.receiveAsFlow().collect { event ->
when (event) {
is LocalEvent.ColorData -> {
populate(event.color)
}

is LocalEvent.Error -> {
Toast.makeText(context, "Error", Toast.LENGTH_LONG).show()
}
}
}
}
}
}
Loading