【问题标题】:Issue with FirebaseRecyclerAdapter, on a null object reference when delete dataFirebaseRecyclerAdapter 的问题,在删除数据时在空对象引用上
【发布时间】:2018-11-11 14:08:29
【问题描述】:

Firebase 数据库中的显示工作正常,但是当我尝试从数据库中删除项目时,应用程序崩溃了,尽管删除发生了。写入字符串中的空对象引用:

String postDescription = dataSnapshot.child("desc").getValue().toString();

这是我的代码:

public class PostFragment extends Fragment {

private RecyclerView recyclerPost;

private DatabaseReference postReference;

private View view;
private LinearLayoutManager layoutManager;

public PostFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {

    view = inflater.inflate(R.layout.fragment_post, container, false);

    recyclerPost = view.findViewById(R.id.recycler_post);

    postReference = FirebaseDatabase.getInstance().getReference().child("Posts");
    postReference.keepSynced(true);

    layoutManager = new LinearLayoutManager(getContext());
    layoutManager.setReverseLayout(true);
    layoutManager.setStackFromEnd(true);
    recyclerPost.setHasFixedSize(true);
    recyclerPost.setLayoutManager(layoutManager);

    return view;
}

@Override
public void onStart() {
    super.onStart();
    Query query = postReference.orderByChild("timestamp");

    FirebaseRecyclerOptions<Posts> options =
            new FirebaseRecyclerOptions.Builder<Posts>()
                    .setQuery(query, Posts.class)
                    .build();

    FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<Posts, PostViewHolder>(options) {

        @Override
        protected void onBindViewHolder(@NonNull final PostViewHolder holder, int position, @NonNull final Posts model) {

            final String postId = getRef(position).getKey();
            postReference.child(postId).addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    String postDescription = dataSnapshot.child("desc").getValue().toString();
                    holder.postDesc.setText(postDescription);                   
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            });

            holder.delBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    postReference.child(postId).removeValue();
                }
            });


        }

        @NonNull
        @Override
        public PostViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.blog_item, viewGroup, false);
            return new PostViewHolder(view);
        }

    };

    adapter.startListening();
    recyclerPost.setAdapter(adapter);
}

public class PostViewHolder extends RecyclerView.ViewHolder {

    private TextView postDesc;
    private Button delBtn;
    private View view;

    public PostViewHolder(@NonNull View itemView) {
        super(itemView);
        view = itemView;
        postDesc = (TextView) view.findViewById(R.id.post_description); 
        delBtn = (Button) view.findViewById(R.id.del_post_btn);

    }
}
}

请告诉我这个问题的解决方案。

【问题讨论】:

  • 如果应用程序崩溃,您的 logcat 应该包含错误消息和堆栈跟踪。请查看这些内容,并将它们添加到您的问题中。

标签: android firebase firebase-realtime-database android-recyclerview firebaseui


【解决方案1】:

您可以尝试以下方法:

            postReference.child(postId).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                  if(dataSnapshot.exists()){
                String postDescription = dataSnapshot.child("desc").getValue().toString();
                holder.postDesc.setText(postDescription);                   
            }
          }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

可以使用exists()的方法:

public boolean exists ()

如果快照包含非空值,则返回 true。

它将检查数据快照是否在 数据库,如果它不在数据库中,则可以添加小吃店或吐司。

更多信息在这里:

https://firebase.google.com/docs/reference/android/com/google/firebase/database/DataSnapshot#exists()

【讨论】:

    【解决方案2】:

    每次将帖子添加到适配器/列表视图时,您现在都会在您的onBindViewHolder 中创建一个带有addValueEventListener 的侦听器。此侦听器从数据库中获取值,然后继续侦听更改,直到您将其删除。由于您从不删除这些侦听器,因此随着时间的推移,它们会加起来,事情可能会变得不同步。

    最简单的解决方案是使用addListenerForSingleValueEvent

    @Override
    protected void onBindViewHolder(@NonNull final PostViewHolder holder, int position, @NonNull final Posts model) {
    
        final String postId = getRef(position).getKey();
        postReference.child(postId).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                String postDescription = dataSnapshot.child("desc").getValue().toString();
                holder.postDesc.setText(postDescription);                   
            }
    
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                throw databaseError.toException(); // don't ignore errors
            }
        });
    

    当您使用addListenerForSingleValueEvent 时,侦听器会在onDataChange 第一次触发后立即被移除。

    【讨论】:

      猜你喜欢
      • 2016-11-28
      • 2021-08-16
      • 1970-01-01
      • 2016-10-28
      • 2012-08-07
      • 2019-04-07
      • 1970-01-01
      • 2018-07-22
      相关资源
      最近更新 更多