Android RecyclerView底部添加按钮后应用崩溃问题求助
问题:添加底部按钮后RecyclerView页面崩溃,提示adapter未初始化
核心错误信息
kotlin.UninitializedPropertyAccessException: lateinit property adapter has not been initialized
修改后的布局XML文件
<?xml version="1.0" encoding="utf-8"?> <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/list" android:name="com.talhakasikci.mylittlelibrary.view.MembersListFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" app:layoutManager="LinearLayoutManager" tools:context=".view.MembersListFragment" tools:listitem="@layout/fragment_members_list" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Add a new member" /> </LinearLayout> </androidx.core.widget.NestedScrollView>
完整错误日志
2025-02-05 03:44:31.152 24645-24645 AndroidRuntime com.talhakasikci.mylittlelibrary E FATAL EXCEPTION: main Process: com.talhakasikci.mylittlelibrary, PID: 24645 kotlin.UninitializedPropertyAccessException: lateinit property adapter has not been initialized at com.talhakasikci.mylittlelibrary.view.MembersListFragment.onViewCreated$lambda$0(MembersListFragment.kt:52) at com.talhakasikci.mylittlelibrary.view.MembersListFragment.$r8$lambda$sTuiqA9XHSIlUYSztqmtb3yO0Bs(Unknown Source:0) at com.talhakasikci.mylittlelibrary.view.MembersListFragment$$ExternalSyntheticLambda0.invoke(D8$$SyntheticClass:0) at com.talhakasikci.mylittlelibrary.view.MembersListFragment$sam$androidx_lifecycle_Observer$0.onChanged(Unknown Source:2) at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133) at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151) at androidx.lifecycle.LiveData.setValue(LiveData.java:309) at androidx.lifecycle.LiveData$1.run(LiveData.java:93) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) 2025-02-05 03:44:31.225 32339-32452 OneSearchS...stProvider com...le.android.apps.nexuslauncher E Failed to fetch suggestions from AppSearch, fallback to AGA java.util.concurrent.CompletionException: java.util.NoSuchElementException: No value present at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:308) at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:323) at java.util.concurrent.CompletableFuture$UniAccept.tryFire(CompletableFuture.java:684) at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:486) at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2138) at com.google.android.apps.nexuslauncher.allapps.H0.onResult(Unknown Source:59) at android.app.appsearch.SearchSessionUtil$1.lambda$onResult$0(SearchSessionUtil.java:129) at android.app.appsearch.SearchSessionUtil$1.$r8$lambda$_nlk9WiPjSfaAsqKYmp0aPvSRC0(SearchSessionUtil.java:1) at android.app.appsearch.SearchSessionUtil$1$$ExternalSyntheticLambda0.run(R8$$SyntheticClass:13) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.os.HandlerThread.run(HandlerThread.java:67) Caused by: java.util.NoSuchElementException: No value present at java.util.Optional.get(Optional.java:144) at com.google.android.apps.nexuslauncher.allapps.H0.onResult(Unknown Source:16) at android.app.appsearch.SearchSessionUtil$1.lambda$onResult$0(SearchSessionUtil.java:129) at android.app.appsearch.SearchSessionUtil$1.$r8$lambda$_nlk9WiPjSfaAsqKYmp0aPvSRC0(SearchSessionUtil.java:1) at android.app.appsearch.SearchSessionUtil$1$$ExternalSyntheticLambda0.run(R8$$SyntheticClass:13) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.os.HandlerThread.run(HandlerThread.java:67)
原Fragment代码
package com.talhakasikci.mylittlelibrary.view import android.os.Bundle import androidx.fragment.app.Fragment import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.lifecycle.ViewModelProvider import com.talhakasikci.mylittlelibrary.R import com.talhakasikci.mylittlelibrary.adapter.MyMembersRecyclerViewAdapter import com.talhakasikci.mylittlelibrary.databinding.FragmentMembersListBinding import com.talhakasikci.mylittlelibrary.view.placeholder.PlaceholderContent import com.talhakasikci.mylittlelibrary.viewModel.MembersViewModel class MembersListFragment : Fragment() { private lateinit var viewModel: MembersViewModel private lateinit var adapter: MyMembersRecyclerViewAdapter private lateinit var binding:FragmentMembersListBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentMembersListBinding.inflate(inflater,container,false) val view = inflater.inflate(R.layout.fragment_members_list_list, container, false) if (view is RecyclerView) { view.layoutManager = LinearLayoutManager(context) adapter = MyMembersRecyclerViewAdapter(emptyList()) view.adapter = adapter } return view } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProvider(this).get(MembersViewModel::class.java) viewModel.allMembers.observe(viewLifecycleOwner) { members -> adapter.updateData(members) } binding.DeleteIcon.setOnClickListener { } } }
Adapter代码
package com.talhakasikci.mylittlelibrary.adapter import androidx.recyclerview.widget.RecyclerView import android.view.LayoutInflater import android.view.ViewGroup import android.widget.TextView import com.talhakasikci.mylittlelibrary.view.placeholder.PlaceholderContent.PlaceholderItem import com.talhakasikci.mylittlelibrary.databinding.FragmentMembersListBinding import com.talhakasikci.mylittlelibrary.model.Members class MyMembersRecyclerViewAdapter( private var members: List<Members> ) : RecyclerView.Adapter<MyMembersRecyclerViewAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( FragmentMembersListBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val member = members[position] holder.idView.text = member.id.toString() holder.NameView.text = member.First_Name holder.SurnameView.text = member.Last_Name holder.MemberID.text = member.MemberID.toString() } override fun getItemCount(): Int = members.size fun updateData(newMembers: List<Members>) { members = newMembers notifyDataSetChanged() } inner class ViewHolder(binding: FragmentMembersListBinding) : RecyclerView.ViewHolder(binding.root) { val idView: TextView = binding.itemNumber val NameView: TextView = binding.Name val SurnameView: TextView = binding.Surname val MemberID: TextView = binding.MemberID } }
ViewModel代码
package com.talhakasikci.mylittlelibrary.viewModel import android.app.Application import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.viewModelScope import com.talhakasikci.mylittlelibrary.model.Members import com.talhakasikci.mylittlelibrary.roomdb.BooksDB import com.talhakasikci.mylittlelibrary.roomdb.MembersDao import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class MembersViewModel(application: Application) : AndroidViewModel(application) { private val membersDao: MembersDao = BooksDB.getDatabase(application).MembersDao() val allMembers: LiveData<List<Members>> = membersDao.getAll() fun insert(member: Members) { viewModelScope.launch(Dispatchers.IO) { membersDao.MemberInsert(member) } } fun delete(member: Members) { viewModelScope.launch(Dispatchers.IO) { membersDao.MemberDelete(member) } } }
问题分析
修改布局后,页面根布局变为NestedScrollView,不再是原来的RecyclerView。原Fragment的onCreateView方法中,仅当view是RecyclerView时才会初始化adapter,现在该条件不成立,导致adapter始终未初始化。当onViewCreated中LiveData回调触发时,调用adapter.updateData()就会抛出未初始化异常。
另外,原代码中初始化了binding但未使用,反而重复通过inflater加载布局,属于冗余代码。
修复方案
1. 修正Fragment的布局加载与Adapter初始化
修改onCreateView方法,利用ViewBinding获取RecyclerView并初始化adapter,移除冗余的布局加载代码:
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentMembersListBinding.inflate(inflater, container, false) // 通过binding获取RecyclerView并初始化 val recyclerView = binding.list recyclerView.layoutManager = LinearLayoutManager(context) adapter = MyMembersRecyclerViewAdapter(emptyList()) recyclerView.adapter = adapter return binding.root }
2. 优化RecyclerView布局高度
原布局中RecyclerView的layout_height设为match_parent,在NestedScrollView中会导致RecyclerView占满所有剩余空间,底部按钮可能被遮挡。建议改为wrap_content:
<androidx.recyclerview.widget.RecyclerView ... android:layout_height="wrap_content" ... />
3. 可选:添加按钮点击事件
若需实现添加用户功能,给按钮设置id并添加点击事件:
<!-- 给按钮添加id --> <Button android:id="@+id/addMemberButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Add a new member" />
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProvider(this).get(MembersViewModel::class.java) viewModel.allMembers.observe(viewLifecycleOwner) { members -> adapter.updateData(members) } // 添加按钮点击逻辑 binding.addMemberButton.setOnClickListener { // 此处可跳转到添加用户页面或弹出添加对话框 Toast.makeText(context, "准备添加新用户", Toast.LENGTH_SHORT).show() } }
内容的提问来源于stack exchange,提问作者talha kaşıkci
相关产品推荐
相关产品推荐

