首页 > 解决方案 > RecyclerView 除非收到通知,否则不会将数据绑定到 ViewHolder

问题描述

我正在尝试实现RecyclerViewwith 数据绑定。

RecyclerView我用来findViewById检索小部件时,它工作正常。但是,如果我使用RecyclerView数据绑定,则数据不会绑定到ViewHolder.

MainActivity.kt

package com.example.wifilogger

import android.os.Bundle
import android.os.Handler
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.wifilogger.databinding.ActivityMainBinding
import com.example.wifilogger.helper.WiFi
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private var wifiList = ArrayList<WiFi>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityMainBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_main)

        binding.loading = true

        wifiList.add(WiFi("38:BC:01:64:2D:38", "Example", -87, "WPA2"))

        recycler_view.apply {

            layoutManager = LinearLayoutManager(context)

            adapter = WiFiAdapter(wifiList)
        }

        Handler().postDelayed({
            recycler_view.adapter?.notifyDataSetChanged()
        }, 1000)
    }
}

WiFi.kt

data class WiFi(var BSSID: String, var SSID: String, var level: Int, var encryption: String)

WiFi适配器

package com.example.wifilogger

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import com.example.wifilogger.databinding.ListItemBinding
import com.example.wifilogger.helper.WiFi


class WiFiAdapter(_wifiList: ArrayList<WiFi>) :
    androidx.recyclerview.widget.RecyclerView.Adapter<WiFiAdapter.ViewHolder>() {
    private val wifiList = _wifiList

    class ViewHolder(_binding: ListItemBinding) : androidx.recyclerview.widget.RecyclerView.ViewHolder(_binding.root) {
        var binding: ListItemBinding = _binding
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding: ListItemBinding = DataBindingUtil.inflate(
            LayoutInflater.from(parent.context),
            R.layout.list_item, parent, false
        )

        return ViewHolder(binding)
    }

    override fun getItemCount() = wifiList.size

    override fun onBindViewHolder(holder: ViewHolder, pos: Int) {
        holder.binding.ssid.text = wifiList[pos].SSID
        holder.binding.bssid.text = wifiList[pos].BSSID
        holder.binding.level.text = wifiList[pos].level.toString()
        holder.binding.encryption.text = wifiList[pos].encryption
    }
}

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tool="http://schemas.android.com/tools">

    <data>
        <variable
            name="ssid"
            type="String" />
        <variable
            name="bssid"
            type="String" />
        <variable
            name="level"
            type="int" />
        <variable
            name="encryption"
            type="String" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingBottom="8dp"
        android:paddingEnd="16dp"
        android:paddingStart="16dp"
        android:paddingTop="8dp">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/ssid"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingBottom="8dp"
                android:textColor="@color/md_grey_900"
                android:text="@{ssid}"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tool:hint="SSID: Mum Use This One" />

            <TextView
                android:id="@+id/bssid"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/md_grey_600"
                android:text="@{bssid}"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/ssid"
                tool:hint="BSSID: 4A-C0-D0-07-91-E5" />

            <TextView
                android:id="@+id/level"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingBottom="8dp"
                android:textColor="@color/md_grey_600"
                android:text='@{level + "dBm"}'
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tool:hint="-68 dBm" />

            <TextView
                android:id="@+id/encryption"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/md_grey_600"
                android:text="@{encryption}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/level"
                tool:hint="WPA2" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </LinearLayout>
</layout>

notifyDataSetChanged()如果我稍微延迟 调用,该代码就可以工作。截屏

但是,如果我删除该行,则数据不会绑定到 list_item。 截屏

我认为将数据绑定到时正在运行一些异步任务ViewHolder,但我不知道在哪里。

任何帮助,将不胜感激。谢谢你。

标签: androidkotlinandroid-recyclerviewandroid-databinding

解决方案


尝试

class WiFiAdapter(_wifiList: ArrayList<WiFi>) :
    androidx.recyclerview.widget.RecyclerView.Adapter<WiFiAdapter.ViewHolder>() {

    ...

    override fun onBindViewHolder(holder: ViewHolder, pos: Int) {

        ...

        holder.binding.executePendingBindings()
    }
}

推荐阅读