Skip to content

Instantly share code, notes, and snippets.

@dladukedev
Created August 15, 2024 02:35
Show Gist options
  • Save dladukedev/2cbb9969c275c1c402ef8703c175883d to your computer and use it in GitHub Desktop.
Save dladukedev/2cbb9969c275c1c402ef8703c175883d to your computer and use it in GitHub Desktop.
An example of using Use Case interfaces without backing Use Case classes
package com.example.counterapplication
import android.app.Application
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.ViewModel
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.HiltAndroidApp
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import javax.inject.Inject
import javax.inject.Singleton
@HiltAndroidApp
class MyApp: Application()
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val viewModel by viewModels<CounterViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
CounterScreen(viewModel = viewModel, modifier = Modifier.padding(innerPadding))
}
}
}
}
@Composable
fun CounterScreen(viewModel: CounterViewModel, modifier: Modifier = Modifier) {
val state by viewModel.value.collectAsState()
Column(modifier = modifier) {
Text(text = state.toString())
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Button(onClick = { viewModel.postAction(CounterViewModel.Action.ADD_ONE)}) {
Text("Add One")
}
Button(onClick = { viewModel.postAction(CounterViewModel.Action.SUBTRACT_ONE)}) {
Text("Subtract One")
}
}
}
}
@HiltViewModel
class CounterViewModel @Inject constructor(
private val addOne: AddOne,
private val subtractOne: SubtractOne,
subscribeValue: SubscribeValue
): ViewModel() {
val value = subscribeValue.value
fun postAction(action: Action) {
when(action) {
Action.ADD_ONE -> addOne()
Action.SUBTRACT_ONE -> subtractOne()
}
}
enum class Action {
ADD_ONE, SUBTRACT_ONE
}
}
interface AddOne {
fun addOne()
}
operator fun AddOne.invoke() {
addOne()
}
interface SubtractOne {
fun subtractOne()
}
operator fun SubtractOne.invoke() {
subtractOne()
}
interface SubscribeValue {
val value: StateFlow<Int>
}
@Singleton
class ValueRepository @Inject constructor(): AddOne, SubtractOne, SubscribeValue {
override fun subtractOne() {
_value.update { it - 1 }
}
override fun addOne() {
_value.update { it + 1 }
}
private val _value = MutableStateFlow(0)
override val value: StateFlow<Int> = _value
}
@Module
@InstallIn(SingletonComponent::class)
abstract class CounterModule {
@Binds
abstract fun bindAdd(valueRepository: ValueRepository): AddOne
@Binds
abstract fun bindSubtract(valueRepository: ValueRepository): SubtractOne
@Binds
abstract fun bindSubscribeValue(valueRepository: ValueRepository): SubscribeValue
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment