Kotlin中RecyclerView的Adapter未被调用问题求助
开发Android应用时遇到问题:ShoppingListActivity布局仅包含ShoppingListFragment,该Fragment接收listId参数,需展示对应ID的购物列表名称及商品RecyclerView。目前列表名称显示正常,但RecyclerView始终无内容。
调试确认:传入Adapter的listItems不为空,Adapter实例已创建,但onCreateViewHolder、getItemCount、onBindViewHolder从未被调用。
相关代码
ShoppingListActivity代码
class ShoppingListActivity : AppCompatActivity() { private var _binding: ActivityShoppingListBinding? = null private val binding get() = _binding!! private lateinit var shoppingListViewModel: ShoppingListViewModel private lateinit var shoppingListNameTextView: TextView private lateinit var recyclerView: RecyclerView private lateinit var shoppingList: ShoppingList override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_shopping_list) val listId = intent.getIntExtra("ShoppingListId", 0) if (savedInstanceState == null) { supportFragmentManager.commit { add(R.id.shopping_list_fragment, ShoppingListFragment(listId)) setReorderingAllowed(true) } } } }
ShoppingListActivity布局文件
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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/activity_shopping_list" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Activities.ShoppingListActivity"> <androidx.fragment.app.FragmentContainerView android:id="@+id/shopping_list_fragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
ShoppingListFragment代码
class ShoppingListFragment(private val listId: Int) : Fragment() { private var _binding: FragmentShoppingListBinding? = null private val binding get() = _binding!! private lateinit var shoppingListViewModel: ShoppingListViewModel private lateinit var shoppingListNameTextView: TextView private lateinit var recyclerView: RecyclerView private lateinit var shoppingList: ShoppingList override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_shopping_list, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) _binding = FragmentShoppingListBinding.bind(view) recyclerView = binding.shoppingListRecyclerView val context = requireContext() val shoppingListViewModelFactory = ShoppingListViewModelFactory(context) shoppingListViewModel = ViewModelProvider(this, shoppingListViewModelFactory)[ShoppingListViewModel::class.java] shoppingListNameTextView = binding.shoppingListName shoppingList = shoppingListViewModel.getListById(listId) shoppingListNameTextView.text = shoppingList.Name val itemsInList = shoppingListViewModel.getItemsInShoppingList(shoppingList) val adapter = SingleShoppingListAdapter(itemsInList) recyclerView.adapter = adapter } }
ShoppingListFragment布局文件
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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/shopping_list_fragment" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".UI.Fragments.ShoppingListFragment"> <TextView android:id="@+id/shopping_list_name" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginStart="52dp" android:layout_marginTop="44dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/shopping_list_recycler_view" android:layout_width="50dp" android:layout_height="150dp" android:layout_marginTop="60dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/shopping_list_name" app:layout_constraintVertical_bias="0.0" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/add_item_to_shopping_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="60dp" android:layout_marginBottom="76dp" android:clickable="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@android:drawable/ic_menu_add" /> </androidx.constraintlayout.widget.ConstraintLayout>
列表项布局文件recycler_view_shopping_list_item_element.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView 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:layout_width="match_parent" android:layout_height="match_parent"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="10dp" android:layout_height="match_parent"> <TextView android:id="@+id/shopping_list_item_name" android:layout_width="match_parent" android:layout_height="wrap_content" tools:layout_editor_absoluteX="-16dp" app:layout_constraintTop_toTopOf="parent" tools:layout_editor_absoluteY="1dp" /> <TextView android:id="@+id/shopping_list_item_quantity" android:layout_width="10dp" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/shopping_list_item_name" tools:layout_editor_absoluteX="0dp" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView>
SingleShoppingListAdapter代码
class SingleShoppingListAdapter(private val listItems: ArrayList<ShoppingListItem>) : RecyclerView.Adapter<SingleShoppingListAdapter.SingleShoppingListViewHolder>() { inner class SingleShoppingListViewHolder(view: View) : RecyclerView.ViewHolder(view) { private val name: TextView = view.findViewById(R.id.shopping_list_item_name) private val quantity: TextView = view.findViewById(R.id.shopping_list_item_quantity) fun bind(item: ShoppingListItem) { name.text = item.Name quantity.text = item.Quantity.toString() } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SingleShoppingListViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_view_shopping_list_item_element, parent, false) return SingleShoppingListViewHolder(view) } override fun getItemCount(): Int { return listItems.size } override fun onBindViewHolder(holder: SingleShoppingListViewHolder, position: Int) { holder.bind(listItems[position]) } }
问题根源与解决方案
1. 核心问题:RecyclerView未设置LayoutManager
RecyclerView必须指定LayoutManager才能计算子项布局、触发Adapter的生命周期方法。你的代码仅设置了Adapter,未配置LayoutManager,导致Adapter方法完全不执行。
修复代码(在Fragment的onViewCreated中,设置Adapter前添加):
// 线性布局管理器,可根据需求换成GridLayoutManager等 recyclerView.layoutManager = LinearLayoutManager(requireContext())
2. 布局参数错误:RecyclerView宽度过窄
Fragment布局中RecyclerView的android:layout_width="50dp",宽度仅50dp,即使显示内容也几乎不可见。同时固定高度150dp会限制显示范围,应改为自适应剩余空间。
修复后的RecyclerView布局代码:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/shopping_list_recycler_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="60dp" app:layout_constraintBottom_toTopOf="@+id/add_item_to_shopping_list" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/shopping_list_name" />
3. 列表项布局宽度异常
列表项的根ConstraintLayout设置android:layout_width="10dp",导致内部TextView无法正常显示内容。同时CardView高度设为match_parent会让每个子项占满RecyclerView高度,需改为wrap_content。
修复后的列表项布局代码:
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp"> <TextView android:id="@+id/shopping_list_item_name" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toStartOf="@+id/shopping_list_item_quantity" android:layout_marginEnd="8dp"/> <TextView android:id="@+id/shopping_list_item_quantity" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView>
4. 优化ViewBinding使用(可选)
Fragment中ViewBinding的使用方式可以更规范,避免重复绑定:
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentShoppingListBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) recyclerView = binding.shoppingListRecyclerView // 后续直接使用binding对象即可,无需再次bind } override fun onDestroyView() { super.onDestroyView() _binding = null // 销毁视图时置空binding,避免内存泄漏 }
内容的提问来源于stack exchange,提问作者borjanob

