I have an AsyncTask
that takes in context (used onPostExecute
) and runs doInBackground
to return an ArrayList of objects from a server. When I execute this I can see that doInBackground
runs fine, however it is not passing the result on to onPostExecute
.
After much searching, I have yet to find an answer of how to return an ArrayList of objects in an AsyncTask
.
This is the object I'm creating in doInBackground
and using onPostExecute
:
public class ServerTimeCard {
public String eventNameInput;
Boolean isLocation, isImage, isVoice;
public ServerTimeCard(String eventNameInput, boolean isLocation, boolean isImage, boolean isVoice) {
this.eventNameInput = eventNameInput;
this.isLocation = isLocation;
this.isImage = isImage;
this.isVoice = isVoice;
}
}
I'm executing the AsyncTask
with new LoadFriendCards(context).execute();
in onCreate
.
Expected Output: doInBackground
should return an ArrayList to onPostExecute
Current Output: The ArrayList<ServerTimeCard>
in onPostExecute
has a size of zero when the same arraylist in doInBackground
has a larger size.
The following is the AsyncTask
code.
public class LoadFriendCards extends AsyncTask<Void, Void, ArrayList<ServerTimeCard>> {
Context context;
ArrayList<ServerTimeCard> result;
public LoadFriendCards(Context context) {
this.context = context;
}
@Override
protected ArrayList<ServerTimeCard> doInBackground(Void... voids) {
result = new ArrayList<ServerTimeCard>();
// ...a bunch of data retrieval goes on here...
// querying parse for object info
// adding a new object to the local ArrayList for all in db
for (String friend : friendsListNames) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("TestObject");
query.whereEqualTo("accountName", friend+"@gmail.com");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
for (ParseObject cardInfo : objects) {
ServerTimeCard item = new ServerTimeCard(
cardInfo.getString("eventName"),
cardInfo.getBoolean("isImage"),
cardInfo.getBoolean("isImage"),
cardInfo.getBoolean("isVoice"));
result.add(item);
Log.e("New item called: ", String.valueOf(item.eventNameInput));
Log.e("New size of array...", String.valueOf(result.size()));
}
} else {
Log.d("info", "Error: " + e.getMessage());
}
}
});
}
// returning the new ArrayList<ServerTimeCard> to onPostExecute
// PROBLEM: THE SIZE OF THE RESULT IS 0
Log.e("Size of passing array", String.valueOf(result.size()));
return result;
}
@Override
protected void onPostExecute(ArrayList<ServerTimeCard> result) {
// PROBLEM: This returns 0
Log.e("Data list size: ", String.valueOf(result.size()));
// trying to use all objects in the arraylist here but it doesn't work
// due to the size. Something isn't passing correctly.
}
}
Logcat output of Log.e: (which looks like it calls doInBackground, then onPostExecute, then doInBackground again)
E/Size of passing array﹕ 0
E/Data list size:﹕ 0
E/New item called:﹕ yah
E/New size of array...﹕ 1
E/New item called:﹕ lplokolol
E/New size of array...﹕ 2
E/New item called:﹕ It works
E/New size of array...﹕ 3
SOLVED: I originally thought I needed the AsyncTask but I ended up deleting it all and throwing all the code into a method in my Main class. I was running too many things at once in an asynctask and the structure was throwing data all over the place. Lesson learned: keep it simple.
Your issue is that you are using findInBackground for your query. That method is done in a background thread. So you're basically running an async task, within an async task.
doInBackground
findInBackground
-> run asynchronously so code execute continuesonPostExecute
is called before your query finishes.done
call back is then called for your query to fill your listSo what you need to do instead is either use findInBackground
outside of an AsyncTask
(that method is intended to not be used in an AsyncTask) or use the find function.