I have a BluetoothService Class which offers BLE Services like scanning and holding a MutableList of known devices. When scanning it adds new devices to the list and posts them with the postValue() function to notify about the change.
My goal is to bring this data to the frontend and listing the found devices. I tried following the android widgets-sample and almost have the same code as there except for replacing the ViewModelFactory as its deprecated. I checked my MutableLiveData List in the debugger and they are in fact up to date. I suspect the observer not being registered correctly, as it fires.
My Recycler View looks like this:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listFoundDevices"
android:layout_width="347dp"
android:layout_height="352dp"
android:layout_marginTop="28dp"
android:background="#CD3131"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/recycler_view_item" />
recycler_view_item:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="66dp"
android:layout_marginTop="3dp"
android:textColor="@android:color/black"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
MainActivity shortened:
private val mainActivityViewModel by viewModels<MainActivityViewModel>()
private val bluetoothService = BluetoothService()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val peripheralAdapter = PeripheralAdapter {peripheral -> adapterOnClick(peripheral)}
val recyclerView: RecyclerView = findViewById(R.id.listFoundDevices)
recyclerView.adapter = peripheralAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
setSupportActionBar(binding.toolbar)
mainActivityViewModel.scanLiveData.observe(this) {
it?.let {
//Never fires the message despite updating the liveData with postValue()
println("Got an Update!")
peripheralAdapter.submitList(it as MutableList<MyPeripheral>)
}
}
}
private fun adapterOnClick(peripheral: MyPeripheral){
print("clicked on item")
}
ViewModel:
class MainActivityViewModel (private var bluetoothService: BluetoothService): ViewModel() {
private val repository by lazy { bluetoothService.scanLiveData }
val scanLiveData = MutableLiveData(repository.value)
}
PeripheralAdapter:
class PeripheralAdapter(private val onClick: (MyPeripheral) -> Unit) :
ListAdapter<MyPeripheral, PeripheralAdapter.PeripheralViewHolder>(PeripheralDiffCallback) {
class PeripheralViewHolder(itemView: View, val onClick: (MyPeripheral) -> Unit) :
RecyclerView.ViewHolder(itemView) {
private val peripheralTextView: TextView = itemView.findViewById(R.id.textView)
private var currentPeripheral: MyPeripheral? = null
init {
itemView.setOnClickListener {
currentPeripheral?.let {
onClick(it)
}
}
}
fun bind(peripheral: MyPeripheral) {
currentPeripheral = peripheral
peripheralTextView.text = peripheral.name
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PeripheralViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.recycler_view_item, parent, false)
return PeripheralViewHolder(view, onClick)
}
override fun onBindViewHolder(holder: PeripheralViewHolder, position: Int) {
val peripheral = getItem(position)
holder.bind(peripheral)
}
}
BluetoothService:
var knownPeripherals = ArrayList<MyPeripheral>()
var scanLiveData = MutableLiveData(knownPeripherals)
fun handleDevice(result: ScanResult, data: ByteArray?) {
val peripheral = knownPeripherals.find { it.serialNumberAdv == foundSN }
if (peripheral == null){
knownPeripherals.add(MyPeripheral(this, result))
updateMutableData()
}
}
private fun updateMutableData(){
scanLiveData.postValue(knownPeripherals)
}
A hint why it's not working out would be appreciated.