android - 用视图绑定替换 kotlin 合成后应用程序被强制关闭
问题描述
我试图学习有关 android 的新知识,但是当我将项目更改为使用视图绑定时,应用程序强制在启动时关闭。找出导致强制关闭问题的原因对我来说将是一个非常大的帮助。
这是 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)
}
}
}
}
这是 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)
}
}
如果你能帮我解决这个问题,那将是一个非常大的帮助。
解决方案
这是MessagingAdapter
可能适合您的基本布局。然后,onBindViewHolder
您可以使用 访问您的视图holder.binding.viewId
。您可以根据需要进行调整。
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
}
推荐阅读
- excel - 如果单元格 A2:A1000 包含任何字母或数字,请将今天的日期放在同一行
- javascript - 如何显示多个满足条件的数组元素?
- java - 未指定的弹簧配置文件加载
- python - 在多个 python 进程之间共享 RabbitMQ 通道
- java - Android SyncService 在 120 秒后完全销毁
- vb.net - 无法取消运行 SQL 查询的后台工作程序
- ruby - 为什么在 32 位 Linux 上需要从 Rust 编译的共享对象时出现编码错误?
- python - 用不同的值替换现有的 EC2 标签
- jquery - 具有 hasClass() 问题的多个选择器
- r - 如何使用 tryCatch() 忽略 R 中的 while 循环中的错误