简体   繁体   English

用视图绑定替换 kotlin 合成后应用程序强制关闭

[英]App is force closing after replacing kotlin synthetics with view binding

I was trying to learn new things about android, but as I was changing the project to use viewbinding, the app force closes on launch.我试图了解有关 android 的新知识,但是当我将项目更改为使用视图绑定时,应用程序强制在启动时关闭。 It will be a really big help for me to find out what is causing the force close issue.找出导致强制关闭问题的原因对我来说将是一个非常大的帮助。

This is the MainActivity.kt code这是 MainActivity.kt 代码

class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"

//You can ignore this messageList if you're coming from the tutorial,
// it was used only for my personal debugging
var messagesList = mutableListOf<Message>()

private lateinit var adapter: MessagingAdapter
private val botList = listOf("Peter" , "Peter" , "Peter" , "Peter")
private lateinit var binding: ActivityMainBinding


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    recyclerView()

    clickEvents()

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

private fun clickEvents() {

    //Send a message
    binding.btnSend.setOnClickListener {
        sendMessage()
    }

    //Scroll back to correct position when user clicks on text view
    binding.etMessage.setOnClickListener {
        GlobalScope.launch {
            delay(100)

            withContext(Dispatchers.Main) {
                binding.rvMessages.scrollToPosition(adapter.itemCount - 1)

            }
        }
    }
}

private fun recyclerView() {
    adapter = MessagingAdapter()
    binding.rvMessages.adapter = adapter
    binding.rvMessages.layoutManager = LinearLayoutManager(applicationContext)

}

override fun onStart() {
    super.onStart()
    //In case there are messages, scroll to bottom when re-opening app
    GlobalScope.launch {
        delay(100)
        withContext(Dispatchers.Main) {
            binding.rvMessages.scrollToPosition(adapter.itemCount - 1)
        }
    }
}

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

    if (message.isNotEmpty()) {
        //Adds it to our local list
        messagesList.add(Message(message, SEND_ID, timeStamp))
        binding.etMessage.setText("")

        adapter.insertMessage(Message(message, SEND_ID, timeStamp))
        binding.rvMessages.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
            binding.rvMessages.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))

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

} }

This is the MessagingAdapter.kt file这是 MessagingAdapter.kt 文件

class MessagingAdapter: RecyclerView.Adapter<MessagingAdapter.MessageViewHolder>() {

var messagesList = mutableListOf<Message>()
private lateinit var binding: MessageItemBinding

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.findViewById<View>(R.id.tv_message).apply {
                binding.tvMessage.text = currentMessage.message
                visibility = View.VISIBLE
            }
            holder.itemView.findViewById<View>(R.id.tv_bot_message).visibility = View.GONE
        }
        RECEIVE_ID -> {
            holder.itemView.findViewById<View>(R.id.tv_bot_message).apply {
                binding.tvBotMessage.text = currentMessage.message
                visibility = View.VISIBLE
            }
            holder.itemView.findViewById<View>(R.id.tv_message).visibility = View.GONE
        }
    }
}

fun insertMessage(message: Message) {
    this.messagesList.add(message)
    notifyItemInserted(messagesList.size)
}

} }

It would be a really big help if you could help me fix this.如果你能帮我解决这个问题,那将是一个非常大的帮助。

Here is a basic layout of the MessagingAdapter that may work for you.这是一个可能适合您的MessagingAdapter的基本布局。 Then within onBindViewHolder you can access your views with holder.binding.viewId .然后在onBindViewHolder ,您可以使用holder.binding.viewId访问您的视图。 You can adjust it as needed.您可以根据需要进行调整。

class MessagingAdapter(var messagesList: List<Message>) : 
    RecyclerView.Adapter<MessagingAdapter.MessageViewHolder>() {

    inner class MessageViewHolder(val binding: MessageItemBinding) :
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
        val view =
            MessageItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return MessageViewHolder(view)
    }
    //other required implementations
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM