navController.navigate()在lambda回调中调用不生效问题
问题场景
点击按钮后需要先发起POST请求,等请求完成后携带网络加载得到的bundle打开目标Fragment。
在不带bundle的测试场景下发现:把navigate方法写在网络请求回调中时无法正常跳转,但logcat可以正常打印Got login response日志,证明回调确实被执行;如果把changeFragmentToMessages()移到网络请求代码外侧、放在请求发起前调用,跳转功能完全正常,点击按钮就能打开目标Fragment。
对应代码如下:
fun changeFragmentToMessages() { findNavController().navigate(R.id.action_loginFragment_to_messagesFragment) } private fun loginButtonClicked(v:View) { val login = inputLogin.text.toString() val password = inputPassword.text.toString() Fuel .post(ReqUtils.getUri("loadchats")) .body( JSONObject( mapOf( "login" to login, "password" to password ) ).toString() ) .header("content-type", "application/json") .response { request, response, result -> Log.d("HTTP", "Got login response") changeFragmentToMessages() } }
问题原因
Fuel的response回调默认执行在子工作线程,Android系统要求所有UI相关操作(包括Navigation组件的页面导航操作)必须在主线程调用,子线程里直接调navigate不会触发正常跳转。
把跳转逻辑移到请求外层时,代码运行在按钮点击事件的主线程上下文里,所以可以正常工作。
解决方案
核心是把导航逻辑切到主线程执行,后续携带请求返回的bundle参数跳转也遵循这个规则即可,常见实现方式有两种:
- 利用当前点击的View对象直接切主线程,不需要额外引入依赖,改动最小:
.response { request, response, result -> Log.d("HTTP", "Got login response") // 切到主线程执行导航 v.post { // 后续需要传参时,在这里解析result生成Bundle传入即可 // 示例:val chatBundle = bundleOf("chatData" to 解析后的返回数据) // findNavController().navigate(R.id.action_loginFragment_to_messagesFragment, chatBundle) changeFragmentToMessages() } }
- 如果项目使用Kotlin协程,可以引入Fuel的协程扩展,在生命周期感知的协程作用域中处理请求,天然在主线程返回结果:
// 先引入对应协程扩展依赖 // implementation "com.github.kittinunf.fuel:fuel-coroutines:<当前使用的Fuel版本号>" private fun loginButtonClicked(v:View) { val login = inputLogin.text.toString() val password = inputPassword.text.toString() lifecycleScope.launch { val (request, response, result) = Fuel .post(ReqUtils.getUri("loadchats")) .body( JSONObject( mapOf( "login" to login, "password" to password ) ).toString() ) .header("content-type", "application/json") .awaitResponse() Log.d("HTTP", "Got login response") // lifecycleScope默认在主线程启动,直接执行导航即可 changeFragmentToMessages() } }
注意:所有和UI、组件导航相关的操作,都不要在子线程直接调用,否则会出现不生效、崩溃等不可预期的问题。
内容的提问来源于stack exchange,提问作者Nikitiy
相关产品推荐
相关产品推荐

