mnlfischer
mnlfischer

Reputation: 155

Null object reference in Firebase result loop

I want to receive all challenges in Firestore and loop over result to add it to an ArrayList.

db.collection("challenges")
        .get()
        .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                    for (DocumentSnapshot document : task.getResult()) {
                        if (document.exists()) {
                            Log.d(TAG, document.getId() + " => " + document.getData());
                    Error-> Challenge challenge = document.toObject(Challenge.class);
                            Log.d(TAG, challenge.getUid() + " => " + challenge.getText());
                            challengeList.add(document.getData().toString());
                        }
                    }

                    challengeListView.setAdapter(challengeArrayAdapter);
                } else {
                    Log.d(TAG, "Error getting documents: ", task.getException());
                }
            }
        });

Error is:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[])' on a null object reference

Line:

Challenge challenge = document.toObject(Challenge.class);

The log with Log.d(TAG, document.getId() + " => " + document.getData()); is working.

Reference: https://firebase.google.com/docs/firestore/query-data/get-data#get_all_documents_in_a_collection

This is my my Challenge Class:

public class Challenge {

    private Date createdAt;
    private Date changedAt;
    private String uid;
    private String text;
    private double longitude;
    private double latitude;

    public Challenge(String uid, String text, double longitude, double latitude) {
        Date currentDate = new Date();
        this.createdAt = currentDate;
        this.changedAt = currentDate;
        this.uid = uid;
        this.text = text;
        this.longitude = longitude;
        this.latitude = latitude; }

    public Date getCreatedAt() { return createdAt; }

    public Date getChangedAt() { return changedAt; }

    public String getUid() { return uid; }

    public String getText() { return text; }

    public double getLongitude() { return longitude; }

    public double getLatitude() { return latitude;}
}

Upvotes: 2

Views: 1960

Answers (3)

Himanshu Sharma
Himanshu Sharma

Reputation: 1

Bro, you need to add Default Constructor in your Challenge Model class as it is needed for Firebase

public Challenge() {} //add this line

Upvotes: 0

Nouman Ch
Nouman Ch

Reputation: 4121

I know it is too late but it may help some one in my case my object was

public class RFQ {
    public String content,email,receiverKey,productKey,companyKey;
    public Sender sender;
    public Long createAt;

    public RFQ() {
    }

    public RFQ(String content, String email, String receiverKey, String productKey, String companyKey, Sender sender, Long createAt) {
        this.content = content;
        this.email = email;
        this.receiverKey = receiverKey;
        this.productKey = productKey;
        this.companyKey = companyKey;
        this.sender = sender;
        this.createAt = createAt;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Long getCreateAt() {
        return createAt;
    }

    public void setCreateAt(Long createAt) {
        this.createAt = createAt;
    }

    public String getReceiverKey() {
        return receiverKey;
    }

    public void setReceiverKey(String receiverKey) {
        this.receiverKey = receiverKey;
    }

    public String getProductKey() {
        return productKey;
    }

    public void setProductKey(String productKey) {
        this.productKey = productKey;
    }

    public String getCompanyKey() {
        return companyKey;
    }

    public void setCompanyKey(String companyKey) {
        this.companyKey = companyKey;
    }

    public Sender getSender() {
        return sender;
    }

    public void setSender(Sender sender) {
        this.sender = sender;
    }
}

Everything is proper here but still, I was getting the error that was due to my Sender class in my Sender class I missed to place non-args constructor.

Upvotes: 0

Alex Mamo
Alex Mamo

Reputation: 138869

You need to change this line of code:

Challenge challenge = document.toObject(Challenge.class);

with

Map<String, Object> map = task.getResult().getData());

To use toObject() method for a single document, please use the following code:

DocumentReference docRef = db.collection("challenges").document("yourDocument");
docRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
        Challenge challenge = documentSnapshot.toObject(Challenge.class);
    }
});

The error is because of your modell class. Your code looks good. Add the no-argument constructor in your model class. Keep that code or use the Map<String, Object> and your problem will be solved.

To add the no-argument constructor, please add the following line of code in your model class:

public Challenge() {} //Needed for Firebase

after the decalaration of class variables.

Upvotes: 4

Related Questions