You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何FragmentLoginBinding返回null?Stream SDK聊天应用空指针问题

问题原因

LoginFragment重写了onCreateView方法,并且在方法内部直接使用binding对象,但此时父类BindingFragment的onCreateView还未执行,_binding变量仍然是null,强制类型转换时触发NullPointerException。

解决方案

有两种修复方式,推荐第一种:

方式一:将视图初始化逻辑移至onViewCreated

子类不要重写onCreateView,而是在onViewCreated中处理控件绑定、事件监听等逻辑,此时父类已经完成binding的初始化:

修改后的LoginFragment代码:

@AndroidEntryPoint
class LoginFragment : BindingFragment<FragmentLoginBinding>() {

    override val bindingInflater: (LayoutInflater) -> ViewBinding
        get() = FragmentLoginBinding::inflate

    private val viewModel : LoginViewModel by viewModels()

    // 移除重写的onCreateView,使用父类的实现
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        binding.btnConfirm.setOnClickListener{
            setUpConnectingUIState()
            viewModel.connectUser(binding.etUsername.text.toString())
        }

        binding.etUsername.addTextChangedListener {
            binding.etUsername.error = null
        }

        subscribeToEvents()
    }

    private fun setUpConnectingUIState(){
        binding.progressBar.isVisible = true
        binding.btnConfirm.isVisible = false
    }

    private fun setUpIdealUIState(){
        binding.progressBar.isVisible = false
        binding.btnConfirm.isVisible = true
    }

    private fun subscribeToEvents(){
        lifecycleScope.launch {
            viewModel.logInEvent.collect{event ->
                when(event){
                    is LoginViewModel.LogInEvent.ErrorInputTooShort->{
                        setUpIdealUIState()
                        binding.etUsername.error =
                            getString(R.string.error_username_too_short,Constants.MIN_USERNAME_LENGTH)
                    }
                    is LoginViewModel.LogInEvent.ErrorLogIn->{
                        setUpIdealUIState()
                        Toast.makeText(
                            requireContext(),
                            event.error,
                            Toast.LENGTH_LONG
                        ).show()
                    }
                    is LoginViewModel.LogInEvent.Success->{
                        setUpIdealUIState()
                    }
                }
            }
        }
    }
}

方式二:重写onCreateView时先调用父类方法

如果必须重写onCreateView,需要先调用super.onCreateView()完成binding的初始化,再使用binding对象:

修改后的LoginFragment的onCreateView:

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // 先调用父类方法初始化binding
    val view = super.onCreateView(inflater, container, savedInstanceState)
    
    binding.btnConfirm.setOnClickListener{
        setUpConnectingUIState()
        viewModel.connectUser(binding.etUsername.text.toString())
    }

    binding.etUsername.addTextChangedListener {
        binding.etUsername.error = null
    }

    subscribeToEvents()

    return view
}
额外优化建议

可以给BindingFragment的binding属性添加空判断,避免潜在的空指针:

protected val binding: T
    get() = checkNotNull(_binding) { "Binding is only valid between onCreateView and onDestroyView" }

内容的提问来源于stack exchange,提问作者Navneet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:53:22