使用Navigation组件搭配ViewBinding时NavHostFragment加载失败问题
问题根因
崩溃是由初始化时序错误导致:你将ViewBinding通过Dagger注入,注入动作在super.onCreate()执行前触发,此时Activity的FragmentManager相关组件还未完成初始化,FragmentHostCallback为null。调用ViewBinding.inflate解析布局时,布局中的<fragment>标签会触发系统实例化NavHostFragment,调用FragmentHostCallback.getContext()时就触发了空指针。
解决方案
方案1(推荐):移除Dagger注入ViewBinding逻辑,改为基类手动初始化
这是官方推荐的ViewBinding使用方式,从根源避开时序冲突:
- 修改基类实现:
abstract class ViewBindingBaseActivity<VB : ViewBinding> : DaggerAppCompatActivity() { private var _binding: VB? = null protected val binding get() = _binding!! abstract fun inflateBinding(inflater: LayoutInflater): VB override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) _binding = inflateBinding(layoutInflater) setContentView(binding.root) } override fun onDestroy() { super.onDestroy() _binding = null // 避免内存泄漏 } }
- 对应修改Activity实现:
class OnboardingActivity : ViewBindingBaseActivity<ActivityOnboardingBinding>() { override fun inflateBinding(inflater: LayoutInflater) = ActivityOnboardingBinding.inflate(inflater) @Inject lateinit var onboardingActivityViewModel: OnboardingActivityViewModel @Inject lateinit var userProfileViewModel: UserProfileViewModel // 其他原有逻辑保持不变 }
- 删除Dagger中ViewBinding的相关注入配置。
方案2:保留Dagger注入逻辑,调整Fragment初始化方式
如果必须保留通过Dagger注入ViewBinding的逻辑,修改布局中Fragment的声明和初始化逻辑:
- 将布局中的
<fragment>标签替换为FragmentContainerView,去掉class属性:
<androidx.fragment.app.FragmentContainerView android:id="@+id/navOnboardingHost" android:layout_width="match_parent" android:layout_height="0dp" app:defaultNavHost="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
- 在Activity的
onCreate中手动添加NavHostFragment:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (savedInstanceState == null) { val navHost = NavHostFragment.create(R.navigation.your_onboarding_nav_graph) supportFragmentManager.beginTransaction() .replace(R.id.navOnboardingHost, navHost) .setPrimaryNavigationFragment(navHost) .commit() } // 其他原有逻辑 }
内容的提问来源于stack exchange,提问作者Bipin Vayalu
相关产品推荐
相关产品推荐

