继承FirebaseRecyclerAdapter时报DataSnapshot无法转换为Posts类怎么解决
Android FirebaseRecyclerAdapter 类型转换异常问题
我在进行Android开发时,需要为RecyclerView创建适配器,因此继承FirebaseRecyclerAdapter类实现逻辑,但运行时抛出异常。我在网上找到的同类示例均采用该继承方式,不确定是自身代码存在问题还是该继承方式已不再支持,恳请各位帮忙排查解决,非常感谢。
适配器代码
public class PostAdapterTest extends FirebaseRecyclerAdapter <Posts, PostAdapterTest.postsViewHolder> { private BottomSheetDialog bottomSheetDialog; private Context mContext; private Boolean downloadOrOpen = false; private boolean buttonStatus = true; private DatabaseReference likesRef = FirebaseDatabase.getInstance().getReference("Likes"); private FirebaseUser mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser(); private String difficulty = null; private int likesCounter; private ReadWritePermissions mReadWritePermissions; public PostAdapterTest(@NonNull FirebaseRecyclerOptions<Posts> postsFirebaseRecyclerOptions, ReadWritePermissions mReadWritePermissions, Context mContext) { super(postsFirebaseRecyclerOptions); this.mContext = mContext; this.mReadWritePermissions = mReadWritePermissions; } @Override protected void onBindViewHolder(@NonNull PostAdapterTest.postsViewHolder holder, int position, @NonNull Posts model) { final String postKey = getRef(position).getKey(); String postUid = model.getPostId(); holder.nickname.setText(model.getNickname()); holder.country.setText(model.getCountry()); holder.title.setText(model.getCountry()); holder.days.setText(model.getDays()); holder.kilometers.setText(model.getKilometers()); holder.description.setText(model.getDescription()); difficulty = model.getDifficulty(); holder.map.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Uri mapUri = Uri.parse(model.getMap()); mapOptions(mapUri); } }); holder.comments.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CommentsFragment commentsFragment = new CommentsFragment(); Bundle args = new Bundle(); args.putString("postId", postUid); commentsFragment.setArguments(args); FragmentTransaction fragmentTransaction = ((FragmentActivity)mContext).getSupportFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.frame_container, commentsFragment); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); } }); holder.setLikeButtonStatus(postKey); holder.likes.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { buttonStatus = true; likesRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if(buttonStatus == true) { if(snapshot.child(postKey).hasChild(mFirebaseUser.getUid())) { likesRef.child(postKey).child(mFirebaseUser.getUid()).removeValue(); buttonStatus = false; }else { likesRef.child(postKey).child(mFirebaseUser.getUid()).setValue(true); buttonStatus = false; } } } @Override public void onCancelled(@NonNull DatabaseError error) { } }); switch (difficulty) { case "Easy": holder.difficulty.setImageResource(R.drawable.ic_easy); break; case "Difficult": holder.difficulty.setImageResource(R.drawable.ic_difficult); break; case "Hard": holder.difficulty.setImageResource(R.drawable.ic_hard); break; } ArrayList<Slider> sliderArrayList = new ArrayList<>(); Picasso.get().load(model.getAvatarUri()).into(holder.avatarUri); } }); } @NonNull @Override public PostAdapterTest.postsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.posts, parent, false); return new PostAdapterTest.postsViewHolder(view); } class postsViewHolder extends RecyclerView.ViewHolder { public CircleImageView avatarUri; public TextView nickname, country, title, days, likesNum, kilometers,description, fileSize, fileName; public SliderView mSliderView; public ImageView comments, save, difficulty; public ImageButton likes; public ImageButton more; public LinearLayout map; public postsViewHolder(@NonNull View itemView) { super(itemView); avatarUri = itemView.findViewById(R.id.posts_profile_picture); nickname = itemView.findViewById(R.id.posts_nickname); country = itemView.findViewById(R.id.posts_country); title = itemView.findViewById(R.id.posts_title); days = itemView.findViewById(R.id.posts_days); difficulty = itemView.findViewById(R.id.posts_difficulty); mSliderView = itemView.findViewById(R.id.posts_images); likes = itemView.findViewById(R.id.posts_likes); comments = itemView.findViewById(R.id.posts_comments); save = itemView.findViewById(R.id.posts_save); likesNum = itemView.findViewById(R.id.posts_likes_number); description = itemView.findViewById(R.id.posts_description); more = itemView.findViewById(R.id.posts_more); kilometers = itemView.findViewById(R.id.posts_distance); fileSize = itemView.findViewById(R.id.posts_uploaded_file_size); fileName = itemView.findViewById(R.id.posts_uploaded_file_name); map = itemView.findViewById(R.id.posts_map_layout); } public void setLikeButtonStatus(final String key) { mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser(); likesRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { likesCounter = (int)snapshot.child(key).getChildrenCount(); if(snapshot.child(key).hasChild(mFirebaseUser.getUid())) { likes.setImageResource(R.drawable.ic_liked_red); likesNum.setText(likesCounter + " Likes"); }else if(likesCounter == 0) { likes.setImageResource(R.drawable.ic_unliked_red); likesNum.setText(""); }else { likes.setImageResource(R.drawable.ic_unliked_red); likesNum.setText(likesCounter + " Likes"); } } @Override public void onCancelled(@NonNull DatabaseError error) { } }); } } private void mapOptions(Uri mapUri) { } }
Logcat错误信息
Process: com.company.android.myapplication, PID: 8349 java.lang.ClassCastException: com.google.firebase.database.DataSnapshot cannot be cast to com.company.android.myapplication.Posts at com.company.android.myapplication.test.PostAdapterTest.onBindViewHolder(PostAdapterTest.java:44) at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:149) at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7254) at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337) at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194) at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6296) at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2330) at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631) at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591) at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668) at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309) at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012) at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4578)
解决方案
该错误和FirebaseRecyclerAdapter的继承方式无关,核心原因是FirebaseUI无法将数据库返回的DataSnapshot转换成自定义的Posts类,按以下步骤排查即可:
- 检查Posts类的结构:必须包含公共无参构造方法,所有需要映射的字段要么是公共属性,要么有对应的get/set方法,字段名要和数据库中的字段名完全一致,大小写也不能错,如果字段名不匹配需要添加
@PropertyName注解显式指定对应的数据库字段名。 - 检查FirebaseRecyclerOptions的初始化代码:确认你设置的Query指向的数据库节点下,每个子节点的结构都和Posts类完全匹配,不要误指向了包含其他数据结构的上层节点。
- 定位具体转换问题:可以临时在构建Options时手动获取对应位置的DataSnapshot,调用
snapshot.getValue(Posts.class)并添加try-catch,捕获转换异常后查看具体的字段不匹配提示,快速定位问题。
内容的提问来源于stack exchange,提问作者allim
相关产品推荐
相关产品推荐

