求助:kotlin.UninitializedPropertyAccessException错误排查(适配器第69行)
Kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized in RecyclerView Adapter
我是Android开发新手,开发的com.example.kotlincountries应用抛出kotlin.UninitializedPropertyAccessException,提示lateinit property binding has not been initialized,错误位于CountryAdapter.kt第69行,尝试多种方案仍无法解决,特求助。
错误日志
AndroidRuntime: FATAL EXCEPTION: main Process: com.example.kotlincountries, PID: 15240 kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized at com.example.kotlincountries.adapter.CountryAdapter.onCountryClicked(CountryAdapter.kt:69) at com.example.kotlincountries.databinding.ItemCountryBindingImpl$OnClickListenerImpl.onClick(ItemCountryBindingImpl.java:173) at android.view.View.performClick(View.java:7506) at android.view.View.performClickInternal(View.java:7483) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:29334) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
已配置与检查内容
Gradle配置
buildFeatures { viewBinding = true dataBinding = true }
Item布局XML
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="country" type="com.example.kotlincountries.model.Country" /> <variable name="listener" type="com.example.kotlincountries.adapter.CountryClickListener" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="150dp" android:onClick="@{listener::onCountryClicked}" android:orientation="horizontal"> <TextView android:id="@+id/countryUuidText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:text="@{String.valueOf(country.uuid)}"> </TextView> <ImageView android:id="@+id/imageView" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:padding="3dp" android:downloadUrl="@{country.imageUrl}"> </ImageView> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_vertical" android:layout_weight="3"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{country.countryName}" android:padding="5dp" android:textSize="18sp" android:textStyle="bold"> </TextView> <TextView android:id="@+id/region" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{country.countryRegion}" android:textSize="16sp" android:padding="5dp"> </TextView> </LinearLayout> </LinearLayout> </layout>
适配器代码
class CountryAdapter(val countryList:ArrayList<Country>): RecyclerView.Adapter<CountryAdapter.CountryViewHolder>(),CountryClickListener { private lateinit var binding : ItemCountryBinding class CountryViewHolder(var view:ItemCountryBinding) :RecyclerView.ViewHolder(view.root) { } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CountryViewHolder { val inflater = LayoutInflater.from(parent.context) val binding = ItemCountryBinding.inflate(inflater, parent, false) return CountryViewHolder(binding) } override fun getItemCount(): Int { return countryList.size } override fun onBindViewHolder(holder: CountryViewHolder, position: Int) { holder.view.country=countryList[position] holder.view.listener=this } fun updateCountryList(newCountryList:List<Country>){ countryList.clear() countryList.addAll(newCountryList) notifyDataSetChanged() } override fun onCountryClicked(v: View) { val uuid=binding.countryUuidText.text.toString().toInt() val action=FeedFragmentDirections.actionFeedFragmentToCountryFragment(uuid) Navigation.findNavController(v).navigate(action) } }
问题原因与解决方案
问题根源
你在适配器类中声明的private lateinit var binding : ItemCountryBinding从未被初始化——每个RecyclerView的ViewHolder都有自己独立的Binding实例(在onCreateViewHolder中创建并传入ViewHolder),而适配器类级别的Binding变量根本没有赋值,所以点击事件中访问它时必然抛出未初始化异常。
解决方案
方案1:通过DataBinding直接传递UUID(推荐)
这种方式更简洁,不需要通过View查找控件:
- 修改XML布局中的点击事件,直接传递
country.uuid和点击的View:
android:onClick="@{(v) -> listener.onCountryClicked(v, country.uuid)}"
- 修改
CountryClickListener接口的方法定义:
interface CountryClickListener { fun onCountryClicked(v: View, uuid: Int) }
- 删除适配器类中的
private lateinit var binding : ItemCountryBinding变量,并修改onCountryClicked实现:
override fun onCountryClicked(v: View, uuid: Int) { val action=FeedFragmentDirections.actionFeedFragmentToCountryFragment(uuid) Navigation.findNavController(v).navigate(action) }
方案2:通过点击View查找目标控件
如果不想修改接口定义,可以直接从点击的View中找到countryUuidText:
- 删除适配器类中的
private lateinit var binding : ItemCountryBinding变量 - 修改
onCountryClicked方法:
override fun onCountryClicked(v: View) { val uuidText = v.findViewById<TextView>(R.id.countryUuidText) val uuid = uuidText.text.toString().toInt() val action=FeedFragmentDirections.actionFeedFragmentToCountryFragment(uuid) Navigation.findNavController(v).navigate(action) }
内容的提问来源于stack exchange,提问作者user16190280
相关产品推荐
相关产品推荐

