Skip to content

Commit 3c73e8a

Browse files
author
Peter Bryant
committed
📝 Add "Bloc vs ViewModel" documentation
1 parent 9709451 commit 3c73e8a

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

docs/why-bloc.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,64 @@ Bloc was designed with three core values in mind.
2323
* **Powerful**: Help make amazing, complex applications by composing them from smaller components;
2424
* **Testable**: Easily test every aspect of your app so you can iterate with confidence.
2525

26-
Overall, Bloc attempts to make state changes predictable by regulating when a state change can occur, and enforcing a single way to change state throughout an app.
26+
Overall, Bloc attempts to make state changes predictable by regulating when a state change can occur, and enforcing a single way to change state throughout an app.
27+
28+
## Bloc vs. ViewModel
29+
30+
MVVM has been the default state management pattern on Android for years, thanks to Google's official Lifecycle packages which included lifecycle-aware ViewModel and LiveData components.
31+
32+
But Jetpack Compose has no notion of the application lifecycle, which makes one of `androidx.lifecycle.ViewModel`'s main benefits moot.
33+
34+
Of course, Compose still has full support for using `androidx.lifecycle` components. But thanks to the fundamentally new architecture of Compose, there's no inherent benefit to using them. This means that you can choose whichever pattern you prefer, or whichever works best for your project and team.
35+
36+
Let's consider our Counter example. Here's what it looks like in Bloc:
37+
38+
```kotlin
39+
sealed class CounterEvent
40+
41+
object CounterIncremented: CounterEvent()
42+
43+
class CounterBloc: Bloc<CounterEvent, Int>(0) {
44+
init {
45+
on<CounterIncremented> {
46+
emit(state + 1)
47+
}
48+
}
49+
}
50+
```
51+
52+
And here's an equivalent ViewModel:
53+
54+
```kotlin
55+
class CounterViewModel: ViewModel() {
56+
val counter = MutableLiveData<Int>(0)
57+
58+
fun increment() {
59+
counter.postValue(counter.value!! + 1)
60+
}
61+
}
62+
```
63+
64+
The Bloc has a couple of advantages:
65+
66+
* The implementation enforces the use of a single type to represent the state; in this case, and `Int`. This is a great way of making sure you're following the single-responsibility principle of [SOLID](https://en.wikipedia.org/wiki/SOLID) object-oriented programming: the Bloc can only be used to represent one aspect of the application's state. By contrast, the ViewModel is fully open to being bloated with other values, which dilutes its ability to have a single responsibility.
67+
* The Bloc is easier to instantiate: it doesn't require any special factories as it doesn't depend on anything from the Android framework.
68+
* The Bloc is also cross-platform; you can use it in any Kotlin code, whereas the ViewModel is Android-only due to its dependency on the Android framework.
69+
* Unlike ViewModels, which tend to represent all UI elements on a particular screen, Blocs can be totally separated from your UI and instead represent the state of a particular piece of data. It's much easier to use a Bloc across multiple UI elements than it is to share a ViewModel.
70+
71+
The ViewModel also has some advantages:
72+
73+
* It's much more familiar to a lot of Android developers, which may be an advantage if you're working on a team.
74+
* It's backwards-compatible with legacy Android UI (Activities and Fragments), making it much easier to use in legacy codebases which are slowly moving towards Compose
75+
* It's flexible, and allows developers to make their own rules about how they want to implement state management.
76+
* There is a little less boilerplate
77+
78+
Of course, we musn't forget that Cubit is also an option, and provides many of the benefits of Bloc without the associated boilerplate:
79+
80+
```kotlin
81+
class CounterCubit: Cubit<Int>(0) {
82+
suspend fun increment = emit(state + 1)
83+
}
84+
```
85+
86+
For simple states like the Counter, `Cubit` is probably the best of both worlds!

0 commit comments

Comments
 (0)