Tim Rösler
01/20/2022, 12:59 PM@Composable
fun MyComposeApp(modifier: Modifier = Modifier, viewModel: MyAppViewModel = getStateViewModel()) {
...
ConstraintLayout(modifier = modifier
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
Log.d("xxx","TabGestures: longPress recognized")
viewModel.switchToEditMode(true)
})
}
My state class look like this:
data class MyAppState(
...
val editMode: Boolean = false,
MyAppViewModel:
class MyAppViewModel(
private val repository: MyAppRepository,
private val savedState: SavedStateHandle
) : ContainerHost<MyAppState, Nothing>, ViewModel() {
override val container = container<MyAppState, Nothing>(
MyAppState(...)
) {
...
}
fun switchToEditMode(editMode: Boolean) {
Log.d("xxx","1 switchToEditMode: $editMode")
intent {
Log.d("xxx","2 switchToEditMode")
reduce {
state.copy(
editMode = editMode,
...
)
}
Log.d("xxx","3 switchToEditMode")
}
}
My code is embedded in some Fragment pages with a pager implementation.
The Compose code is rendered on one of those Fragments.
Due to some legacy code and extended Drag&Drop functionality I was not able to use Compose for the rest of the Fragment pages. On that legacy Fragment pages (Kotlin code) I'm using Drag&Drop functionality enabled by long-press. This code and all the relevant classes are separated from the Compose code (see above). So there shouldn't be any interference.
The only code they share is the whole fragment pager logic.
But the content of this single compose ui is embedded like this:
class MyComposeFragment : Fragment() {
val myAppViewModel: MyAppViewModel by viewModel()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
HomeTheme {
MyComposeApp(Modifier.fillMaxSize(), MyAppViewModel)
}
}
}
}
}
Bug scenario: As long as I do not perform any drag&drop on those legacy code pages, the Compose impl. and Orbit code works like charm. Then I perform a drag&drop gesture on those non Compose code pages and swipe back to my Fragment using the Compose code above. The Compose code on longpress calls:
viewModel.switchToEditMode(true)
and the Log is printed. This now leads to my viewModel where the following function is called:
fun switchToEditMode(editMode: Boolean) {
Log.d("xxx","1 switchToEditMode: $editMode")
...
This log is printed as well but it seems that the complete intent { } block is not going to be executed anymore. At least I cannot see my logs in there.
NOTE: Clicks on the Compose UI are still possible and show a result and also the long-press gesture seems to be recognized correctly. It's just that the intent block is not executed anymore.
Can anybody give a hint or explain to me why and in what situations the intent {} block will not be executed anymore?
How can I fix or work-around? Help is highly appreciated.Oleksii Malovanyi
01/20/2022, 1:08 PMintent{}
(but I don’t remember what is the behaviour if the exceptionHandler is not installed) or some kind of dead loop with state subscriptionTim Rösler
01/20/2022, 4:55 PMval handler = CoroutineExceptionHandler { _, exception ->
Log.d("xxx","CoroutineExceptionHandler got $exception")
}
override val container = container<MyAppState, Nothing>(
MyAppState(...), Container.Settings(exceptionHandler = handler)
) {
Any other idea or things I can do/try out?Tim Rösler
01/21/2022, 4:51 PMpublic fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.intentx(
registerIdling: Boolean = true,
transformer: suspend SimpleSyntax<STATE, SIDE_EFFECT>.() -> Unit
): Unit {
Log.d("OOO", "0 intentx")
kotlinx.coroutines.runBlocking {
Log.d("OOO", "1 intentx")
container.orbit {
Log.d("OOO", "2 intentx")
withIdling(registerIdling) {
SimpleSyntax(this).transformer()
}
}
}
}
fun switchToEditMode(editMode: Boolean) {
Log.d("OOO", "0 switchToEditMode: $editMode")
intentx {
//intent {
Log.d("OOO", "1 switchToEditMode: $editMode state: ${state.editMode} ")
reduce {
state.copy(
editMode = editMode,
...
)
}
Log.d("OOO", "2 switchToEditMode: $editMode state: ${state.editMode} ")
}
}
In my bug scenario the .intentx function prints the logs until Log.d("OOO", "1 intentx").
The last one in the "container.orbit" is NOT printed out.
If I understand this correctly the intents should now be in the orbit event loop and waiting to be processed.
But what can hold them back, not to be taken and processed by orbit?
Note: It seems that in this bug scenario non of my orbit intents can go through anymore.
Feedback is highly appreciated.