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代码,更安全高效:
- 在模块级
build.gradle中启用View Binding:
android { ... buildFeatures { viewBinding true } }
- 修改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
相关产品推荐
相关产品推荐

