KotlinLeaner
04/13/2023, 4:08 PM@Composable
function. I am collecting data in flow. When I tried the @Composable
function inside the activity. It's working fine without any problem, but when I write outside the class it not working. I don't understand the problem. Code in the threadKotlinLeaner
04/13/2023, 4:09 PMpackage com.hub.myapplication
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.hub.myapplication.databinding.ActivityMainBinding
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val viewModel by viewModels<MainActivityViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
viewModel.showBottomSheetContent.collect {
binding.bottomSheetComposeView.setContent {
ModalBottomSheetSample()
}
}
}
}
binding.buttonComposeView.setContent {
ButtonViewContent()
}
}
@Composable
fun ButtonViewContent() {
val scope = rememberCoroutineScope()
Column(Modifier.fillMaxSize()) {
Button(
onClick = {
scope.launch {
viewModel.showBottomSheetContent.emit(true)
}
}
) {
Text(text = "Open Bottom Sheet")
}
}
}
@Composable
@OptIn(ExperimentalMaterialApi::class)
fun ModalBottomSheetSample() {
val sheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden, skipHalfExpanded = true)
val scope = rememberCoroutineScope()
SideEffect {
scope.launch {
sheetState.show()
}
}
ModalBottomSheetContent(sheetState)
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ModalBottomSheetContent(sheetState: ModalBottomSheetState) {
ModalBottomSheetLayout(
sheetState = sheetState,
sheetContent = {
LazyColumn {
items(5) {
ListItem(
icon = {
Icon(
Icons.Default.Favorite,
contentDescription = null
)
},
text = { Text("Item $it") },
)
}
}
}
) {}
}
}
KotlinLeaner
04/13/2023, 4:10 PMpackage com.hub.myapplication
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.hub.myapplication.databinding.ActivityMainBinding
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val viewModel by viewModels<MainActivityViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
viewModel.showBottomSheetContent.collect {
binding.bottomSheetComposeView.setContent {
ModalBottomSheetSample()
}
}
}
}
binding.buttonComposeView.setContent {
ButtonViewContent()
}
}
@Composable
fun ButtonViewContent() {
val scope = rememberCoroutineScope()
Column(Modifier.fillMaxSize()) {
Button(
onClick = {
scope.launch {
viewModel.showBottomSheetContent.emit(true)
}
}
) {
Text(text = "Open Bottom Sheet")
}
}
}
}
@Composable
@OptIn(ExperimentalMaterialApi::class)
fun ModalBottomSheetSample() {
val sheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden, skipHalfExpanded = true)
val scope = rememberCoroutineScope()
SideEffect {
scope.launch {
sheetState.show()
}
}
ModalBottomSheetContent(sheetState)
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ModalBottomSheetContent(sheetState: ModalBottomSheetState) {
ModalBottomSheetLayout(
sheetState = sheetState,
sheetContent = {
LazyColumn {
items(5) {
ListItem(
icon = {
Icon(
Icons.Default.Favorite,
contentDescription = null
)
},
text = { Text("Item $it") },
)
}
}
}
) {}
}
Zach Klippenstein (he/him) [MOD]
04/13/2023, 6:03 PMZach Klippenstein (he/him) [MOD]
04/13/2023, 6:03 PMSideEffect
- a new coroutine will be launched on every recomposition.KotlinLeaner
04/13/2023, 6:29 PMKotlinLeaner
04/13/2023, 6:30 PMZach Klippenstein (he/him) [MOD]
04/14/2023, 12:00 AMthis
implicitly passed to the composables when they’re defined as members of your activity class are preventing some composable from skipping on repeated calls to setContent, so it’s working by accident because something is relying on recomposition to re-show the sheet. When you move the composables out of the class, they no longer capture this
, and so they can skip.KotlinLeaner
04/14/2023, 7:46 AM