Srikrishna
08/02/2023, 7:05 AMStylianos Gakis
08/02/2023, 7:33 AMSrikrishna
08/02/2023, 8:31 AMimport android.annotation.SuppressLint
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.Timer
import java.util.TimerTask
import kotlin.random.Random
fun timerRepeat(delay: Long, runnable: suspend () -> Unit) {
Timer().scheduleAtFixedRate(object : TimerTask() {
override fun run() {
CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>).launch {
runnable()
}
}
}, 0, delay)
}
@Composable
fun MainScreen() {
// Column(modifier = Modifier.fillMaxSize()) {
// Navigator(ImageListScreen()) {
// CurrentScreen()
// }
// }
val flow = remember {
val flow = MutableStateFlow(0)
timerRepeat(1000) {
flow.value = flow.value + 1
}
flow
}
TestContainer(flow = flow)
}
@Composable
fun TestContainer(flow: StateFlow<Int>) {
val value = flow.collectAsStateWithLifecycle().value
TestWidget.Widget(count = value)
}
open class Initializer {
private var objectId = Random.nextInt(100, 200)
private var update = 0
val initialized: StateFlow<String> = MutableStateFlow("Initializer.$objectId.${update++}")
fun initComplete() {
(initialized as MutableStateFlow).value = "Initializer.$objectId.done"
}
fun isInitialized(): Boolean {
return initialized.value.contains("done")
}
}
abstract class Widget : Initializer() {
private var objectId = Random.nextInt(100, 200)
abstract fun init()
@Composable
protected abstract fun build()
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun Content() {
val value = super.initialized.collectAsStateWithLifecycle().value
Timber.v("[$objectId] initialized.value:$value, isInitialized():${super.isInitialized()}")
val scope = rememberCoroutineScope()
scope.launch {
init()
initComplete()
}
if (value.contains("done")) {
this.build()
}
}
}
class TestWidget(private val count: Int) : Widget() {
companion object {}
override fun init() {
}
@Composable
override fun build() {
Text("Hello $count")
}
}
@Composable
fun TestWidget.Companion.Widget(count: Int) {
val widget = remember { mutableStateOf(TestWidget(count)) }
LaunchedEffect(key1 = count, block = {
widget.value = TestWidget(count)
})
widget.value.Content()
}
29426-29426 Widget in.cjcj.jcp V [196] initialized.value:Initializer.100.0, isInitialized():false
29426-29426 Widget in.cjcj.jcp V [127] initialized.value:Initializer.100.done, isInitialized():false
29426-29426 Widget in.cjcj.jcp V [173] initialized.value:Initializer.165.done, isInitialized():false
val value = super.initialized.collectAsStateWithLifecycle().value
Timber.v("[$objectId] initialized.value:$value, isInitialized():${super.isInitialized()}")
initialization is considered done if initialized value contains done. calling manually .value return the right value but collectAsStateWithLifecycle return old object valueStylianos Gakis
08/02/2023, 11:15 AM@Composable
fun Content() {
val value = super.initialized.collectAsStateWithLifecycle().value
Timber.v("[$objectId] initialized.value:$value, isInitialized():${super.isInitialized()}")
val scope = rememberCoroutineScope()
scope.launch {
init()
initComplete()
}
if (value.contains("done")) {
this.build()
}
}
you’re launching a coroutine in composition, and calling build
in composition too. Don’t know if this is where the problem is, but I’d definitely fix those as a first stepSrikrishna
08/09/2023, 5:09 PMfun <T> StateFlow<T>.state(scope: CoroutineScope): State<T> {
val flow = this
val state = mutableStateOf(flow.value, referentialEqualityPolicy())
scope.launch {
flow.collect {
withContext(Dispatchers.Main) {
state.value = it
}
}
}
return state
}
replacing collectAsStateWithLifecycle with state solved my problem.Srikrishna
08/09/2023, 5:10 PMscope.launch {
init()
initComplete()
}
is this is a problemStylianos Gakis
08/09/2023, 5:14 PM