Before Compose, I use LiveData
to connect between UI component and data, the UI component will be updated when the data of LiveData
type has changed. After I use Compose, I was told that MutableState<T>
is just like LiveData
, but it is used in Compose.
In the following Code A, val count
is MutableState<T>
type in Part 1, so the text will be changed in Part 2 when I click the button in Part 3. The above procedure is easy to understand, just like I use LiveData before.
But "3 times clicked"
will be displayed when I click the button for 3 times, I don’t understand why Part 4 is launched, you know if (count.value == 3)...
is a logic code and it’s not associated with any UI component.
1: Does it mean that the system will observe all code which are associated with val count
, and run it automatically when the count.value
is changed?
2: Will Part 5 always be relaunched when I click the button in Part 3 ?
Code A
@Composable
fun Counter() {
Column {
//Part 1
val count = remember { mutableStateOf(0) }
//Part 2
Text(
text = "I've been clicked ${count.value} times",
)
//Part 3
Button(onClick = { count.value++ }) {
Text("Click me")
}
//Part 4
if (count.value == 3) {
Log.e("My","This is test")
Toast.makeText(LocalContext.current, "3 times clicked", Toast.LENGTH_LONG).show()
}
//Part 5
Log.e("My","Is it always displayed?")
Toast.makeText(LocalContext.current, "Is it always displayed", Toast.LENGTH_LONG).show()
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BasicsCodelabTheme {
Surface{
Counter()
}
}
}
}
}
Added Content
In Code B, I know the Part A will be relaunched when the value of displayFullItemByID
has changed.
-
Will Part B be relaunched when the value of
displayFullItemByID
has changed ? -
Will Part C be relaunched when the value of
displayFullItemByID
has changed and it’s equal to 5 ?
Code B
class VoiceAdapters (private val aHomeViewModel: HomeViewModel) {
fun bind(inputMVoice: MVoice) {
aHomeViewModel.displayFullItemByID.observe(mLifecycleOwner) {
//Part A
_isDisplayed.value = inputMVoice.id == it
}
//Part B
Log.e("My","Can I relaunched in Part B")
if (aHomeViewModel.displayFullItemByID.value==5) {
//Part C
Log.e("My","Can I relaunched in Part C")
}
}
}
class HomeViewModel() : AndroidViewModel(mApplication) {
private val _displayFullItemByID = MutableLiveData(-1)
val displayFullItemByID: LiveData<Int> = _displayFullItemByID
...
}
2
Answers
A
Toast
is an example of a side-effect – something that affects the state of the device outside of the Composable itself (in this particular case, having the system show a toast message).As per the documentation, compositions should be side-effect free – a core part of the mental model is that the actual composition of a
@Composable
function could happen many, many times.So yes, any reads of
count.value
will cause that composable function to recompose (i.e., be executed again). However, this probably isn’t what you want in the case of aToast
message – you wouldn’t want multiple toast messages, just the one when the value first changes to 3.This is one of the use cases for
LaunchedEffect
, which only runs its block when the input parameters change:So let me start with the CODE A
Answer: If a compose has a local state variable then anytime the state variable is changed then the whole
@Composable
function gets reinvoked and recomposition happens. Regardless of whether it’s logic code or UI code…Answer: Yes each time when there is a recomposition i.e in this case the change of count causes recomposition… then whole Counter() is called again and hence the part 5 is also called again and again
Coming to CODE B as mentioned by ianhanniballake it has nothing to do with the Compose and
Other Important Things You Should Know :
You should understand how recomposition works actually from Thinking In Compose Article because you got this question just because of lack of not knowing how recompose actually works…
one point about recomposition mentioned in that is
An example would be, consider this counter Composable()
In the above composable function there is one more Compose() called ShowText().
Key things to understand in this example code is …