I'm using Parse and I'm doing a query to fetch a table .
As you can see in the code below, the list LOCALparseQuestionList is populated correctly during the for loop inside the findInBackground. Once it's done, the LOCALparseQuestionList is empty (the log prints 0 size and I see the same when using the debugger).
How should I fetch correctly the data and populate my LOCALparseQuestionList?
public List<QuestionStruct> getParseAllQuestions() {
final List<QuestionStruct> LOCALparseQuestionList = new ArrayList<QuestionStruct>();
// Select All Query
ParseQuery<ParseObject> questionQuery = ParseQuery.getQuery("triviaQuestions");
questionQuery.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> allQuestions, ParseException e) {
if (e == null) {
parseQuestionList = allQuestions;
Log.d(TAG, "Retrieved " + allQuestions.size() + " All questions");
for (ParseObject qu : allQuestions) {
QuestionStruct currentQuestion = new QuestionStruct();
currentQuestion.setID(qu.getInt("id"));
currentQuestion.setQuestion(qu.getString("question"));
currentQuestion.setCorrectAnswer(qu.getString("correct"));
currentQuestion.setPossibleAnswer(qu.getString("wrong_1"));
currentQuestion.setPossibleAnswer(qu.getString("wrong_2"));
currentQuestion.setPossibleAnswer(qu.getString("wrong_3"));
currentQuestion.setPossibleAnswer(qu.getString("correct"));
LOCALparseQuestionList.add(currentQuestion);
Log.d(TAG, "Retrieved " + LOCALparseQuestionList.size() + " LOCALparseQuestionList ");
}
} else {
Log.d(TAG, "Error: " + e.getMessage());
}
}
});
Log.d(TAG, "questionList size: " + LOCALparseQuestionList.size());
return LOCALparseQuestionList;
}
Its a the number one misunderstanding about asynchronous functions: the code underneath the find function does not run after the find function. It runs before it.
The last log statement in the function logs, and the return statement returns an empty list, because that list is populated later, after the find is done and the results are returned. Anything you do that depend on LOCALparseQuestionList being populated must be done within the find's callback.
Related
public List<String> allMatches = null;
Amplify.DataStore.query(
Todo.class,
items -> {
while (items.hasNext()) {
Todo item = items.next();
allMatches.add(item.getName());
Log.i("Amplify", "Id " + item.getId());
}
},
failure -> Log.e("Amplify", "Could not query DataStore", failure)
);
for(String token : allMatches){
Log.i("help", "Id " + token);
}
the above code works fine. but the list allMatches is empty, even though it is set in the inner function
i am not good at lambda functions so i dont know how to modify the code to make it run
I want to fill an ArrayList with the results I get back from a Parse query. When I get the results I add them to the ArrayList and print the ArrayList size to the console to make sure the results are added, which is succesful, but when I return the ArrayList it's empty. Can anyone explain to me why this happens?
public ArrayList<ParseObject>findAllGroupByUserId(ParseUser userId){
//TODO hier uit db halen alle groupen van user
final ArrayList<ParseObject> groups = new ArrayList<>();
ParseQuery<Group_user> query = ParseQuery.getQuery("Group_user");
query.whereEqualTo("user_id", userId);
query.findInBackground(new FindCallback<Group_user>() {
#Override
public void done(List<Group_user> objects, ParseException e) {
if (e == null) {
for (Group_user group : objects) {
Log.e("SUCCESS", group.getObjectId() + " , " + group.getGroup_id().getObjectId());
ParseObject g = new Group();
groups.add(g);
}
System.out.println(groups.size() + " :Done method"); //THIS RETURNS 2
} else {
Log.e("ERROR", "message: " + e);
}
Log.e("SUCCESS", "we have " + groups.size() + " results");
}
});
System.out.println(groups.size() + " :return"); // THIS RETURNS 0
return groups;
}
Because findInBackground() runs asynchronously on a different thread. You need to execute your remaining logic from the done() call back to get the populated array.
Think of it like this:
Thread 1 -> invokes findInBackground() -> thread one is running -----------> group is empty until Thread 2 finishes
Thread 2 spawned -> reaches out to server and gets query results -> invokes done call back on Thread 1 (now you have the data ready)
So I'm assuming that Group_user is a subclass of ParseObject that you've already defined. Since the findInBackground is async, you should change logic of the calling of the function to async too. Instead of returning list of objects like you were before, do all the logic in the done function of the query, no need to return.
public void findAllGroupByUserId(ParseUser userId) {
ParseQuery<Group_user> query = ParseQuery.getQuery("Group_user");
query.whereEqualTo("user_id", userId);
query.findInBackground(new FindCallback<Group_user>() {
#Override
public void done(List<Group_user> groups, ParseException e) {
if (e == null && groups != null) {
for (Group_user group : groups) {
// perform all logic here
}
} else {
Log.e("Find Callback", "Oh no! Query failed!");
}
}
});
}
I've saved current user's friend list with PFRelation in android with parse and I want to query the current user's friend list to show it in listView (Or ListAdapter, I don't know which one is better)
Can you guys show me how to do it? source code provided will be great
let me know if you need any additional info!
Thank you
EDIT: I've tried this code but there's error occur says that
Error:(67, 25) error: name clash: done(List<ParseObject>,ParseException) in <anonymous com.example.krisanapongpoonsawat.chatit.User$1> and done(List<T>,ParseException) in FindCallback have the same erasure, yet neither overrides the other
where T is a type-variable:
T extends ParseObject declared in interface FindCallback
private void loadUserList()
{
ParseQuery query = new ParseQuery("Friends");
query.whereEqualTo("owner", ParseUser.getCurrentUser().getObjectId().toString());
query.findInBackground(new FindCallback() {
public void done(List<ParseObject> friendList, ParseException e) {
if (e == null) {
Log.d("score", "Retrieved " + friendList.size() + " scores");
for (int i = 0; i < friendlist.size(); i++) {
Object object = friendlist.get(i);
String name = ((ParseObject) object).getObjectId().toString();
listAdapter.add(name);
}
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
}
Does anyone know how to fix this? Thanks
I am now working on CloudCode, and would like to retrieve the number of items in the Parse Database that is greater than certain criteria (i.e. an inputting parameter).
Parse Cloud Code:
Parse.Cloud.define("query_num_greater_than_local", function(request, response)
{
var DB = Parse.Object.extend("Recording_db");
var query= new Parse.Query(DB);
query.greaterThan("Ref_int",1234);
query.find(
{
success: function(results)
{
console.log("received " + results.length + " result(s)");
response.success("done" + results.length);
},
error: function(error)
{
console.log("error: " + error);
}
});
});
Android code:
ParseCloud.callFunctionInBackground("query_num_greater_than_local", new HashMap<String, Object>(), new FunctionCallback<String>()
{
public void done(String result, ParseException e)
{
if (e == null)
{
tv1.setText(""+result);
}
else
{
tv1.setText("ParseException"+e);
}
}
});
Question:
While the above codes return a correct count of items greater than 1234, I would like to ask whether can 1234 be replaced as a parameter? i.e. query for a result based on an inputting variable query criteria, say become query.greaterThan("Ref_int", 2345)?
If then, how could this variable inputting criteria be applied to the codes? Many thanks!
This is doing my head in. I got this working in iOS in about 10 mins. Clearly I'm missing something. I'm simply trying to pull data out of parse.com into a textfield. I have found lots of examples but none explaining why it's not working correctly. Below is the code pulled from parse.com site and jiggyed with. Incidentally it's wigging out on totemList.getString particularly the "getString" part.
ParseQuery<ParseObject> query = ParseQuery.getQuery("Birds");
query.whereEqualTo("totemName", "Pigeon");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> totemList, ParseException e) {
if (e == null) {
Log.d("score", "Retrieved " + totemList.size() + " scores");
String totemDesc = totemList.getString("totemDesc");
//Get the Totems Description
TotemDescription = (TextView)findViewById(R.id.animalDesc);
TotemDescription.setText(totemDesc);
} else {
Log.d("score", "Error: " + e.getMessage());
// something went wrong
TotemDescription = (TextView)findViewById(R.id.animalDesc);
TotemDescription.setText("not bob");
}
}
});
List<> does not have a getString() method.
List<ParseObject> totemList
Perhaps what you wanted to do was to iterate over your list of ParseObject get all the descriptions:
String descriptions = null;
for (ParseObject totem : totemList) {
if (descriptions == null) {
descriptions = totem.getString("totemDesc");
} else {
descriptions = descriptions + ", " + totem.getString("totemDesc");
}
}
Something like that. Then set the resulting string as text of your text field
TotemDescription.setText(descriptions);
If you have more than one ParseObject in your List<> your text will be something like:
Pigeon Totem, Another Pigeon Totem