Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android/FireStore QuerySnapshot convert to CustomObject

I am currently programin a test QuizApp. The gameplay is pretty easy I just want an online database of questions and a user can answer them.

This is what the database looks like:
enter image description here

That collection questions contains an unique ID and a custom Object (questionObject) named 'content'. The number is only something easy I can query/search for.

This is my questionAdder and query UI. It's only a small test App.

public class questionAdder extends AppCompatActivity {

EditText pQuestion, pAnwerA, pAnswerB, pAnswerC, pAnswerD, number;
Button pAdd, query;
private DatabaseReference databaseReference;
private FirebaseFirestore firebaseFirestore;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.addquestion);

    firebaseFirestore = FirebaseFirestore.getInstance();

    pQuestion = (EditText) findViewById(R.id.question);
    pAnwerA = (EditText) findViewById(R.id.answerA);
    pAnswerB = (EditText) findViewById(R.id.answerB);
    pAnswerC = (EditText) findViewById(R.id.answerC);
    pAnswerD = (EditText) findViewById(R.id.answerD);
    number = (EditText) findViewById(R.id.number);

    pAdd = (Button) findViewById(R.id.addQuestion);
    pAdd.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            readQuestionStore();
        }
    });

    query = (Button) findViewById(R.id.query);
    query.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            CollectionReference questionRef = firebaseFirestore.collection("questions");
            questionRef.whereEqualTo("content.number", "20").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                    questionObject pContent = queryDocumentSnapshots.toObjects(questionObject.class);
                }
            });
        }
    });

}

public void readQuestionStore(){

    Map<String, Object> pContent = new HashMap<>();
    pContent.put("question", pQuestion.getText().toString());
    pContent.put("Corr Answer", pAnwerA.getText().toString());
    pContent.put("AnswerB", pAnswerB.getText().toString());
    pContent.put("AnswerC", pAnswerC.getText().toString());
    pContent.put("AnswerD", pAnswerD.getText().toString());
    questionObject content = new questionObject(pContent, number.getText().toString()); //document("Essen").collection("Katalog")

    firebaseFirestore.collection("questions").add(content).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
        @Override
        public void onSuccess(DocumentReference documentReference) {
            Toast.makeText(questionAdder.this, "Klappt", Toast.LENGTH_LONG).show();
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Toast.makeText(questionAdder.this, "Klappt nicht", Toast.LENGTH_LONG).show();
        }
    });
}

}



And this is how my questionObject looks like:

public class questionObject{

private Map<String, Object> content;
private String number;

public questionObject(){

}

public questionObject(Map<String, Object> pContent, String pNumber) {
    this.content = pContent;
    this.number = pNumber;
}

public Map<String, Object> getContent() {
    return content;
}

public void setContent(Map<String, Object> content) {
    this.content = content;
}

public String getNumber() {
    return number;
}

public void setNumber(String number) {
    this.number = number;
}

}



Problem In that questionAdder class in the onClickListener I receive an "incompatible types" Error (Found: java.utils.list Required: questionObject).

query.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                CollectionReference questionRef = firebaseFirestore.collection("questions");
                questionRef.whereEqualTo("content.number", "20").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                    @Override
                    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                        questionObject pContent = queryDocumentSnapshots.toObjects(questionObject.class);
                    }
                });
            }
        });

If if I change that to a List it is empty. So the actual question is, how do I get the CustomObject into my code using the Database. Thanks!

like image 362
J. Lo Avatar asked Apr 01 '18 15:04

J. Lo


1 Answers

The reason you are getting this error in because the QuerySnapshot is a type which "contains" multiple documents. Firestore won't decide for you whether there are a bunch of objects to return as a result, or just one. This is why you can take two different approaches:

  1. Put the data in a custom object's list:

    List<questionObject> questionsList=new ArrayList<>();
    
    if (!documentSnapshots.isEmpty()){
        for (DocumentSnapshot snapshot:queryDocumentSnapshots)
            questionsList.add(snapshot.toObject(questionObject.class));
    
    }
    
  2. If you're sure that your gonna get only one queried object, you can just get the first object from the returned queryDocumentSnapshots:

    questionObject object=queryDocumentSnapshots.getDocuments().get(0).toObject(questionObject.class);
    

A few more things you should be aware of:

Why do you write content.number instead of just number? It seems like number is a separated field in your question document, so your code should be as follows:

CollectionReference questionRef = firebaseFirestore.collection("questions");
questionRef.whereEqualTo("number", "20").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
        questionObject pContent = queryDocumentSnapshots.toObjects(questionObject.class);
    }
});

In addition, try to change your number field to int, because it's not a String but a just a number.

By the way, it is more acceptable to write classes' names with a capital letter at a beginning, for example: QuestionObject question=new QuestionObject();

like image 194
Tal Barda Avatar answered Nov 17 '22 23:11

Tal Barda