Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase firestore .QuerySnapshot.getDocumentChanges()' on a null object reference

I have this weird problem that never occured to me in any of my firestore apps,I have this Recyclerview where i want to display image and text from my firestore, and I am getting the following error.

java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.google.firebase.firestore.QuerySnapshot.getDocumentChanges()' on a null object reference

This is how my data in firestore is present:

enter image description here The following is my Activity class

package rimapps.appslet.lchfmalayalam.view;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import com.google.firebase.FirebaseApp;
import com.google.firebase.firestore.DocumentChange;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.QuerySnapshot;

import java.util.ArrayList;
import java.util.List;

import rimapps.appslet.lchfmalayalam.R;
import rimapps.appslet.lchfmalayalam.adapter.BreakfastAdapter;
import rimapps.appslet.lchfmalayalam.model.ContentsBreakfast;

public class BreakfastActivity extends AppCompatActivity {

    private FirebaseFirestore db;
    private static final String TAG="BreakfastActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FirebaseApp.initializeApp(this);
        setContentView(R.layout.activity_breakfast);


        RecyclerView recbrf = (RecyclerView)findViewById(R.id.rec_brf);
        recbrf.setNestedScrollingEnabled(false);
        final List<ContentsBreakfast> breakfastList = new ArrayList();
        recbrf.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        final BreakfastAdapter adapterb = new BreakfastAdapter(breakfastList, getApplicationContext());
        recbrf.setAdapter(adapterb);
        db = FirebaseFirestore.getInstance();
      db.collection("breakfast").addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
                if (e!=null){
                    Log.d(TAG,"Error:"+e.getMessage());
                }
                for (DocumentChange doc: documentSnapshots.getDocumentChanges()){

                    if (doc.getType() == DocumentChange.Type.ADDED){
                        //String title = doc.getDocument().getString("title");

                        ContentsBreakfast bfname= doc.getDocument().toObject(ContentsBreakfast.class);
                        breakfastList.add(bfname);
                        adapterb.notifyDataSetChanged();
                    }
                }}
        });


    }
}

This is my Adapter class of Recyclerview

package rimapps.appslet.lchfmalayalam.adapter;

import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Protocol;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import rimapps.appslet.lchfmalayalam.R;
import rimapps.appslet.lchfmalayalam.model.ContentsBreakfast;
import rimapps.appslet.lchfmalayalam.view.RecipeView;

public class BreakfastAdapter extends RecyclerView.Adapter<BreakfastAdapter.ViewHolder> {

    List<ContentsBreakfast> breakfastlist = new ArrayList<>();
    Context context;

    public BreakfastAdapter(List<ContentsBreakfast> breakfastlist, Context context) {
        this.breakfastlist = breakfastlist;
        this.context = context;
    }
    @NonNull
    @Override
    public BreakfastAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.breakfast_card, parent, false);
        return new BreakfastAdapter.ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.brfname.setText(breakfastlist.get(position).getBfname());
        OkHttpClient client = new OkHttpClient();
        client.setProtocols(Arrays.asList(Protocol.HTTP_1_1));
        RequestOptions options = new RequestOptions()
                .placeholder(R.drawable.placeholder)
                .error(R.drawable.browser)
                .diskCacheStrategy(DiskCacheStrategy.ALL);

        Glide.with(context)
                .load(breakfastlist.get(position).getBfimg())
                .apply(options)
                .into(holder.brfimg);
        holder.card_brf.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent(context, RecipeView.class);
                context.startActivity(intent);
            }
        });
        }

    @Override
    public int getItemCount() {
        return breakfastlist.size();
    }
    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView brfname;
        public ImageView brfimg;
        public CardView card_brf;
        public ViewHolder(View itemView) {
            super(itemView);
            card_brf = (CardView)itemView.findViewById(R.id.brf_card);
            brfname = (TextView) itemView.findViewById(R.id.brf_name);
            brfimg = (ImageView) itemView.findViewById(R.id.brf_image);

        }
    }}

The following code contains my Model class

package rimapps.appslet.lchfmalayalam.model;

public class ContentsBreakfast {
    int bfimg;
    String bfname;

    public int getBfimg() {
        return bfimg;
    }

    public void setBfimg(int bfimg) {
        this.bfimg = bfimg;
    }

    public String getBfname() {
        return bfname;
    }

    public void setBfname(String bfname) {
        this.bfname = bfname;
    }
}
like image 658
appslet inv Avatar asked Mar 06 '23 06:03

appslet inv


1 Answers

If you look at the reference docs for onEvents, they say:

onEvent will be called with the new value or the error if an error occurred. It's guaranteed that exactly one of value or error will be non-null.

Parameters:

value The value of the event. null if there was an error.

error The error if there was error. null otherwise.

So it seems that onEvent either gets an error or a query snapshot. So you need an if... then... else in your code:

public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
    if (e!=null){
        Log.d(TAG,"Error:"+e.getMessage());
    }
    else {
        for (DocumentChange doc: documentSnapshots.getDocumentChanges()){
            if (doc.getType() == DocumentChange.Type.ADDED){
                ContentsBreakfast vidtitle= doc.getDocument().toObject(ContentsBreakfast.class);
                breakfastList.add(vidtitle);
                adapterb.notifyDataSetChanged();
            }
        }
    }
});
like image 92
Frank van Puffelen Avatar answered Mar 10 '23 11:03

Frank van Puffelen