Comments (5)
@L-Andrade release the fix in 1.1.0-alpha02
from voyager.
If you could make a reproduceable of this would be awesome!
It seems that we should check the current state before emiting the stopEvents, aparently, it is already DESTROYED
, I really would want to be able to reproduce to validate a proper fix the code with a workaround :S but maybe a trycatch here or validate the current state would fix this.
private fun emitOnStopEvents() {
stopEvents.forEach {
lifecycle.handleLifecycleEvent(it)
}
}
from voyager.
@DevSrSouza Unfortunately I haven't managed to reproduce it yet 😞
Let me know if you have anything in mind that I can try to replicate it! I'll give it some more tries next week as well once I'm back to work
from voyager.
I believe this is due to a DataBinding component we have inside a Screen
. We were setting the lifecycleOwner
of this DataBinding component to the LocalLifecycleOwner
(which is an AndroidScreenLifecycleOwner
). Inside the generated DataBinding code, there are multiple things happening, including observers being attached to the lifecycle.
This issue is similar, albeit from a different context entirely: https://issuetracker.google.com/issues/184664896
I'm not sure how you folks want to deal with this, or if you want to deal with it at all. In that issue, they just checked the state before emitting it: https://android-review.googlesource.com/c/platform/frameworks/support/+/1673541/4/car/app/app/src/main/java/androidx/car/app/Screen.java#321
The way I managed to reproduce the issue was to make the DataBinding component appear, disappear, and then appear again. I needed some code changes to be able to reproduce it exactly, so I'm not entirely sure it is the only issue.
For now, I've removed the LifecycleOwner attribution from the DataBinding component. I believe it's used more when there's observers/collectors in the DataBinding component, but in this one we don't use it, and it is still working as expected, so it shouldn't be a big issue.
The build with this change will ship on the 15th of January. I'll ping here if the issue appears to be fixed. I might try to replicate it later in an empty project. Feel free to try it yourself as well, of course!
from voyager.
@DevSrSouza Here's a project that replicates the issue:
MainActivity.kt
:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
VoyagerDemoTheme {
SlideNavigator(InitialScreen())
}
}
}
}
@Composable
private fun SlideNavigator(navScreen: Screen) {
Navigator(navScreen) { navigator ->
SlideTransition(navigator)
}
}
class InitialScreen : Screen {
override val key: ScreenKey = uniqueScreenKey
@Composable
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
Button(onClick = { navigator.push(Screen1()) }) {
Text(text = "Push new Screen")
}
}
}
class Screen1 : Screen {
override val key: ScreenKey = uniqueScreenKey
@Composable
override fun Content() {
Box(modifier = Modifier.fillMaxSize()) {
var show by remember { mutableStateOf(false) }
LaunchedEffect(key1 = Unit) {
while (isActive) {
delay(250)
show = !show
}
}
if (!show) {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
} else {
val lifecycleOwner = LocalLifecycleOwner.current
AndroidViewBinding(
factory = { inflater, parent, attachToParent ->
LayoutDataBindingBinding.inflate(inflater, parent, attachToParent)
.apply {
this.lifecycleOwner = lifecycleOwner
}
},
) {
this.text = "Show: $show"
}
}
}
}
}
layout_data_binding.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="text"
type="String" />
</data>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{text}" />
</layout>
- Dependencies:
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
implementation("androidx.activity:activity-compose:1.7.2")
implementation(platform("androidx.compose:compose-bom:2023.10.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
val voyagerVersion = "1.0.0"
implementation("cafe.adriel.voyager:voyager-navigator:$voyagerVersion")
implementation("cafe.adriel.voyager:voyager-transitions:$voyagerVersion")
implementation("androidx.compose.ui:ui-viewbinding")
}
Once setup, you just need to navigate to the next screen and once it hides and shows a few times, navigate back. The crash occurs when navigating back.
Also managed to replicate the issue with this instead of the AndroidViewBinding
:
val lifecycleOwner = LocalLifecycleOwner.current
LaunchedEffect(key1 = Unit) {
lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {})
}
When using a DisposableEffect
and properly removing the observer in onDispose
, it did not crash. So it might mean that the DataBinding component is not properly clearing the observer?
Nevertheless, it might be nice if Voyager would be defensive here and only emit when it's supposed to, instead of creating these crashes. They're pretty hard to debug from an app perspective (even if there might be a leak on the app's end).
from voyager.
Related Issues (20)
- Could I nest a TabNavigator in another TabNavigator? HOT 4
- Backpress in Screen HOT 1
- How to use BackHandler in a Screen with TabNavigator?
- Add windowInsets to BottomSheet HOT 1
- Working with lifecycle events in common HOT 5
- Crash due to Parcelable encountered IOException writing serializable HOT 6
- Navigator inside Dialog doesn't push screen properly
- iOS build error HOT 4
- iOS-like swipe back navigation HOT 3
- Deeplinks and Voyager HOT 1
- Voyager hilt support broken with Dagger 2.51 HOT 1
- UI Testing HOT 1
- Choose Different Animation Transitions Based on Different Screens HOT 1
- navigator scoped for viewmodel (moko-mvvm) HOT 1
- [Question] How to navigate from ScreenModel/ViewModel? HOT 1
- Window inset imePadding stopped working in 1.1.0-alpha03 HOT 2
- Voyager Screen with a `ViewModel` does not have its `SavedStateHandle` saved on process death HOT 1
- Custom back handling depending on the currentScreen HOT 2
- Integration with KMMViewModel
- Nesting Navigators prevents WindowInsets from being updated upon device rotation on iOS
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from voyager.