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

Kotlin中RecyclerView.setAdapter空指针异常排查求助

Android应用Fragment中RecyclerView空指针崩溃解决方案

错误日志

java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.widget.RecyclerView$Adapter)' on a null object reference 
at com.example.accers.ChatFragment.recyclerView(ChatFragment.kt:67)
at com.example.accers.ChatFragment.onCreateView(ChatFragment.kt:41)

问题根源

ChatFragment中直接使用rv_messages、btn_send、et_message等控件ID,但未通过view.findViewById或View Binding完成控件初始化,导致这些变量为null,调用方法时触发空指针异常。

修复方案

方案1:使用findViewById初始化控件

修改ChatFragment的onCreateView及相关方法,确保所有控件都通过view实例获取:

class ChatFragment : Fragment() {
    private val TAG = "ChatFragment"

    var messagesList = mutableListOf<Message>()

    private lateinit var adapter: MessagingAdapter
    private val botList = listOf("Cassandra", "Francesca", "Luigi", "Nico","Lesley","Hiyle","Roselind")
    // 声明控件变量
    private lateinit var rv_messages: RecyclerView
    private lateinit var btn_send: Button
    private lateinit var et_message: EditText

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_chat, container, false)
        
        // 初始化所有控件
        rv_messages = view.findViewById(R.id.rv_messages)
        btn_send = view.findViewById(R.id.btn_send)
        et_message = view.findViewById(R.id.et_message)

        recyclerView()
        clickEvents()

        val random = (0..3).random()
        customBotMessage("Hello! Today you're speaking with ${botList[random]}, how may I help?")

        return view
    }

    // 其余方法保持原有逻辑不变
}

方案2:使用View Binding(推荐)

View Binding可避免手动编写findViewById代码,更安全高效:

  1. 在模块级build.gradle中启用View Binding:
android {
    ...
    buildFeatures {
        viewBinding true
    }
}
  1. 修改ChatFragment代码:
class ChatFragment : Fragment() {
    private val TAG = "ChatFragment"

    var messagesList = mutableListOf<Message>()

    private lateinit var adapter: MessagingAdapter
    private val botList = listOf("Cassandra", "Francesca", "Luigi", "Nico","Lesley","Hiyle","Roselind")
    private lateinit var binding: FragmentChatBinding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        binding = FragmentChatBinding.inflate(inflater, container, false)

        recyclerView()
        clickEvents()

        val random = (0..3).random()
        customBotMessage("Hello! Today you're speaking with ${botList[random]}, how may I help?")

        return binding.root
    }

    private fun clickEvents() {
        binding.btn_send.setOnClickListener {
            sendMessage()
        }

        binding.et_message.setOnClickListener {
            viewLifecycleOwner.lifecycleScope.launch {
                delay(100)
                binding.rv_messages.scrollToPosition(adapter.itemCount - 1)
            }
        }
    }

    private fun recyclerView() {
        adapter = MessagingAdapter()
        binding.rv_messages.adapter = adapter
        binding.rv_messages.layoutManager = LinearLayoutManager(activity)
    }

    override fun onStart() {
        super.onStart()
        viewLifecycleOwner.lifecycleScope.launch {
            delay(100)
            binding.rv_messages.scrollToPosition(adapter.itemCount - 1)
        }
    }

    private fun sendMessage() {
        val message = binding.et_message.text.toString()
        val timeStamp = Time.timeStamp()

        if (message.isNotEmpty()) {
            messagesList.add(Message(message, SEND_ID, timeStamp))
            binding.et_message.setText("")

            adapter.insertMessage(Message(message, SEND_ID, timeStamp))
            binding.rv_messages.scrollToPosition(adapter.itemCount - 1)

            botResponse(message)
        }
    }

    private fun botResponse(message: String) {
        val timeStamp = Time.timeStamp()

        viewLifecycleOwner.lifecycleScope.launch {
            delay(1000)
            val response = BotResponse.basicResponses(message)

            messagesList.add(Message(response, RECEIVE_ID, timeStamp))
            adapter.insertMessage(Message(response, RECEIVE_ID, timeStamp))

            binding.rv_messages.scrollToPosition(adapter.itemCount - 1)

            when (response) {
                OPEN_GOOGLE -> {
                    val site = Intent(Intent.ACTION_VIEW)
                    site.data = Uri.parse("https://www.google.com/")
                    startActivity(site)
                }
                OPEN_SEARCH -> {
                    val site = Intent(Intent.ACTION_VIEW)
                    val searchTerm: String? = message.substringAfterLast("search")
                    site.data = Uri.parse("https://www.google.com/search?&q=$searchTerm")
                    startActivity(site)
                }
            }
        }
    }

    private fun customBotMessage(message: String) {
        viewLifecycleOwner.lifecycleScope.launch {
            delay(1000)
            val timeStamp = Time.timeStamp()
            messagesList.add(Message(message, RECEIVE_ID, timeStamp))
            adapter.insertMessage(Message(message, RECEIVE_ID, timeStamp))

            binding.rv_messages.scrollToPosition(adapter.itemCount - 1)
        }
    }
}

额外优化建议

  • 确保message_item.xml布局中存在tv_message和tv_bot_message两个TextView,避免Adapter中触发空指针。
  • 替换GlobalScope为viewLifecycleOwner.lifecycleScope,符合Android生命周期管理规范,防止内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 22:20:46