Jetpack Compose中如何避免从回退栈返回时重复执行LaunchEffect代码
问题根因
你遇到的是Jetpack Compose + Navigation Compose场景下的常见问题:从Screen B返回Screen A时,Screen A会触发重组合,如果你的LaunchedEffect绑定了会随页面状态变化的key、或是监听了页面生命周期的ON_START/ON_RESUME事件执行逻辑,就会导致代码重复执行。
解决方案
- 方案1:给
LaunchedEffect设置恒定key
直接用LaunchedEffect(Unit)或者LaunchedEffect(true)包裹你的代码,恒定key在页面组合的生命周期内不会发生变化,代码只会在Screen A首次进入组合时执行1次,从回退栈返回时不会重复触发。注意如果需要在页面被系统销毁重建(如旋屏)时重新执行代码,不要用该方案。 - 方案2:绑定位置变量作为执行key
如果你的逻辑仅需要在位置信息变化时执行,可以把location作为LaunchedEffect的key,写法如下:
只要location没有更新,就算页面触发重组合也不会重复执行代码。LaunchedEffect(location) { sharedPrefs.setUserLatLng(CURRENT_LOCATION_LAT_KEY, CURRENT_LOCATION_LNG_KEY, LatLng(location.latitude, location.longitude)) commonViewModel.onLatLngChange(LatLng(location.latitude, location.longitude)) } - 方案3:新增执行标记位做逻辑拦截
在ViewModel中新增布尔标记位,首次执行完成后标记为已执行,后续触发时直接跳过,适合需要全局仅执行一次的场景:// CommonViewModel中新增标记位 var hasLocationInitialized by mutableStateOf(false) private set // Screen A的LaunchedEffect逻辑调整 LaunchedEffect(Unit) { if (!commonViewModel.hasLocationInitialized) { sharedPrefs.setUserLatLng(CURRENT_LOCATION_LAT_KEY, CURRENT_LOCATION_LNG_KEY, LatLng(location.latitude, location.longitude)) commonViewModel.onLatLngChange(LatLng(location.latitude, location.longitude)) commonViewModel.hasLocationInitialized = true } } - 方案4:和页面生命周期解绑
如果该逻辑本身不需要绑定Screen A的生命周期,直接把位置更新的逻辑迁移到ViewModel的初始化方法中执行,完全不受页面跳转、回退的影响。
内容的提问来源于stack exchange,提问作者Suman Radhakrishnan
相关产品推荐
相关产品推荐

