#android #kotlin #android-recyclerview #bluetooth-lowenergy #android-livedata
Вопрос:
У меня есть приложение для Android, которое считывает значения Bluetooth с устройства. Я представляю эти значения в представлении для повторного использования. Я хотел бы найти способ обновить этот список, и я чувствую себя немного потерянным, так как я пробовал разные решения, которые я нашел в Google.
Я действительно не знаю, в чем проблема-в моем просмотре вторсырья или в том, что мой наблюдатель за живыми данными не запускается. Когда я снова пытаюсь прочитать значения, список исчезает, но в своих журналах я вижу, что из модели представления появляется новый список значений
Приложение работает так, как я и предполагал в первой итерации.
Я могу предоставить больше кода, если это необходимо
Поделитесь некоторым кодом для дополнительной ясности
Здесь я читаю значения, в которых я повторно создаю ByteArray.
ReadLineNodeValues().iRObjectTemperature -> {
bleListViewModel.addBleToList(characteristic.value)
}
Который я отправляю своей модели просмотра здесь
class BleValueViewModel: ViewModel() {
fun addBleToList(bleValue: ByteArray) {
blueToothLEvalue.add(bleValue)
mutableLiveDataBluetooth.postValue(blueToothLEvalue)
}
fun getList(): MutableLiveData<ArrayList<ByteArray>> {
return mutableLiveDataBluetooth
}
Здесь я пытаюсь повторно просмотреть список, в котором я добавляю его в свой recyclverView
private fun showItems() {
val bleValueViewModel = ViewModelProvider(requireActivity()).get(BleValueViewModel::class.java)
bleValueViewModel.getList().observe(viewLifecycleOwner) {
if (it.size == 26) {
showlist(it)
}
}
}
RecyclerView
class LineNodeValueDataAdapter :
RecyclerView.Adapter<LineNodeBigViewHolder>() {
private val differCallback = object : DiffUtil.ItemCallback<LinenNodeValueData>() {
override fun areItemsTheSame(
oldItem: LinenNodeValueData,
newItem: LinenNodeValueData
): Boolean {
return oldItem.valueOne == newItem.valueOne amp;amp; oldItem.valueTwo == newItem.valueTwo amp;amp; oldItem.valueThree == newItem.valueThree amp;amp; oldItem.valueFour == newItem.valueFour
}
override fun areContentsTheSame(
oldItem: LinenNodeValueData,
newItem: LinenNodeValueData
): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, differCallback)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LineNodeBigViewHolder {
val binding = CardviewListlayoutValueBinding
.inflate(LayoutInflater.from(parent.context), parent, false)
return LineNodeBigViewHolder(binding)
}
override fun onBindViewHolder(holder: LineNodeBigViewHolder, position: Int) {
val place = differ.currentList[position]
holder.bind(place)
}
override fun getItemCount(): Int = differ.currentList.size
}
Я конвертирую значения, так как все они приходят в виде байтов
fun showlist(listValues: MutableList<ByteArray>) {
//Systemnode
val systemNodeMCUTemp = String(listValues[0])
val systemNodeVoltages = String(listValues[1])
val systemNodeWeatherSensor = String(listValues[2])
val systemNodeOpenThreadCfg = String(listValues[3])
//Linenode
val currentLineNode = String(listValues[4])
val acceleroMeterX = ByteBuffer.wrap(listValues[5]).order(ByteOrder.LITTLE_ENDIAN).float
val acceleroMeterY = ByteBuffer.wrap(listValues[6]).order(ByteOrder.LITTLE_ENDIAN).float
val acceleroMeterZ = ByteBuffer.wrap(listValues[7]).order(ByteOrder.LITTLE_ENDIAN).float
val iRObjectTemperature =
ByteBuffer.wrap(listValues[8]).order(ByteOrder.LITTLE_ENDIAN).float
val contactSensorTemperature =
ByteBuffer.wrap(listValues[9]).order(ByteOrder.LITTLE_ENDIAN).float
val magneticField = ByteBuffer.wrap(listValues[10]).order(ByteOrder.LITTLE_ENDIAN).float
val internalVoltage1V8 =
ByteBuffer.wrap(listValues[11]).order(ByteOrder.LITTLE_ENDIAN).float
val internalVoltagevBusRail =
ByteBuffer.wrap(listValues[12]).order(ByteOrder.LITTLE_ENDIAN).float
val internalVoltageVDD =
ByteBuffer.wrap(listValues[13]).order(ByteOrder.LITTLE_ENDIAN).float
val internalVoltageVDDH =
ByteBuffer.wrap(listValues[14]).order(ByteOrder.LITTLE_ENDIAN).float
val powerHarvestingVoltageSol1 =
ByteBuffer.wrap(listValues[15]).order(ByteOrder.LITTLE_ENDIAN).float
val powerHarvestingVoltageSol2 =
ByteBuffer.wrap(listValues[16]).order(ByteOrder.LITTLE_ENDIAN).float
val powerHarvestingVoltageEmppt =
ByteBuffer.wrap(listValues[17]).order(ByteOrder.LITTLE_ENDIAN).float
val powerHarvestingVoltageHmppt =
ByteBuffer.wrap(listValues[18]).order(ByteOrder.LITTLE_ENDIAN).float
val eHFieldHField =
ByteBuffer.wrap(listValues[19]).order(ByteOrder.LITTLE_ENDIAN).float
val eHFieldEField =
ByteBuffer.wrap(listValues[20]).order(ByteOrder.LITTLE_ENDIAN).float
val ambientTemperaturesAcc =
ByteBuffer.wrap(listValues[21]).order(ByteOrder.LITTLE_ENDIAN).float
val ambientTemperaturesIR =
ByteBuffer.wrap(listValues[22]).order(ByteOrder.LITTLE_ENDIAN).float
val ambientTemperaturesMag =
ByteBuffer.wrap(listValues[23]).order(ByteOrder.LITTLE_ENDIAN).float
val ambientTemperaturesMCU =
ByteBuffer.wrap(listValues[24]).order(ByteOrder.LITTLE_ENDIAN).float
val openThreadCFG =
ByteBuffer.wrap(listValues[25]).order(ByteOrder.LITTLE_ENDIAN).float
val systemNodeList = ArrayList<SystemValue>()
systemNodeList.add(SystemValue("Systemode MguTemp", systemNodeMCUTemp))
systemNodeList.add(SystemValue("Systemnode Voltages", systemNodeVoltages))
systemNodeList.add(SystemValue("Systemnode WeatherSensor", systemNodeWeatherSensor))
systemNodeList.add(SystemValue("Systemnode OpenThreadCfg", systemNodeOpenThreadCfg))
val lineNodevaluelist = ArrayList<LinenNodeValueData>()
val lineNodeListBle = ArrayList<SystemValue>()
lineNodeListBle.add(SystemValue("LineNode Service", currentLineNode))
lineNodeListBle.add(SystemValue("Current LineNode", acceleroMeterX.toString()))
//lineNodeListBle.add(SystemValue("Acclero meter", lineNodeValueSeven.toString()))
Timber.i("Acclerometer2 :: ${acceleroMeterY}}")
lineNodeListBle.add(
SystemValue(
"Accelero Meter",
"X: $acceleroMeterX " "Y: $acceleroMeterY"
" Z: $acceleroMeterZ"
)
)
lineNodeListBle.add(
SystemValue(
"iRObject Temperature",
iRObjectTemperature.toString()
)
)
lineNodeListBle.add(
SystemValue(
"ContactSensor Temperature",
contactSensorTemperature.toString()
)
)
lineNodeListBle.add(SystemValue("Magnetic Field", magneticField.toString()))
lineNodevaluelist.add(
LinenNodeValueData(
"Internal Voltage",
"1V8: $internalVoltage1V8",
"Vbus rail: $internalVoltagevBusRail",
"VDD: $internalVoltageVDD",
"VDDH: $internalVoltageVDDH"
)
)
lineNodevaluelist.add(
LinenNodeValueData(
"Power Harvesting Voltage",
"Sol1: $powerHarvestingVoltageSol1",
"Sol2: $powerHarvestingVoltageSol2",
"E-Mppt: $powerHarvestingVoltageEmppt", "H-Mppt: $powerHarvestingVoltageHmppt"
)
)
lineNodeListBle.add(
SystemValue(
"eHField",
"H-field: $eHFieldHField E-field: $eHFieldEField"
)
)
lineNodevaluelist.add(
LinenNodeValueData(
"Ambient Temperatures",
"Acc: $ambientTemperaturesAcc",
"IR: $ambientTemperaturesIR",
"Mag: $ambientTemperaturesMag",
"Mcu: $ambientTemperaturesMCU"
)
)
lineNodeListBle.add(SystemValue("openThreadCFG", openThreadCFG.toString()))
setupRecyclerViewSystemNode(binding.systemNodeRecyclerView, systemNodeList)
Timber.i("blueviewRecycler :: ${systemNodeList.size}")
setupRecylerViewLineNodeOne(binding.lineNodeRecyclerView, lineNodeListBle, lineNodevaluelist)
Timber.i("blueviewRecycler1 :: ${lineNodeListBle.size} ${lineNodevaluelist.size}")
}
Всем хорошего дня
С уважением
Дроид
Комментарии:
1. Вы всегда можете передать свой объект данных в режиме реального времени в recyclerview.
2. Спасибо за ваш ответ @KristyWelsh, я разберусь с этим
Ответ №1:
Здесь у вас есть условие.
if (it.size == 26) {
showlist(it)
}
Если вы добавляете новые значения в список, list.size изменяется, а условие равно false. Итак, просто удалите условие:
bleValueViewModel.getList().observe(viewLifecycleOwner) {
showlist(it)
}
кроме того, я надеюсь, что вы позвоните showItems
только один раз.
Что касается вашей реализации diff utils, из документа:
areContentsTheSame(int oldItemPosition, int newItemPosition)
Вызывается DiffUtil, когда он хочет проверить, имеют ли два элемента
одинаковые данные.
areItemsTheSame(int oldItemPosition, int newItemPosition)
Вызывается DiffUtil, чтобы решить, представляют ли два объекта один и тот же
элемент.
Кроме того, похоже, что вам следует переопределить обратный вызов DIfUtils:
private val differCallback = object : DiffUtil.ItemCallback<LinenNodeValueData>() {
override fun areItemsTheSame(
oldItem: LinenNodeValueData,
newItem: LinenNodeValueData
): Boolean {
return //return true if i's the same item. I suppose in your case you should check that it's the same ble characteristic.
}
override fun areContentsTheSame(
oldItem: LinenNodeValueData,
newItem: LinenNodeValueData
): Boolean {
return // return true if it has the same content. If you return true it means that content(values) for the object has not change. In other case if values are different, you should return false, it means that values for characteristic changed and recyclerView should update respective view.
}
}
Комментарии:
1. Спасибо за ваш ответ @AnatoliiChub, Да, я удалил это условие сейчас. Но я заметил кое-что еще. Похоже, что мой список просто добавляет новые элементы в список в моей модели представления и не обновляет текущие значения, которые есть в списке. Есть ли способ просто заменить эти старые значения чтения новыми значениями чтения?
2. Хорошо, я не могу найти место, где вы устанавливаете список объектов для адаптера. Но, пожалуйста, убедитесь, что список элементов, которые вы устанавливаете на адаптер, содержит только новые элементы.
3. Конечно, я отредактировал сообщение, поэтому то, что я пытаюсь сделать в showlist, — это преобразовать каждый объект ByteArray в строку/float. @AnatoliiChub
4. Так что, как я могу понять, вы получаете новые значения характеристик ble. И вам нужно показывать только последнее значение для каждой характеристики, верно?
5. Да, значение длительности в каждой характеристике