Skip to content

Instantly share code, notes, and snippets.

@audinue
Created February 14, 2025 22:39
Show Gist options
  • Select an option

  • Save audinue/28096aa9c05b8784a5670e4e3ae79dbd to your computer and use it in GitHub Desktop.

Select an option

Save audinue/28096aa9c05b8784a5670e4e3ae79dbd to your computer and use it in GitHub Desktop.
Clean architecture counter
package id.vorme.app.presentation.ui.screens.packages
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import cafe.adriel.voyager.core.screen.Screen
interface CounterControllerInterface {
fun increment()
}
interface CounterInputBoundary {
@Composable
fun displayCounter()
fun increment()
}
interface CounterOutputBoundary {
@Composable
fun displayCounter(count: Int)
}
interface CounterDataAccessInterface {
fun fetchCount(): Int
fun increment()
}
class CounterController(
val inputBoundary: CounterInputBoundary
) : CounterControllerInterface {
override fun increment() {
inputBoundary.increment()
}
@Composable
fun displayCounter() {
inputBoundary.displayCounter()
}
}
class CounterUseCase(
val outputBoundary: CounterOutputBoundary,
val dataAccessInterface: CounterDataAccessInterface
) : CounterInputBoundary {
val count = mutableStateOf(0)
@Composable
override fun displayCounter() {
LaunchedEffect(true) {
count.value = dataAccessInterface.fetchCount()
}
outputBoundary.displayCounter(
count.value
)
}
override fun increment() {
dataAccessInterface.increment()
count.value = dataAccessInterface.fetchCount()
}
}
class CounterView(
val controllerInterface: Lazy<CounterControllerInterface?>
) {
@Composable
fun displayCounter(count: Int) {
Button({ controllerInterface.value!!.increment() }) {
Text(count.toString())
}
}
}
class CounterPresenter(
val view: CounterView
) : CounterOutputBoundary {
@Composable
override fun displayCounter(count: Int) {
view.displayCounter(count)
}
}
object CounterData {
var count: Int = 7
}
class CounterDataAccess : CounterDataAccessInterface {
override fun fetchCount(): Int {
return CounterData.count
}
override fun increment() {
CounterData.count++
}
}
class CounterScreen : Screen {
@Composable
override fun Content() {
var controller: CounterController? = null
// Manual dependency injection
controller = remember {
CounterController(
inputBoundary = CounterUseCase(
outputBoundary = CounterPresenter(
view = CounterView(
controllerInterface = lazy {
controller
}
)
),
dataAccessInterface = CounterDataAccess()
)
)
}
controller.displayCounter()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment