Jetpack compose beta
Jetpack compose beta was released.
They said
With this beta release, Compose is API complete and has all the features you need to build production-ready apps. Beta also means API stable, so we won’t change or remove APIs. Now is a great time to start learning Compose and begin planning for how you will use it in an upcoming project or feature once it reaches 1.0 later this year.
Rather than looking into Jetpack compose as a whole, I just looked at the parts that interested me.
Basic application implementation style is like
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HelloScreen()
}
}
}
class HelloViewModel : ViewModel() {
private val _name = MutableLiveData("")
val name: LiveData<String> = _name
fun onNameChanged(newName: String) {
_name.value = newName
}
}
@Composable
fun HelloScreen(helloViewModel: HelloViewModel = viewModel()) { // viewModel is alpha yet.
val name: String by helloViewModel.name.observeAsState("")
Column {
Text(text = name)
TextField(
value = name,
onValueChange = { helloViewModel.onNameChanged(it) },
label = { Text("Name") }
)
}
}
When user change value of TextField, the value of ViewModel is changed.
State of HelloScreen is update, and compose is executed.
As a result, UI is updated.
It’s not the same as react, but I feel it’s a little similar.
Information is outdated, but interesting comparison
Statefull UI component
If you want to save some information to composable, you can use remember.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HelloScreen()
}
}
}
class HelloViewModel : ViewModel() {
private val _name = MutableLiveData("")
val name: LiveData<String> = _name
fun onNameChanged(newName: String) {
_name.value = newName
}
}
@Composable
fun HelloScreen(helloViewModel: HelloViewModel = viewModel()) { // viewModel is alpha yet.
val name: String by helloViewModel.name.observeAsState("")
Column {
NameHolder(name = name)
TextField(
value = name,
onValueChange = { helloViewModel.onNameChanged(it) },
label = { Text("Name") }
)
}
}
@Composable
fun NameHolder(name: String) {
var isRed by remember { mutableStateOf(false)}
val color = if (isRed) {
Color.Red
} else {
Color.Black
}
Column {
Text(text = name, color = color)
Button(onClick = { isRed = !isRed }) {
Text(text = "change color")
}
}
}
We can use glide
My personal concerns points
- There doesn’t seem to be an easy way to set the margin.
We can set margin by using Spacer. But spacer do not accept negative value.
We can use Box to display the UI on top of each other, but there may be case that you want to use negative margin.
One of the things I was interested in was CompositionLocal.
https://developer.android.com/reference/kotlin/androidx/compose/runtime/CompositionLocal
In jetpack compose, CompositionLocal is used like this.
@Composable
fun App(user: User) {
CompositionLocalProvider(ActiveUser provides user) {
SomeScreen()
}
}@Composable
fun SomeScreen() {
UserPhoto()
}@Composable
fun UserPhoto() {
val user = ActiveUser.current
ProfileIcon(src = user.profilePhotoUrl)
}
We can access user instance inside UserPhoto.
Scaffold
https://developer.android.com/jetpack/compose/layout#slot-based-layouts
Scaffold makes it easy to support Material Design.
Before reading the API, I thought that Jetpack compose is inspired by FlexBox, since react uses FlexBox and the basic idea of Flutter’s UI components is based on FlexBox.
But I could not find out API which is similar to FlexBox…
This is deprecated document
It seems that there were Flex.kt and other API.
I could not find out the reason why they remove them.
If we want to use layout like FlexBox, we need to create custom layout like this
https://developer.android.com/jetpack/compose/layout#create-custom
Although nothing is exactly the same, I have the impression that it has been influenced by React and Flutter as well.
Provider, Scaffold, Key, etc. are also common in Flutter.
One thing that surprised me was the lack of support for FlexBox, but maybe they prioritized keeping it simple.