Kotlin开发类Tinder应用时Fragment中添加CardStackView出现空指针异常求助
解决CardStackView空指针异常(Attempt to invoke virtual method...)
嘿,我看到你在开发类Tinder应用时遇到了空指针问题,这个错误其实很常见,咱们一步步来解决它。
问题根源
你遇到的NullPointerException是因为在HomePageFragment的onCreateView方法里,直接使用了kotlin synthetic提供的stack_view引用,但这个引用此时还没有被初始化。因为你是手动inflate了布局文件到变量v中,而synthetic的view绑定是在fragment的root view被设置之后才完成的——也就是你return v之后。所以在return之前调用stack_view.layoutManager时,stack_view还是null,自然就崩溃了。
另外,你的HomeUserAdapter还有一个潜在的崩溃点:homeUserList初始是null,但getItemCount()直接返回homeUserList!!.size,这肯定会触发空指针;而且onBindViewHolder里每次都调用generateUser()生成新列表,会导致数据不一致。
解决方案
1. 修复Fragment中的CardStackView引用问题
把直接使用synthetic的stack_view改成从inflate的view中获取实例:
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val v = inflater.inflate(R.layout.fragment_home_page, container, false) layoutManager = CardStackLayoutManager(context,this).apply { setSwipeableMethod(SwipeableMethod.AutomaticAndManual) setOverlayInterpolator(LinearInterpolator()) } // 从inflate的view中获取CardStackView实例 val cardStackView = v.findViewById<com.yuyakaido.android.cardstackview.CardStackView>(R.id.stack_view) cardStackView.layoutManager = layoutManager cardStackView.adapter = adapter cardStackView.itemAnimator.apply { if(this is DefaultItemAnimator){ supportsChangeAnimations = false } } return v }
2. 修复Adapter的数据源问题
修改HomeUserAdapter,初始化数据源并正确使用它:
class HomeUserAdapter:RecyclerView.Adapter<HomeUserAdapter.HomeUserViewHolder>() { // 初始化列表,避免null值 private var homeUserList: List<HomeUserItem> = generateUser() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeUserViewHolder { val itemView = LayoutInflater.from(parent.context).inflate(R.layout.user_card,parent,false) return HomeUserViewHolder(itemView) } override fun onBindViewHolder(holder: HomeUserViewHolder, position: Int) { // 直接使用已初始化的列表,不要每次生成新数据 val currentItem = homeUserList[position] Picasso.get().load(currentItem.user_img).into(holder.user_img) holder.user_name.text = currentItem.user_name holder.medal_num.text = currentItem.medal_num holder.id_num.text = currentItem.userId holder.user_intro.text = currentItem.user_intro holder.user_give_num.text = currentItem.user_give_num holder.user_receive_num.text = currentItem.user_receive_num } private fun generateUser(): ArrayList<HomeUserItem> { val list = ArrayList<HomeUserItem>() list.add( HomeUserItem( "https://i.pinimg.com/236x/8c/64/03/8c6403cc892231f15a6845e00d7433a9.jpg", "Maria", "200", "510uu", "I am from USA ,I am an engineer ,I hope to make the world a better place", "500", "100") ) return list } override fun getItemCount(): Int { return homeUserList.size } class HomeUserViewHolder(itemView: View):RecyclerView.ViewHolder(itemView) { val user_img : ImageView = itemView.user_img val user_name : TextView = itemView.user_name val medal_num : TextView = itemView.medal_num val id_num : TextView = itemView.id_num val user_intro : TextView = itemView.user_intro val user_give_num : TextView = itemView.user_give_num val user_receive_num : TextView = itemView.user_receive_num } }
改动说明
- Fragment部分:通过
v.findViewById直接获取刚inflate出来的CardStackView,确保引用有效,避开了kotlin synthetic的初始化时机问题。 - Adapter部分:
- 初始化
homeUserList为generateUser()的返回值,避免null导致的崩溃; onBindViewHolder直接使用已有的列表,不再每次生成新数据,保证数据一致性。
- 初始化
这样修改后,你的空指针问题应该就能解决了,Adapter也不会再有潜在的崩溃风险。
内容的提问来源于stack exchange,提问作者Yellow Clock
相关产品推荐
相关产品推荐

