Skip to content

Commit 0957394

Browse files
author
Peter Bryant
committed
🔥 Remove side-effects
1 parent 0e73392 commit 0957394

File tree

30 files changed

+85
-295
lines changed

30 files changed

+85
-295
lines changed

compose/src/main/java/com/ptrbrynt/kotlin_bloc/compose/BlocComposer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import kotlinx.coroutines.flow.Flow
3939
*/
4040

4141
@Composable
42-
fun <B : BlocBase<State, *>, State> BlocComposer(
42+
fun <B : BlocBase<State>, State> BlocComposer(
4343
bloc: B,
4444
transformStates: Flow<State>.() -> Flow<State> = { this },
4545
content: @Composable (State) -> Unit,

compose/src/main/java/com/ptrbrynt/kotlin_bloc/compose/BlocListener.kt

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,50 @@ import com.ptrbrynt.kotlin_bloc.core.BlocBase
88
import kotlinx.coroutines.flow.Flow
99

1010
/**
11-
* Takes a [bloc] and an [onSideEffect] callback and invokes [onSideEffect] in response to side
12-
* effects in the [bloc].
11+
* Takes a [bloc] and an [onState] callback and invokes [onState] in response to state changes in the [bloc].
1312
*
14-
* It should be used for side-effects resulting from new side-effects being emitted by the [bloc] e.g.
13+
* It should be used for side-effects resulting from new states being emitted by the [bloc] e.g.
1514
* navigation, showing a snackbar etc.
1615
*
1716
* If you want to build composables in response to new states, use [BlocComposer]
1817
*
1918
* ```kotlin
20-
* BlocListener(bloc) { sideEffect ->
21-
* // React to the new side effect here
19+
* BlocListener(bloc) { state ->
20+
* // React to the new state here
2221
* }
2322
* ```
2423
*
25-
* * An optional [transformSideEffects] can be implemented for more granular control over
24+
* An optional [transformStates] can be implemented for more granular control over
2625
* the frequency and specificity with which transitions occur.
2726
*
28-
* For example, to debounce the side effects:
27+
* For example, to debounce the states:
2928
*
3029
* ```kotlin
3130
* BlocListener(
3231
* myBloc,
33-
* transformSideEffects = { this.debounce(1000) },
32+
* transformStates = { this.debounce(1000) },
3433
* ) {
35-
* // React to the new side-effect here
34+
* // React to the new state here
3635
* }
3736
* ```
3837
*
3938
* @param bloc The bloc or cubit that the [BlocListener] will interact with.
40-
* @param onSideEffect The callback function which will be invoked whenever a new `state` is emitted by the [bloc].
41-
* @param transformSideEffects Provides more granular control over the [State] flow.
39+
* @param onState The callback function which will be invoked whenever a new `state` is emitted by the [bloc].
40+
* @param transformStates Provides more granular control over the [State] flow.
4241
* @see BlocComposer
4342
*/
4443

4544
@Composable
46-
fun <B : BlocBase<*, SideEffect>, SideEffect> BlocListener(
45+
fun <B : BlocBase<State>, State> BlocListener(
4746
bloc: B,
48-
transformSideEffects: Flow<SideEffect>.() -> Flow<SideEffect> = { this },
49-
onSideEffect: suspend (SideEffect) -> Unit,
47+
transformStates: Flow<State>.() -> Flow<State> = { this },
48+
onState: suspend (State) -> Unit,
5049
) {
51-
val state by bloc.sideEffectFlow.transformSideEffects().collectAsState(initial = null)
50+
val state by bloc.stateFlow.transformStates().collectAsState(initial = null)
5251

5352
state?.let {
5453
LaunchedEffect(it) {
55-
onSideEffect(it)
54+
onState(it)
5655
}
5756
}
5857
}

compose/src/main/java/com/ptrbrynt/kotlin_bloc/compose/BlocSelector.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import kotlinx.coroutines.flow.map
2727
*/
2828

2929
@Composable
30-
fun <B : BlocBase<State, *>, State, T> BlocSelector(
30+
fun <B : BlocBase<State>, State, T> BlocSelector(
3131
bloc: B,
3232
selector: (State) -> T,
3333
content: @Composable (T) -> Unit,

compose/src/main/java/com/ptrbrynt/kotlin_bloc/compose/LoggingBlocObserver.kt

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,22 @@ import com.ptrbrynt.kotlin_bloc.core.Transition
1212
*/
1313
class LoggingBlocObserver : BlocObserver() {
1414

15-
override fun <B : BlocBase<State, *>, State> onChange(bloc: B, change: Change<State>) {
15+
override fun <B : BlocBase<State>, State> onChange(bloc: B, change: Change<State>) {
1616
super.onChange(bloc, change)
1717
Log.i(bloc::class.simpleName, change.toString())
1818
}
1919

20-
override fun <B : BlocBase<*, *>> onCreate(bloc: B) {
20+
override fun <B : BlocBase<*>> onCreate(bloc: B) {
2121
super.onCreate(bloc)
2222
Log.i(bloc::class.simpleName, "Created")
2323
}
2424

25-
override fun <B : Bloc<Event, *, *>, Event> onEvent(bloc: B, event: Event) {
25+
override fun <B : Bloc<Event, *>, Event> onEvent(bloc: B, event: Event) {
2626
super.onEvent(bloc, event)
2727
Log.i(bloc::class.simpleName, event.toString())
2828
}
2929

30-
override fun <B : BlocBase<*, SideEffect>, SideEffect> onSideEffect(
31-
bloc: B,
32-
sideEffect: SideEffect,
33-
) {
34-
super.onSideEffect(bloc, sideEffect)
35-
Log.i(bloc::class.simpleName, sideEffect.toString())
36-
}
37-
38-
override fun <B : Bloc<Event, State, *>, Event, State> onTransition(
30+
override fun <B : Bloc<Event, State>, Event, State> onTransition(
3931
bloc: B,
4032
transition: Transition<Event, State>,
4133
) {

compose/src/test/java/com/ptrbrynt/kotlin_bloc/compose/LoggingBlocObserverTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class LoggingBlocObserverTest {
3838
stream.println("I/CounterBloc: Increment")
3939
stream.println("I/CounterBloc: Change(state=0, newState=1)")
4040
stream.println("I/CounterBloc: Transition(state=0, event=Increment, newState=1)")
41-
stream.println("I/CounterBloc: 1")
4241
}
4342
}
4443
}

compose/src/test/java/com/ptrbrynt/kotlin_bloc/compose/blocs/CounterBloc.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import com.ptrbrynt.kotlin_bloc.core.Bloc
44

55
enum class CounterEvent { Increment, Decrement }
66

7-
class CounterBloc : Bloc<CounterEvent, Int, Int>(0) {
7+
class CounterBloc : Bloc<CounterEvent, Int>(0) {
88
init {
99
on<CounterEvent> { event ->
1010
when (event) {
1111
CounterEvent.Increment -> emit(state + 1)
1212
CounterEvent.Decrement -> emit(state - 1)
1313
}
14-
emitSideEffect(state)
1514
}
1615
}
1716
}

core/src/main/java/com/ptrbrynt/kotlin_bloc/core/Bloc.kt

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,14 @@ import kotlinx.coroutines.launch
1212
* Takes [Event]s as input and transforms them into a [Flow]
1313
* of [State]s as an output.
1414
*
15-
* Also emits a [Flow] of [SideEffect]s, which are non-state outputs emitted as a result of new
16-
* [Event]s.
17-
*
1815
* @param initial The initial [State]
1916
* @param Event The type of event this can receive
2017
* @param State The type of state this emits
21-
* @param SideEffect The type of side-effect this can emit
2218
* @see Cubit
2319
*/
2420
@Suppress("LeakingThis")
25-
abstract class Bloc<Event, State, SideEffect>(initial: State) :
26-
BlocBase<State, SideEffect>(initial) {
21+
abstract class Bloc<Event, State>(initial: State) :
22+
BlocBase<State>(initial) {
2723
protected val eventFlow = MutableSharedFlow<Event>()
2824

2925
init {
@@ -37,22 +33,14 @@ abstract class Bloc<Event, State, SideEffect>(initial: State) :
3733
}
3834

3935
@PublishedApi
40-
internal val emitter = object : Emitter<State, SideEffect> {
36+
internal val emitter = object : Emitter<State> {
4137
override suspend fun emit(state: State) {
4238
mutableChangeFlow.emit(Change(this@Bloc.state, state))
4339
}
4440

4541
override suspend fun emitEach(states: Flow<State>) {
4642
states.onEach { emit(it) }.launchIn(blocScope)
4743
}
48-
49-
override suspend fun emitSideEffect(sideEffect: SideEffect) {
50-
mutableSideEffectFlow.emit(sideEffect)
51-
}
52-
53-
override suspend fun emitSideEffects(sideEffects: Flow<SideEffect>) {
54-
sideEffects.onEach { emitSideEffect(it) }.launchIn(blocScope)
55-
}
5644
}
5745

5846
/**
@@ -77,7 +65,7 @@ abstract class Bloc<Event, State, SideEffect>(initial: State) :
7765
* @param E The type of [Event] that this handles
7866
*/
7967
protected inline fun <reified E : Event> on(
80-
noinline mapEventToState: suspend Emitter<State, SideEffect>.(E) -> Unit,
68+
noinline mapEventToState: suspend Emitter<State>.(E) -> Unit,
8169
) {
8270
eventFlow
8371
.transformEvents()

core/src/main/java/com/ptrbrynt/kotlin_bloc/core/BlocBase.kt

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import kotlinx.coroutines.launch
1414
* @param initial The initial [State]
1515
*/
1616
@Suppress("LeakingThis")
17-
abstract class BlocBase<State, SideEffect>(initial: State) {
17+
abstract class BlocBase<State>(initial: State) {
1818

1919
init {
2020
Bloc.observer.onCreate(this)
@@ -29,18 +29,6 @@ abstract class BlocBase<State, SideEffect>(initial: State) {
2929
}
3030
}
3131

32-
protected val mutableSideEffectFlow = MutableSharedFlow<SideEffect>().apply {
33-
blocScope.launch {
34-
collect { onSideEffect(it) }
35-
}
36-
}
37-
38-
/**
39-
* The [Flow] of [SideEffect]s
40-
*/
41-
val sideEffectFlow: Flow<SideEffect>
42-
get() = mutableSideEffectFlow
43-
4432
/**
4533
* The current [State] [Flow]
4634
*/
@@ -73,22 +61,4 @@ abstract class BlocBase<State, SideEffect>(initial: State) {
7361
Bloc.observer.onChange(this, change)
7462
this.state = change.newState
7563
}
76-
77-
/**
78-
* Called whenever a [SideEffect] is emitted.
79-
*
80-
* **Note: `super.onSideEffect` should always be called first.**
81-
*
82-
* ```kotlin
83-
* override fun onSideEffect(sideEffect: SideEffect) {
84-
* // Always call super.onSideEffect first
85-
* super.onSideEffect(sideEffect)
86-
*
87-
* // Custom logic goes here
88-
* }
89-
* ```
90-
*/
91-
open fun onSideEffect(sideEffect: SideEffect) {
92-
Bloc.observer.onSideEffect(this, sideEffect)
93-
}
9464
}

core/src/main/java/com/ptrbrynt/kotlin_bloc/core/BlocObserver.kt

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ abstract class BlocObserver {
1212
*
1313
* @param bloc The [Bloc] or [Cubit] which was created.
1414
*/
15-
open fun <B : BlocBase<*, *>> onCreate(bloc: B) {}
15+
open fun <B : BlocBase<*>> onCreate(bloc: B) {}
1616

1717
/**
1818
* Called whenever an [event] is `add`ed to any [bloc].
1919
*
2020
* @param bloc The [Bloc] to which the [Event] was `add`ed
2121
* @param event The [Event] added to the [Bloc]
2222
*/
23-
open fun <B : Bloc<Event, *, *>, Event> onEvent(bloc: B, event: Event) {}
23+
open fun <B : Bloc<Event, *>, Event> onEvent(bloc: B, event: Event) {}
2424

2525
/**
2626
* Called whenever a [Change] occurs in any [Bloc] or [Cubit].
@@ -31,7 +31,7 @@ abstract class BlocObserver {
3131
* @param bloc The [Bloc] or [Cubit] which emitted the [change]
3232
* @param change The [Change] that occurred within the [bloc]
3333
*/
34-
open fun <B : BlocBase<State, *>, State> onChange(bloc: B, change: Change<State>) {}
34+
open fun <B : BlocBase<State>, State> onChange(bloc: B, change: Change<State>) {}
3535

3636
/**
3737
* Called whenever a [Transition] occurs in any [Bloc].
@@ -43,18 +43,9 @@ abstract class BlocObserver {
4343
* @param bloc The [Bloc] in which the [transition] occurred
4444
* @param transition The [Transition] which occurred within the [bloc]
4545
*/
46-
open fun <B : Bloc<Event, State, *>, Event, State> onTransition(
46+
open fun <B : Bloc<Event, State>, Event, State> onTransition(
4747
bloc: B,
4848
transition: Transition<Event, State>,
4949
) {
5050
}
51-
52-
/**
53-
* Called whenever a [SideEffect] is emitted by a [Bloc] or [Cubit].
54-
*/
55-
open fun <B : BlocBase<*, SideEffect>, SideEffect> onSideEffect(
56-
bloc: B,
57-
sideEffect: SideEffect,
58-
) {
59-
}
6051
}

core/src/main/java/com/ptrbrynt/kotlin_bloc/core/Cubit.kt

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.onEach
66

77
/**
88
* A [Cubit] is similar to a [Bloc] but has no notion of events,
9-
* instead relying on methods to [emit] [State]s and [SideEffect]s.
9+
* instead relying on methods to [emit] [State]s..
1010
*
1111
* Every [Cubit] requires an initial state, which will be the state
1212
* of the [Cubit] before [emit] has been called.
@@ -20,24 +20,15 @@ import kotlinx.coroutines.flow.onEach
2020
*
2121
* @param initial The initial [State]
2222
* @param State The type of state this emits
23-
* @param SideEffect The type of side-effect this can emit
2423
* @see Bloc
2524
*/
26-
abstract class Cubit<State, SideEffect>(initial: State) :
27-
BlocBase<State, SideEffect>(initial), Emitter<State, SideEffect> {
25+
abstract class Cubit<State>(initial: State) :
26+
BlocBase<State>(initial), Emitter<State> {
2827
override suspend fun emit(state: State) {
2928
mutableChangeFlow.emit(Change(this.state, state))
3029
}
3130

3231
override suspend fun emitEach(states: Flow<State>) {
3332
states.onEach { emit(it) }.launchIn(blocScope)
3433
}
35-
36-
override suspend fun emitSideEffect(sideEffect: SideEffect) {
37-
mutableSideEffectFlow.emit(sideEffect)
38-
}
39-
40-
override suspend fun emitSideEffects(sideEffects: Flow<SideEffect>) {
41-
sideEffects.onEach { emitSideEffect(it) }.launchIn(blocScope)
42-
}
4334
}

core/src/main/java/com/ptrbrynt/kotlin_bloc/core/Emitter.kt

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.Flow
55
/**
66
* Interface which can be implemented on any object which can [emit] a [State] or a [SideEffect]
77
*/
8-
interface Emitter<State, SideEffect> {
8+
interface Emitter<State> {
99
/**
1010
* Emit a new [State]
1111
*/
@@ -15,14 +15,4 @@ interface Emitter<State, SideEffect> {
1515
* [emit] each [State] which is emitted by the [states] [Flow].
1616
*/
1717
suspend fun emitEach(states: Flow<State>)
18-
19-
/**
20-
* Emit a new [SideEffect]
21-
*/
22-
suspend fun emitSideEffect(sideEffect: SideEffect)
23-
24-
/**
25-
* Emit a [Flow] of [SideEffect]s.
26-
*/
27-
suspend fun emitSideEffects(sideEffects: Flow<SideEffect>)
2818
}

core/src/test/java/com/ptrbrynt/kotlin_bloc/core/blocs/CounterBloc.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object Decrement : CounterEvent()
1414
open class CounterBloc(
1515
private val onTransitionCallback: ((Transition<CounterEvent, Int>) -> Unit)? = null,
1616
private val onEventCallback: ((CounterEvent) -> Unit)? = null,
17-
) : Bloc<CounterEvent, Int, Unit>(0) {
17+
) : Bloc<CounterEvent, Int>(0) {
1818

1919
init {
2020
on<Increment> {

core/src/test/java/com/ptrbrynt/kotlin_bloc/core/blocs/MultiFlowBloc.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ data class MultiFlowNumberAdded(val number: Int) : MultiFlowEvent()
1212

1313
@ExperimentalCoroutinesApi
1414

15-
class MultiFlowBloc : Bloc<MultiFlowEvent, List<Int>, Unit>(emptyList()) {
15+
class MultiFlowBloc : Bloc<MultiFlowEvent, List<Int>>(emptyList()) {
1616
private val numbers = MutableStateFlow(emptyList<Int>())
1717

1818
init {

core/src/test/java/com/ptrbrynt/kotlin_bloc/core/blocs/SeededBloc.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.ptrbrynt.kotlin_bloc.core.blocs
22

33
import com.ptrbrynt.kotlin_bloc.core.Bloc
44

5-
class SeededBloc(private val seed: List<Int>, initial: Int) : Bloc<String, Int, Unit>(initial) {
5+
class SeededBloc(private val seed: List<Int>, initial: Int) : Bloc<String, Int>(initial) {
66
init {
77
on<String> {
88
for (value in seed) {

core/src/test/java/com/ptrbrynt/kotlin_bloc/core/cubits/CounterCubit.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import com.ptrbrynt.kotlin_bloc.core.Change
44
import com.ptrbrynt.kotlin_bloc.core.Cubit
55

66
class CounterCubit(private val onChangeCallback: ((Change<Int>) -> Unit)? = null) :
7-
Cubit<Int, Unit>(0) {
7+
Cubit<Int>(0) {
88
suspend fun increment() = emit(state + 1)
99
suspend fun decrement() = emit(state - 1)
1010

0 commit comments

Comments
 (0)