android-studio - Kotlin:runOnUiThread 未解决参考
问题描述
我正在尝试使用 Activity.runOnUiThread(Runnable),但 Android Studio 似乎认为该函数不存在。我已确保“android.app.Activity”已导入。
我正在尝试使用线程连接到蓝牙设备并读取数据。我已经列出了配对的设备,然后单击其中一个配对设备将我带到第二个屏幕,然后我可以在其中连接/断开所选设备的套接字。连接和断开连接正常。
我现在正试图将数据流从 readThread 内部类发送回 UI 线程,但我无法让 runOnUiThread 工作。无论我做什么 runOnUiThread 都无法识别。
package com.example.idxdatalogger
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.view.View
import android.app.Activity
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_second.*
import java.io.IOException
import java.io.InputStream
import java.util.*
class SecondActivity : AppCompatActivity() {
var btAdapter: BluetoothAdapter? = null
var data = arrayListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
btAdapter = BluetoothAdapter.getDefaultAdapter()
val position = (intent.getStringExtra("position"))!!.toInt()
val uuid = UUID.fromString(intent.getStringExtra("UUID"))
//textView.text = position.toString()
//textView2.text = uuid.toString()
val pairedDevices: Set<BluetoothDevice> = btAdapter!!.bondedDevices
btDeviceLabel.text = pairedDevices.elementAt(position).name.toString()
var inStream = connectStream(uuid, position, pairedDevices.elementAt(position), btAdapter)
conStat(inStream)
connectButton.setOnClickListener {
inStream.start()
conStat(inStream)
}
cancelButton.setOnClickListener {
inStream.cancel()
conStat(inStream)
inStream = connectStream(uuid, position, pairedDevices.elementAt(position), btAdapter)
}
}
/*
change text and button visiblity for connect/disconnect buttons
*/
fun conStat(inStream: connectStream) {
if (inStream.socket!!.isConnected) {
socketStatus.text = getString(R.string.connectionOpened)
connectButton.visibility = View.INVISIBLE
cancelButton.visibility = View.VISIBLE
} else {
socketStatus.text = getString(R.string.connectionClosed)
connectButton.visibility = View.VISIBLE
cancelButton.visibility = View.INVISIBLE
}
}
class connectStream(
private val uuid: UUID,
private val position: Int,
private val device: BluetoothDevice,
private val adapter: BluetoothAdapter?
) : Thread() {
val socket: BluetoothSocket? = device.createRfcommSocketToServiceRecord(uuid)
override fun run() {
adapter?.cancelDiscovery()
try {
socket?.connect()
manageConnection().readThread(socket!!).start()
} catch (e: IOException) {
Log.i("SOCKET: ", "Failed to connect")
Log.i("UUID: ", uuid.toString())
Log.i("Device: ", device.name)
Log.i("Address: ", device.address)
}
}
fun cancel() {
try {
socket?.close()
} catch (e: IOException) {
Log.i("SOCKET: ", "Could not close socket")
}
}
}
class manageConnection() {
private val MESSAGE_READ: Int = 0
inner class readThread(socket: BluetoothSocket) : Thread() {
private val inStream: InputStream = socket.inputStream
private val inBuffer: ByteArray = ByteArray(1024)
override fun run() {
var readBytes: Int
while (true) {
readBytes = try { inStream.read(inBuffer)
} catch (e: IOException) {
Log.d("IN_STREAM: ", "Input stream disconnected")
break
}
SecondActivity.runOnUiThread(Runnable {
})
}
}
}
}
}
编辑:
重新编写我的程序以使用 Thread(Runnable{}) 而不是为每个线程使用单独的类实例。runOnUiThread 现在可以正常工作了。我已经在下面发布了我的更新代码,但这还没有完全发挥作用。现在,我们可以认为问题已解决。
package com.example.idxdatalogger
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.util.Log
import android.view.View
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.*
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_second.*
import java.io.IOException
import java.io.InputStream
import java.util.*
/*
*/
class SecondActivity : AppCompatActivity() {
var btAdapter: BluetoothAdapter? = null
var data = arrayListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
btAdapter = BluetoothAdapter.getDefaultAdapter()
val position = (intent.getStringExtra("position"))!!.toInt()
val uuid = UUID.fromString(intent.getStringExtra("UUID"))
val pairedDevices: Set<BluetoothDevice> = btAdapter!!.bondedDevices
val device = pairedDevices.elementAt(position)
btDeviceLabel.text = pairedDevices.elementAt(position).name.toString()
val socket: BluetoothSocket? = device.createRfcommSocketToServiceRecord(uuid)
//var inStream = connectStream(uuid, position, pairedDevices.elementAt(position), btAdapter)
conStat(socket!!)
val inStream: InputStream = socket.inputStream
val inBuffer: ByteArray = ByteArray(1024)
var readBytes : Int
connectButton.setOnClickListener {
//connect to device
Thread(Runnable {
kotlin.run {
btAdapter?.cancelDiscovery()
try {
socket.connect()
runOnUiThread(Runnable { conStat(socket) })
//read stream
Thread(Runnable{
while(true) {
readBytes = try {
inStream.read(inBuffer)
} catch (e: IOException) {
Log.d("IN_STREAM: ", "input stream disconnected")
break
}
//return stream information to UI thread
runOnUiThread(Runnable {
data.add(inBuffer.toString())
dataList.adapter = dataListAdapter(this,data)
dataList.visibility = View.VISIBLE
})
}
}).start()
} catch (e: IOException) {
Log.i("SOCKET: ", "Failed to connect")
Log.i("UUID: ", uuid.toString())
Log.i("Device: ", pairedDevices.elementAt(position).name)
Log.i("Address: ", pairedDevices.elementAt(position).address)
}
}
}).start()
}
cancelButton.setOnClickListener {
//close socket connection
Thread(Runnable {
try {
socket.close()
} catch (e: IOException) {
Log.i("SOCKET: ", "Could not close socket")
}
runOnUiThread(Runnable {
conStat(socket)
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
})
}).start()
}
}
/*
change text and button visiblity for connect/disconnect buttons
*/
fun conStat(socket : BluetoothSocket) {
if (socket.isConnected) {
socketStatus.text = getString(R.string.connectionOpened)
connectButton.visibility = View.INVISIBLE
cancelButton.visibility = View.VISIBLE
} else {
socketStatus.text = getString(R.string.connectionClosed)
connectButton.visibility = View.VISIBLE
cancelButton.visibility = View.INVISIBLE
}
}
解决方案
SecondActivity.runOnUiThread(...)
是不正确的,因为您在类上调用方法并且runOnUiThread()
方法不是静态的。您需要在类的实例上调用此方法,Activity
而不是在类本身上。
推荐阅读
- sonarqube - Sonarqube 7.9.1 社区故障排除
- python - 需要使用python根据标题提取内容
- algorithm - 冒泡排序和分布排序算法的“问题大小”是多少?
- terraform-provider-aws - 如何在一个elb下添加多个实例
- python - 如何找到句子的核心上下文
- python - int64 数组和 int 的总和是否应该通过 int64 类型检查?
- c# - 使用非托管内存时出现奇怪的内存使用情况
- python - PYTEST - 如何使 CONFTEST.PY 在其他 python 目录中可用
- jmeter - 无法在另一个请求中使用 Beanshell 预处理器变量
- php - 表格数据输入未按预期工作。它只是在数据库中保存一条记录