android - 如何在 BroadcastReceiver.onReceive 中设置 RecyclerView.ViewHolder 的颜色?

标签 android bluetooth broadcastreceiver kotlin

我正在创建一个扫描并配对蓝牙设备的应用程序。我在 RecyclerView 中显示设备,并通过为该设备的 ViewHolder 着色来指示绑定(bind)状态。我的问题是 ViewHolder 的颜色仅在再次扫描设备后才更改,我希望它在配对或取消配对时立即更新颜色。我试图通过使用广播接收器来做到这一点,但我无法获得对正确 ViewHolder 的引用。我怎样才能做到这一点?我在下面包含了我的 RecyclerView.Adapter 代码和包含广播接收器的 BluetoothUtils 文件。提前致谢。我的适配器:

class DeviceAdapter(val mContext : Context) : RecyclerView.Adapter<DeviceAdapter.DeviceHolder>() {

companion object {
    val TAG = "Device Adapter"

    fun DeviceHolder.setColor(bonded: Boolean):Unit{
        val background = if (bonded)Color.CYAN else Color.TRANSPARENT
        this.itemView.setBackgroundColor(background)
    }

}

val mDevices = ArrayList<BluetoothDevice>()

fun updateItems(list: ArrayList<BluetoothDevice>) {
    mDevices.clear()
    mDevices.addAll(list)
    Log.d(TAG, "updating items : $mDevices")
    notifyDataSetChanged()
}

fun ViewGroup.inflate(@LayoutRes res: Int, attachToRoot: Boolean = false): View {
    return LayoutInflater.from(mContext).inflate(res, this, attachToRoot)
}

override fun onBindViewHolder(holder: DeviceHolder, position: Int) {
    Log.d(TAG, "onBindViewHolder called!")
    holder.bindItems(mDevices.get(position))
    if (mDevices.get(position).bondState==BluetoothDevice.BOND_BONDED) {
        holder.itemView.setBackgroundColor(CYAN)
    } else {
        holder.itemView.setBackgroundColor(Color.TRANSPARENT)
    }
}

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): DeviceAdapter.DeviceHolder {
    Log.d(TAG, "onCreateViewHolder called!")
    val v = parent!!.inflate(R.layout.device_item, false)
    return DeviceHolder(v)
}

override fun getItemCount(): Int {
    return mDevices.size
}

inner class DeviceHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    val nameView = itemView.findViewById(R.id.nameView) as TextView
    val addrView = itemView.findViewById(R.id.addressView) as TextView
    var dialog: AlertDialog? = null;

    fun bindItems(btDevice: BluetoothDevice) {
        Log.d(TAG, "holder created!")
        nameView.text = btDevice.name ?: "Unknown"
        addrView.text = btDevice.address
        itemView.setOnClickListener {
            dialog = AlertDialog.Builder(it.context)
                    .setTitle("Options")
                    .setView(R.layout.options_dialog_layout)
                    .setNegativeButton("Cancel", DialogInterface.OnClickListener { _, which -> })
                    .create()
            dialog!!.show()
            val ops = listOf(
                    dialog!!.findViewById(R.id.statOp),
                    dialog!!.findViewById(R.id.pairOp),
                    dialog!!.findViewById(R.id.connectOp),
                    dialog!!.findViewById(R.id.sendOp),
                    dialog!!.findViewById(R.id.unPairOp)
            )
            ops.forEach { it.setOnClickListener {
                Toast.makeText(it.context, it.id.toString(), Toast.LENGTH_SHORT).show()
                when(it.id){
                    R.id.statOp -> {}
                    R.id.connectOp -> {
                        Log.d(TAG, "connectOp reached")
                        BluetoothReflection.connectDevice(btDevice)
                        dialog!!.dismiss()
                    }// BluetoothUtils.connect(BluetoothAdapter.getDefaultAdapter(), btDevice)
                    R.id.pairOp -> {
                        Log.d(TAG, "pairOp reached")
                        BluetoothUtils.startPair(BluetoothAdapter.getDefaultAdapter(), btDevice)
                        if (btDevice.bondState==BluetoothDevice.BOND_BONDED){
                            this@DeviceHolder.itemView.setBackgroundColor(CYAN) //doesn't work
                        }
                        Log.d(TAG, "start pair complete")
                        dialog!!.dismiss()
                    }//
                    R.id.unPairOp -> {//no executable code found here
                        Log.d(TAG, "unPairOp reached")
                        BluetoothUtils.unPair(btDevice)
                        if (btDevice.bondState==BluetoothDevice.BOND_NONE){
                            this@DeviceHolder.itemView.setBackgroundColor(Color.TRANSPARENT) //doesn't work
                        }
                        Log.d(TAG, "unpair complete")
                        dialog!!.dismiss()
                    }
                    R.id.sendOp -> {}
                }
            } }
        }

    }
}
}

和我的 BluetoothUtils:

class BluetoothUtils {

companion object {

    var listener: ListenThread? = null

    val _UUID = UUID.fromString("a0e7e4c7-0e4e-43b7-9d18-659192512164")
    val TAG = "BluetoothUtils"

    val receiver = MainBTStatusReceiver()

    fun initPairingServer(adapter: BluetoothAdapter){
        var mmServerSocket: BluetoothServerSocket?
        try {
            var tmp = adapter.listenUsingRfcommWithServiceRecord(TAG, _UUID)
            mmServerSocket = tmp
            listener = ListenThread(mmServerSocket)
            listener!!.start()
        }catch (ioe: IOException){
            Log.e(TAG, "Error initializing Bluetooth", ioe)
        }
    }

    fun cancelListener() = listener!!.cancel()

    fun connect(adapter: BluetoothAdapter, device: BluetoothDevice){
        var btSocket: BluetoothSocket?

        try {
            adapter.cancelDiscovery()
            btSocket = device.createRfcommSocketToServiceRecord(_UUID)
            PairingThread(btSocket).start()
        }catch (ioe: IOException){
            Log.e(TAG, "error connecting", ioe)
        }
    }

    fun startPair(adapter: BluetoothAdapter, device: BluetoothDevice): Unit{
        adapter.cancelDiscovery()
        Log.d(TAG, device.bondState.toString())
        device.createBond()
    }

    fun unPair(device: BluetoothDevice): Any = device::class.java.getMethod("removeBond").invoke(device)

}
}

class ListenThread(val btServSock: BluetoothServerSocket) : Thread(){

companion object {
    val TAG = "ListenThread"
}

var btSocket: BluetoothSocket? = null

override fun run() {
    super.run()
    while (true){
        try {
            Log.d(TAG, "listening . . . ")
            btSocket = btServSock.accept()
        }catch (ioe: IOException){
            Log.e(TAG, "Error", ioe) // SHOULD HANDLE FAILURE OF LISTENER INSTANTIATION
            break
        }

        //manage connection here
        //with either BluetoothUtils function
        //or BluetoothSocket extension
    }
}

fun cancel() = btServSock.close()
}

class PairingThread(val btSocket: BluetoothSocket) : Thread(){

companion object {
    val TAG = "Pairing Thread"
}

override fun run() {
    super.run()

    try {
        Log.d(TAG, "attempting to connect")
        btSocket.connect()
    }catch (ioe: IOException){
        Log.e(TAG, "error connecting", ioe)
        btSocket.close()
    }
}
}


class MainBTStatusReceiver(): BroadcastReceiver(){

val TAG = "MainBTStatusReceiver"
var mAdapter: DeviceAdapter? = null

fun setAdapter(adapter: DeviceAdapter){
    mAdapter = adapter
}

override fun onReceive(context: Context?, intent: Intent) {
    val action = intent.action
    val devExtra = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) as BluetoothDevice
    when(action){
        BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {
            val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
            when(device.bondState){
                BluetoothDevice.BOND_BONDED -> {

                    Log.d(TAG, "BONDED")
                }
                BluetoothDevice.BOND_BONDING -> {Log.d(TAG, "BONDING")}
                BluetoothDevice.BOND_NONE -> {Log.d(TAG, "NONE")}
            }
        }
    }
}

最佳答案

booleanint 添加到BluetoothDevice 模型以管理 View 。

例如,

BluetoothDevice:添加了 isOn 状态。 (抱歉,是 Java)

class BluetoothDevice {
    boolean isOn;

    public boolean isOn() {
        return isOn;
    }

    public void setOn(boolean isOn) {
        this.isOn = isOn;
    }
}

DeviceHolder:改变 View 的颜色

fun bindItems(btDevice: BluetoothDevice) {
   stateView.textColor = btDevice.isOn() ? Color.RED : Color.GREEN
}

DeviceAdapter:添加了getItems

fun getItems() {
   return mDevices
}

如果你想改变isOn状态,改变模型并通知它。

adapter.getItems().get(i).setOn(true);
adapter.notifyDataSetChanged();

关于android - 如何在 BroadcastReceiver.onReceive 中设置 RecyclerView.ViewHolder 的颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46781262/

相关文章:

java - Android - 其他应用窃取我的 Intent 接收器?

android - 无法使用 eclipse 导入 google_play_services

Android GridView 双指缩放

Android 蓝牙 RFCOMM 直接连接树莓派无需配对

java - AlarmManager 膨胀布局

Android BroadcastReceiver,设备重启后自动运行服务

android - 如何从 Android 设备获取 apk 文件?

android - 将数据从一个 xamarin.android 应用程序发送到另一个 xamarin.forms 应用程序

linux - 创建虚拟蓝牙设备/服务并让执行计算机发现/使用它们

android - Android/iOS 上的蓝牙游戏