i am making an android app in which i am getting the data from the server side by making doinbackground method and assigning these values to the variables which are declared globally. Problem is that i am using that variables in oncreate method where it give me null values because the doinbackground method finishes after the variables are used in oncreate. what could be the solution for this?
public void getProfileInfo() {
String currentUserId = ParseUser.getCurrentUser().getObjectId();
ParseQuery<ParseObject> query = ParseQuery
.getQuery(ParseConstants.KEY_USER_INFO);
query.whereEqualTo(ParseConstants.KEY_USER_ID_INFO, currentUserId);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
for (ParseObject thisUser : objects) {
name = thisUser
.getString(ParseConstants.TYPE_INFO_FULLNAME);
email = ParseUser.getCurrentUser().getEmail();
}
} else {
Log.d("Activity", "Error: " + e.getMessage());
}
}
});
}
i am calling this method in oncreate before i use the variables name and email.i checked the value of name and email. it gave me the right values.
It sounds like you have a bit of timing problem.
Just to state the obvious, you can't start an asynchronous task on a background thread, and then blindly use the results without knowing that the task has completed.
The use of the results needs to be triggered by the completion of the task.
So, whatever you're doing to access these 'global variables' that is getting nulls - don't do it at a deterministic time (e.g. in onCreate) - do it when you actually get the results back.
If there's a chance that the results may come back before the point where you're currently trying to access them, check to see if they have come back, and if they have, use them. If they haven't, wait until they do come back.
I'll leave the implementation of this as an "exercise for the reader"
Related
i'm having an issue that soon enough going to blow me.
i have Database table lets call it A. table A has field that determines if this row is processed or no. i update the field myself from within the Parse Browser to either True | False, and trying to call query.findInBackground() to check with the Boolean value however the returned List always returns False if its True and vice versa. enough talking let me show you what i'm doing.
public static void getMyRequests(ParseUser user, final FindCallback<ServicesModel> callback) {
ParseQuery<ServicesModel> query = new ParseQuery<>(ServicesModel.class);
if (!user.getBoolean(ParseHelper.CAN_UPLOAD)) {
query.whereEqualTo("user", user);
}
query.findInBackground(new FindCallback<ServicesModel>() {
#Override public void done(final List<ServicesModel> objects, ParseException e) {
if (e == null) {
if (objects != null && !objects.isEmpty()) {
for (ServicesModel object : objects) {
object.setHandlerUser(object.getParseUser("handlerUser"));
object.setProcessedTime(object.getLong("processedTime"));
object.setCategoryType(object.getString("categoryType"));
object.setUser(object.getParseUser("user"));
object.setUserRequest(object.getString("userRequest"));
object.setImageUrl(object.getString("imageUrl"));
object.setProcessed(object.getBoolean("isProcessed"));
Logger.e(object.getBoolean("isProcessed") + "");
}
callback.done(objects, null);
} else {
callback.done(null, new ParseException(1001, "No Services"));
}
} else {
callback.done(null, e);
}
}
});
}
the code above suppose to refresh my data but however my log always shows that isProcessed is False even tho it's set to True inside the Parse Browser
what i have tried besides this? fetchAllInBackground & fetch() you name it. the object will always return false until i re-run the application from Android Studio what i'm doing here wrong? btw here is how i initialize Parse
Parse.setLogLevel(BuildConfig.DEBUG ? DEBUG_LEVEL : Parse.LOG_LEVEL_NONE);
ParseObject.registerSubclass(ProductsModel.class);
ParseObject.registerSubclass(ProductRentalModel.class);
ParseObject.registerSubclass(ServicesModel.class);
Parse.enableLocalDatastore(context);
Parse.initialize(context, context.getString(R.string.app_id), context.getString(R.string.client_id));
the answer was to remove
Parse.enableLocalDatastore(context);
which is bad anyway, without the datastore enabled the data are refreshed probably, however with enabling the local database, the data will not refresh unless if i killed the app and/or re-install it. that's bad. but did the trick.
The find on the db does not complete, so the FindCallback.done() method is never called, no errors, nothing, just is not called. this is the code
ParseQuery<ParseObject> pq = ParseQuery.getQuery("Category").setLimit(1);
pq.getFirstInBackground(new GetCallback<ParseObject>() {
#Override
public void done(ParseObject object, ParseException e) {
throw new RuntimeException();
}
});
I can see the prints before and after this portion of code, but the exception is never thrown. Please, I do really need help.
Edit: I use the parse-login before this point and it works correctly, even the saveInBackground() works correctly, the only problems I find are about queries, (find, getfirst ecc).
Resolved, I found out that the background features offered by Parse do not work if in your activity there are fragments, so you have to implement them yourself. The only strange fact is that in the beginning some function (such saveInBackground as I mentioned above) worked.
Check the ACL column in the parse object row, maybe you don't have permission to read.Double click on the ACL column and check the "public Read".
Thy this:
ParseQuery<ParseObject> pq = ParseQuery.getQuery("Category").setLimit(1);
pq.findInBackground(new FindCallback< ParseObject >() {
#Override
public void done(List< ParseObject > parseObjects, ParseException e) {
// Success
} else {
e.printStackTrace();
}
The pq.getFirstInBackground(new GetCallback<ParseObject>() is meant to return only one object, so you need to help it zero in on that object, for example a particular name or item.
Try adding pq.whereEqualTo("item", biscuit);.
If you want to return a list of objects you need to use a different callback.
End product should look like this.
ParseQuery<ParseObject> pq = ParseQuery.getQuery("Category").setLimit(1);
pq.whereEqualTo("item_key_here", "item_value_here");
pq.getFirstInBackground(new GetCallback<ParseObject>() {
#Override
public void done(ParseObject object, ParseException e) {
if(object != null){
//do stuff here
}
});
I'm using parse to store my data and do a lot of queries while using my program.
The issue is that after about +/-20 similar queries, parse findInBackground() or getFirstInBackground() doesn't return a callback and app stuck at that possition.
My query code:
ParseQuery<OptionCodeDTO> mQuery;
mQuery = ParseQuery.getQuery(OptionCodeDTO.class);
mQuery.whereEqualTo("code", prCode);
mQuery.getFirstInBackground(new GetCallback<OptionCodeDTO>() {
#Override
public void done(OptionCodeDTO optionCodeDTO, ParseException e) {
if (isVisible()) {
if (e == null) {
OptionCode opCode = new OptionCode(optionCodeDTO);
mCodes.push(opCode);
printCodes();
prDescrLayout.setVisibility(View.VISIBLE);
prDescProgress.setVisibility(View.GONE);
mPRLable.setVisibility(View.GONE);
} else {
if (e.getCode() == ParseException.CONNECTION_FAILED) {
mPrDescr.setText(R.string.dtc_lookup_check_network);
} else if (e.getCode() == ParseException.OBJECT_NOT_FOUND) {
mPrDescr.setText(R.string.pr_lookup_code_not_found);
} else {
mPrDescr.setText(R.string.dtc_lookup_other_problems);
}
prDescrLayout.setVisibility(View.VISIBLE);
prDescProgress.setVisibility(View.GONE);
}
}
}
});
First of all, if your app ANRs (application not responding) because of something from UI thread that relies on background threads, that is incorrect architecture.
Probably you have to optimize your app's interaction with Parse. Generally it is a bad practice to make lots of saveInBackground, for example from inside a loop. You can add objects, those need to be saved, to a list and then use ParseObject.saveAllInBackground(objectList)
Also an idea to optimize is to use local storage - android's built in SQLite. For example if your app relies on something being saved to Parse, the logic is like this:
When saving object first you save to local DB and run a saveInBackground method.
When fetching objects you first fetch from your local DB and then run a getInBackground method, which inside a callback persists the information to your local DB.
This way you will make your app usable without internet connection.
I have recently managed to switch to Local Datastore, moving all the needed parts of the database to the client. Furthermore I send a push notification whenever data changes so that the client data stays up to date.
Now my problem is that one of the pointers in my data keeps returning the old pointer after updating.
Here is the code that I use:
public ParseQuery<CircuitUnit> circuitUnits() {
ParseQuery<CircuitUnit> query = CircuitUnit.getQuery();
query.include(CircuitUnit.circuits);
query.include(CircuitUnit.guard);
query.setLimit(1000);
return query;
}
circuitUnits().findInBackground(
new FindCallback<CircuitUnit>() {
#Override
public void done(List<CircuitUnit> objects, ParseException e) {
Log.d(TAG, "Pinning circuitUnits " + objects.size());
// debugging loop of results
for (CircuitUnit circuitUnit : objects) {
if (circuitUnit.getObjectId().equals("TXEZDch6wK")) {
Guard guard = circuitUnit.getGuard();
Log.d(TAG, "Guard: " + guard.getObjectId());
}
}
// This function updates the Local datastore with the newly fetched objects
// updateServerDataPin(objects, PinsGlobal.CIRCUIT_UNITS,
e, callback);
}
});
The Logged output is: "Guard: L440gHXKTY" where it should be SDDg23rR4h
I have added a screenshot of the CircuitUnit table showing that SDDg23rR4h is indeed the expected objectId of the pointer.
I tried to create a sample project showing the issue as part of the bug report for parse.com, but that returned the correct pointer.
My theory is then that this problem lies in having data in the Local Datastore which somehow interferes with the result. Not that I understand why, cause I am clearly querying the network and not locally.
It seems as if the include statements are ignored and simply filled with the known data from the Local Datastore.
Has anyone experienced something similar or have a possible explanation to this behaviour?
I was making two Parse.com queries ..
ABC.findInBackground(new FindCallback<ParseObject>()
{
...
}
DEF.findInBackground(new FindCallback<ParseObject>()
{
...
}
and I essentially tried doing this,
CountDownLatch waitForBoth = new CountDownLatch(2);
ABC.findInBackground(new FindCallback<ParseObject>()
{
...
waitForBoth.countDown();
}
DEF.findInBackground(new FindCallback<ParseObject>()
{
...
waitForBoth.countDown();
}
// (error handling (just a flag) not shown)
waitForBoth.await();
Log("both are finished yay!");
of course, I just get the sundry errors IllegalMonitorStateException: object not locked by thread before wait() etc etc etc.
Part of the problem other than me being dense is, those calls to Parse's findInBackground in fact, take you off on a new thread anyway, right?
For the record, one of those Parse calls looks like this,
ParseQuery<ParseObject>PQ = ParseQuery.getQuery("SomeTable");
PQ.whereEqualTo("SomeColumn", ParseUser.getCurrentUser());
PQ.include("SomeOtherColumn");
PQ.findInBackground(new FindCallback<ParseObject>()
{
#Override
public void done(List<ParseObject> res, ParseException e)
{
if (e == null)
{
// res is the List of ParseObject results from the cloud
// here, you'd basically...
waitForBoth.countDown();
}
else
{
int errCodeSimple = e.getCode();
exampleWoeFlag = false;
waitForBoth.countDown();
}
}
});
}
and the doco on that ...
http://parse.com/docs/android/api/com/parse/ParseQuery.html#findInBackground(com.parse.FindCallback)
The Parse SDK does create a new Thread, but the "done" method is running on the UI Thread. This means you are calling "countDown" on the UI Thread, but you will never reach there, because you have called "await" on it.
You could solve it by creating your own Threads and passing the CountDownLatch in it. And then use Parse's synchronous methods
does that make sense ? Someone correct me if Im wrong
By the way, there is an excellent (free) course running on coursera at the moment (https://www.coursera.org/course/posa) that discusses the CountDownLatch in Android.
kind regards
Anton