cómo establecer el color de RecyclerView.ViewHolder en BroadcastReceiver.onReceive?

Estoy creando una aplicación que escanea y se empareja con dispositivos Bluetooth. Estoy mostrando los dispositivos en un RecyclerView e indicando el estado del enlace coloreando el ViewHolder para ese dispositivo. Mi problema es que el color del ViewHolder solo se cambia después de escanear para dispositivos otra vez y quiero que actualice inmediatamente el color en el par o desvinculación. Estoy intentando hacer esto mediante el uso de un receptor de transmisión, pero no puedo get una reference al ViewHolder correcto. ¿Cómo puedo conseguir esto? Estoy incluyendo mi código a continuación para mi RecyclerView.Adapter y mi file BluetoothUtils que contiene el receptor de difusión. gracias por adelantado. mi adaptador:

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 -> {} } } } } } } } 

y mi 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")} } } } } 

Agregue boolean o int a BluetoothDevice model para administrar la vista.

Por ejemplo,

BluetoothDevice: se agregó el estado de isOn . (Lo siento, es Java)

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

DeviceHolder: cambió el color de la vista

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

DeviceAdapter: getItems agregados

 fun getItems() { return mDevices } 

Si desea cambiar el estado de isOn , cambie el model y notifíquelo.

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

También me gusta la respuesta anterior, pero la forma en que lo hice fue pasar el BroadcastReceiver al DeviceAdapter:

 class DeviceAdapter(val mContext:Context, val mReceiver:MainBTStatusReceiver) : RecyclerView.Adapter<DeviceAdapter.DeviceHolder>() 

y luego hizo un ViewHolder miembro de BroadcastReceiver y una function setter para ViewHolder llamada setFocus. antes de llamar a cualquier function de la class BluetoothUtils llamé a la function setFocus y luego el receptor de difusión modifica el color de la vista que el foco está actualmente configurado también. Me preocupa que esto no sea confiable ya que es el método más preciso para modificar el ViewHolder correcto todo el time. si ve algún problema con esto, por favor coméntemelo para avisarme.

mi BroadcastReceiver actualizado:

 class MainBTStatusReceiver(): BroadcastReceiver() { val TAG = "MainBTStatusReceiver" var holder: DeviceAdapter.DeviceHolder? = null fun setFocus(holder: DeviceAdapter.DeviceHolder) { this.holder = holder } override fun onReceive(context: Context?, intent: Intent) { val action = intent.action when (action) { BluetoothDevice.ACTION_BOND_STATE_CHANGED -> { val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) when (device.bondState) { BluetoothDevice.BOND_BONDED -> { holder!!.itemView.setBackgroundColor(Color.CYAN) Log.d(TAG, "BONDED") } BluetoothDevice.BOND_BONDING -> { Log.d(TAG, "BONDING") } BluetoothDevice.BOND_NONE -> { holder!!.itemView.setBackgroundColor(Color.TRANSPARENT) Log.d(TAG, "NONE") } } } } } } 

y las dos declaraciones en mi expresión when que llaman a setFocus ():

  R.id.pairOp -> { Log.d(TAG, "pairOp reached") mReceiver.setFocus(this@DeviceHolder) BluetoothUtils.startPair(BluetoothAdapter.getDefaultAdapter(), btDevice) Log.d(TAG, "start pair complete") dialog!!.dismiss() } R.id.unPairOp -> { Log.d(TAG, "unPairOp reached") mReceiver.setFocus(this@DeviceHolder) BluetoothUtils.unPair(btDevice) Log.d(TAG, "unpair complete") dialog!!.dismiss() }