Считывайте значения ble и обновляйте список livedata/recyclerview

#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. Да, значение длительности в каждой характеристике