Kotlin-尝试调用虚拟方法'void androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.wid



我试图运行应用程序,但当我试图访问底部导航栏的内容时,它崩溃了,其中有一个片段,片段包含一个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)

xml片段

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ChatFragment">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_layout_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#E4E4E4"
android:orientation="horizontal">
<EditText
android:id="@+id/et_message"
android:inputType="textShortMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight=".5"
android:background="@drawable/round_button"
android:backgroundTint="@android:color/white"
android:hint="Type a message..."
android:padding="10dp"
android:singleLine="true" />
<Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@drawable/round_button"
android:backgroundTint="#26A69A"
android:text="Send"
android:textColor="@android:color/white" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_messages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/ll_layout_bar"
tools:itemCount="20"
tools:listitem="@layout/message_item" />
<!--    <View-->
android:layout_below="@+id/dark_divider"
<!--        android:layout_width="match_parent"-->
<!--        android:layout_height="10dp"-->
<!--        android:background="#42A5F5"-->
<!--        android:id="@+id/dark_divider"/>-->
</RelativeLayout>
</FrameLayout>
<<h4>片段类/h4>
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")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var view = inflater.inflate(R.layout.fragment_chat, container, false)
// var button: Button = view.findViewById(R.id.btn_send)
recyclerView()
clickEvents()
val random = (0..3).random()
customBotMessage("Hello! Today you're speaking with ${botList[random]}, how may I help?")
return view
}
private fun clickEvents() {
//Send a message
btn_send.setOnClickListener {
sendMessage()
}
// Scroll back to correct position when user clicks on text view
et_message.setOnClickListener {
GlobalScope.launch {
delay(100)
withContext(Dispatchers.Main) {
rv_messages.scrollToPosition(adapter.itemCount - 1)
}
}
}
}

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

override fun onStart() {
super.onStart()
//In case there are messages, scroll to bottom when re-opening app
GlobalScope.launch {
delay(100)
withContext(Dispatchers.Main) {
rv_messages.scrollToPosition(adapter.itemCount - 1)
}
}
}
private fun sendMessage() {
val message = et_message.text.toString()
val timeStamp = Time.timeStamp()
if (message.isNotEmpty()) {
//Adds it to our local list
messagesList.add(Message(message, SEND_ID, timeStamp))
et_message.setText("")
adapter.insertMessage(Message(message, SEND_ID, timeStamp))
rv_messages.scrollToPosition(adapter.itemCount - 1)
botResponse(message)
}
}
private fun botResponse(message: String) {
val timeStamp = Time.timeStamp()
GlobalScope.launch {
//Fake response delay
delay(1000)
withContext(Dispatchers.Main) {
//Gets the response
val response = BotResponse.basicResponses(message)
//Adds it to our local list
messagesList.add(Message(response, RECEIVE_ID, timeStamp))
//Inserts our message into the adapter
adapter.insertMessage(Message(response, RECEIVE_ID, timeStamp))
//Scrolls us to the position of the latest message
rv_messages.scrollToPosition(adapter.itemCount - 1)
//Starts Google
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) {
GlobalScope.launch {
delay(1000)
withContext(Dispatchers.Main) {
val timeStamp = Time.timeStamp()
messagesList.add(Message(message, RECEIVE_ID, timeStamp))
adapter.insertMessage(Message(message, RECEIVE_ID, timeStamp))
rv_messages.scrollToPosition(adapter.itemCount - 1)
}
}
}
}

我的适配器类

class MessagingAdapter: RecyclerView.Adapter<MessagingAdapter.MessageViewHolder>() {
var messagesList = mutableListOf<Message>()
inner class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.setOnClickListener {
//Remove message on the item clicked
messagesList.removeAt(adapterPosition)
notifyItemRemoved(adapterPosition)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
return MessageViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.message_item, parent, false)
)
}
override fun getItemCount(): Int {
return messagesList.size
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
val currentMessage = messagesList[position]
when (currentMessage.id) {
SEND_ID -> {
holder.itemView.tv_message.apply {
text = currentMessage.message
visibility = View.VISIBLE
}
holder.itemView.tv_bot_message.visibility = View.GONE
}
RECEIVE_ID -> {
holder.itemView.tv_bot_message.apply {
text = currentMessage.message
visibility = View.VISIBLE
}
holder.itemView.tv_message.visibility = View.GONE
}
}
}
fun insertMessage(message: Message) {
this.messagesList.add(message)
notifyItemInserted(messagesList.size)
}
}

<<h4> MainActivity类/h4>主活动类有底部导航栏来取代碎片

val navHostFragment = supportFragmentManager.findFragmentById(R.id.mainContainer) as NavHostFragment
navController = navHostFragment.navController
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNavigationView)
setupWithNavController(bottomNavigationView, navController)

我尝试过类似的解决方案,但我仍然不知道如何应用类似的问题和错误。谢谢你

您正在使用kotlin合成材料。在内部,它将作为getView().findViewById(R.id.rv_messages)

工作由于在oncreateView中,您试图访问视图之前,甚至视图附加在片段布局树中。

getView()将始终返回null。

你可以做几件事。您可以将视图传递给回收器视图函数,并像view.rv_messages一样访问。

最好像下面这样处理。

否则可以移动与onViewCreated()相关的所有视图。在onCreateView()中,你只需要膨胀并返回视图。所以在onViewCreated()中,当它调用getView()时,因为视图已经在onCreateView中添加了,它将返回正确的视图对象。

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var view = inflater.inflate(R.layout.fragment_chat, container, false)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView()
clickEvents()
val random = (0..3).random()
customBotMessage("Hello! Today you're speaking with ${botList[random]}, how may I help?")
}

合成也已被弃用,目前不推荐使用。强烈建议您使用视图绑定来绑定视图。作为,早些时候我有一个奇怪的问题与合成,我已经在这里覆盖。

有关kotlin合成的更多细节,请参阅此处。

最新更新