I have a complex problem, what I don't understand. In this class I would like to
add 21 random objects from one arraylist listChallenges to the arraylist finalChallenges. However it doesn't work , sometimes finalChallanges contains 21 objects , but most of the times it contains less objects, but I don't know where is the problem. Actually, I tried to comment every step, and if did something wrong, please tell me.
Please help me, I have no idea what shoud I do..
ArrayList<Challenges> listChallenges = new ArrayList<Challenges>();
ArrayList<Challenges> finalChallenges = new ArrayList<Challenges>(20);
//Check where the same userId and subscribers.objectId,
//Request these categories object and save to the ArrayList<Category> totalCategories
//Save these categories objectId to the selectedCategoriesId List<String>
BackendlessDataQuery query = new BackendlessDataQuery();
query.setWhereClause( "subscribers.objectId = '"+backendlessUser.getObjectId()+"'");
Backendless.Data.of(Category.class).find(query, new AsyncCallback<BackendlessCollection<Category>>() {
@Override
public void handleResponse(BackendlessCollection<Category> categoriesBackendlessCollection) {
//add selected categories to totalActivities Category ArrayList
for( Category categories : categoriesBackendlessCollection.getData()) {
totalCategories.add(categories);
selectedCategoriesId.add(categories.getObjectId());
//
}
System.out.println(selectedCategoriesId);
//For cycle is going to selectedCategoriesId.size
//Check where the same category-objectId and actual selectedCategoriesId
//Request these challenges object, which are in the actual category and save to the ArrayList<Challenges> listChallenges
//Save these categories objectId to the selectedCategoriesId List<String>
for(int k=0;k<selectedCategoriesId.size();k++) {
BackendlessDataQuery query = new BackendlessDataQuery();
query.setPageSize(pageSize);
query.setWhereClause("category.objectId = '" + selectedCategoriesId.get(k) + "'");
Backendless.Data.of(Challenges.class).find(query, new AsyncCallback<BackendlessCollection<Challenges>>() {
@Override
public void handleResponse(BackendlessCollection<Challenges> cha) {
for (Challenges challenges : cha.getData()) {
listChallenges.add(challenges);
challengeTitle.add(challenges.getChallengeTitle());
challengeContent.add(challenges.getChallengeContent());
challangeId.add(challenges.getObjectId());
}
System.out.println("osszes elem:"+listChallenges);
//ArrayList<Challenges> finalChallenges size is 21 with 0
// get from listChallenges random 21 object without concord and add to the finalChallenges
Random random = new Random();
List<Challenges> temp = new ArrayList<>(listChallenges);
ArrayList<Challenges> tempNewList = new ArrayList<Challenges>();
//ArrayList<Challenges> temp = new ArrayList<Challenges>(listChallenges.size());
for (Challenges item : listChallenges) temp.add(item);
while (finalChallenges.size()<21 && temp.size()>0) {
int index = random.nextInt(temp.size());
tempNewList.add(temp.get(index));
temp.remove(index);
finalChallenges= tempNewList;
}
// System.out.println("kihívások");
System.out.println(finalChallenges);
System.out.println(finalChallenges.size());
// title.setText(challengeTitle.get(0));
// content.setText(challengeContent.get(0));
// objectId = challangeId.get(0);
}
@Override
public void handleFault(BackendlessFault fault) {
}
});
//save finalChallenges array objects to the current user "userChallenges" relationship
Backendless.UserService.login( email, password, new AsyncCallback<BackendlessUser>() {
@Override
public void handleResponse(BackendlessUser backendlessUser) {
backendlessUser.setProperty("userChallenges",new ArrayList<>(finalChallenges));
}
});
Backendless.UserService.update(backendlessUser, new BackendlessCallback<BackendlessUser>() {
@Override
public void handleResponse(BackendlessUser response) {
System.out.println( "User has been updated" );
}
@Override
public void handleFault(BackendlessFault fault) {
System.out.println( "User has not been updated");
}
});
}
@Override
public void handleFault(BackendlessFault backendlessFault) {
System.out.println( "Server reported an error - " + backendlessFault.getMessage() );
}
},true);
}
}
@Override
public void handleFault(BackendlessFault fault) {
}
});
You don't show where finalChallenges
is initialized, and we can see it is overwritten asynchronously in response handlers: it is very likely an issue of concurrent access.
The logic itself where you fill the list from random elements of another list would be correct, if the instance of finalChallenges
was not "shared" across different/concurrent executions of that handler.
Also, a small tip: to create your temp list in one go without loop you can do this: List<Challenge> temp = new ArrayList<>(listChallenges);
Edit: 2 suggestions.
listChallenges = tempNewList
)backendlessUser.setProperty("userChallenges", new ArrayList<>(finalChallenges));
)