I'm meeting a problem in my current app, the app containt following/follower system, when I look to user profil I want to retrieve an information if I'm already following this user or not. this is my code
private class CheckinIfFollowing extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//preexcution
}
#Override
protected Void doInBackground(Void... params) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Follow");
query.whereEqualTo("from", ParseUser.getCurrentUser());
query.whereEqualTo("to", userId);
query.getFirstInBackground(new GetCallback<ParseObject>() {
#Override
public void done(ParseObject object, ParseException e) {
if(e==null){
Toast.makeText(UserProfil.this, "blue", Toast.LENGTH_SHORT).show();
//btn_follow.setButtonColor(getResources().getColor(R.color.bleu));
}else{
if(e.getCode() == ParseException.OBJECT_NOT_FOUND)
{
Toast.makeText(UserProfil.this, "pink", Toast.LENGTH_SHORT).show();
//btn_follow.setButtonColor(getResources().getColor(R.color.pink));
}
else
{
//unknown error, debug
}
}
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
// followingButton(AlreadyFollowing);
// btn_follow.setClickable(true);
}
}
I'm executing the AsyncTask but nothing shown in the screen.
Btw the "from" and "to" column of the Follow class in parse.com are pointers to _User.
First of all (that's not directly related to your issue, just an observatino): if you're using <something>InBackground method of a query, you don't have to put it inside an AsyncTask. It's already being executed in the background. In your case, you are basically (simplifying a bit here) executing an async task from an async task.
Although you didn't say what's stored in the userId object, I'm assuming (based on it's name) it's an objectId of a ParseUser object and not a ParseUser object itself. And I believe that's a reason for your issue. This line to be exact:
query.whereEqualTo("to", userId);
You said:
Btw the "from" and "to" column of the Follow class in parse.com are
pointers to _User.
If you're storing Pointer to another ParseObject you should probably be passing this type of an object if you're using this field in a query (and not an objectId - String). So in your case you should be passing an instance of ParseUser instead of its objectId.
You can use createWithoutData method of ParseObject to create an object (with objectId) that you can use for your query.
Related
I am calling an API through POST method and its constantly returning NULL. What could be the possible reason? I have posted the whole code. protected void onPostExecute(Void result) is actually getting NULL.
The structure of what you're doing is not right. You're using an AsyncTask with a return type of Void. The only possible value of type Void is null, so that's the only thing you can possibly get back in your onPostExecute() method. That's what happens when you return null from your doInBackground() method.
Void is appropriate for when generics force you to use a type, but you don't really need one. So you'd use it only when you don't actually need anything to be returned. In your case, where you're wanting to retrieve something that results from the call, you need a different type.
If all you want is to know whether it's succeeded or not, you could use Boolean, and have it return true when it succeeds (where you currently have return null), and false when it fails (in your catch blocks).
From the javadoc
The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.
so result is always null.
You must change your asyncTask to return something different than Void
Something like :
private class MyTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//Do request
return "response"; //return request's response as String
}
#Override
protected void onPostExecute(String result) {
if(result.equals("response")){
Toast.makeText(getApplicationContext(), "HTTP POST is working...", Toast.LENGTH_LONG).show();
} else{
Toast.makeText(getApplicationContext(), "Invalid POST req...", Toast.LENGTH_LONG).show();
}
}
}
I don't understand how is the Parse working?
I download data in parse to my arraylist , but when I show the Pets.size inside (//here) method "done" it will show 4, but when I show pets.size outside the done's method it will show 0?
public class Test extends AppCompatActivity {
ArrayList<Pet> pets;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
pets = new ArrayList<>();
ParseQuery<Pet> query = new ParseQuery<>("Pets");
query.findInBackground(new FindCallback<Pet>() {
#Override
public void done(List<Pet> list, ParseException e) {
if (e!=null){
Toast.makeText(Test.this,"Error",Toast.LENGTH_LONG).show();
}
for (Pet pet : list){
Pet newPet = new Pet();
newPet.setName(pet.getName());
newPet.setType(pet.getType());
pets.add(newPet);
}
// here
}
});
Toast.makeText(Test.this,"You have "+pets.size()+" pets",Toast.LENGTH_LONG).show();
}
Here's my Pet class:
#ParseClassName("Pets")
public class Pet extends ParseObject {
public String getName(){
return getString("name");
}
public void setName(String name) {
put("name", name);
}
public String getType(){
return getString("type");
}
public void setType(String type) {
put("type", type);
}
}
And an orther question , what should I do if I wanna save the data in local data?
Explanation:
findInbackground performs an operation to find all ParseObjects in a background thread (outside the main thread, or UI thread). So when it completes in the place where you have the comment
//here
That is when the background thread finishes it's call to find the objects. When you try to look at the size of the array outside that call where it shows size of 0, it is because it reached that point before the background thread finishes it's work (of adding to your array from objects it found).
What is happening is the operation for find() is happening in parallel with your main threads code.
And for your second question, make sure you enableLocalDatastore and then you can pin results from queries to your local cache. This data is stored on the device until the user deletes your app or clears cached data in settings.
Follow this guide to setup local cache Local Datastore with Parse
Note: A solution to your problem for when the background task of finding the pets is complete is to call a method from within the Callback for the findInBackground call that will handle the newly found Pet ParseObjects. Also remember to handle if the query fails either by finding no objects or some failure in connection / timeout.
just calling pet.pin() or pet.pinInBackground(); you can save a parseObject in local storage , to query objects in local storage you need set query.fromPin(true)
https://parse.com/docs/android/guide#objects-the-local-datastore
"done" method fires when the background task ends.
In detail problem is I am Using parse.com as backend and I am trying to get text data into my app i have created class on parse.com and in my app also.
this is my class code from app to get data from parse:
#ParseClassName("WhatsApp")
public class WhatsApp extends ParseObject {
public String gettitle(){
return getString("title");
}
public void settitle(String title){
put("title",title);
}
public String getdes(){
return getString("des");
}
public void setdes(String des){
put("des",des);
}
#Override
public String toString() {
return getString("title")+"\n"+(getString("des"));
}
}
now how i can get 1 column data from parse only title with the help of this class and create a base adapter to design row .can anyone give me example how this can done thanks.
You can restrict the fields returned by using selectKeys method in ParseQuery.
ParseQuery<ParseObject> query = ParseQuery.getQuery("WhatsApp");
query.selectKeys(Arrays.asList("title"));;
List<ParseObject> results = query.find();
The remaining fields can be fetched later by calling one of the fetchIfNeeded variants on the returned objects:
ParseObject object = results.get(0);
object.fetchIfNeededInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
// all fields of the object will now be available here.
}
});
At some point in my Parse-powered application I'm building a ParseQuery to retrieve a certain amount of data from a table ("class" as Parse calls them).
This class includes Pointers to other classes. So data is not available by default (isDataAvailable() == false). I need to fetch() the data on all those Pointers.
Here is my functionning code:
// Simplified code
new ParseQuery<MyClass>("MyClass").where(...).findInBackground(new FindCallback<MyClass>() {
#Override
public void done(final List<MyClass> objects, final ParseException pe) {
for (final Object object : objects) {
object.fetchIfNeeded();
}
myCustomCallback.objects(objects);
}
});
And here comes my problem: The callbacks in Parse seems to run on UIThread (I tested Looper.getMainLooper().getThread() == Thread.currentThread()).
So I end up with:
I/Choreographer: Skipped X frames! The application may be doing too much work on its main thread.
I know I could use fetchIfNeededInBackground() to avoid that, but then my callback would not run when all the fetches are done.
How to run all fetch actions in background and yet trigger my callback only once they all are done?
I had sort of same problems. I needed to do a lot of stuff before triggering callback.
It is really difficult to handle all those requests and know which one came last.
So my solution was to create async task myself, and work with synchronous parse methods (delete, fetch, save... those without "inBackground" part =) )
new AsyncTask<Void, Void, Object>() {
#Override
protected Object doInBackground(Void... params) {
List<MyClass> objects = new ParseQuery<MyClass>("MyClass").find();
for (final Object object : objects) {
object.fetchIfNeeded();
}
return objects;
}
#Override
protected void onPostExecute(Object objects) {
myCustomCallback.objects(objects);
}
}.execute();
That is general solution for many "nested" calls. Just add them one by one.
But for you, I think "include" method on ParseQuery would be enough.
Something like
new ParseQuery<MyClass>("MyClass").where("")
.include(NAME_OF_THE_OBJECT_IN_PARSE_DB)
.findInBackground(new FindCallback<MyClass>() {
#Override
public void done(final List<MyClass> objects, final ParseException pe) {
myCustomCallback.objects(objects);
}
});
You can check in Parse documentation
I hope this helps.
I am currently having trouble getting a value from an AsyncTask that gets data from a JSON connection. I have looked at a few examples, but mostly I have only seen posting results from AsyncTask.
First I have an object called Dog that only has a String, Name. I am trying to get the Name of the dog from the server.
Using the following code in my oncreate, I start the DogAsyncTask while assing in an URL called n and a Dog d_in.
Dog d_in = new Dog("DogName");
DogAsyncTask task = new DogAsyncTask(d_in);
String n = "www.dog.com";
task.execute(n);
Log.e("Out", d_in.getName());
My AsyncTask is as follows:
private class DogAsyncTask extends AsyncTask<String, Void, String> {
Dog d = null;
DogAsyncTask(Dog d){
this.d = d;
}
ProgressDialog mProgressDialog;
#Override
protected void onPostExecute(String result) {
d.setName(result);
Log.e("Dog", d.getName());
mProgressDialog.dismiss();
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(AsyncTestActivity.this, "Loading...", "Data is Loading...");
}
#Override
protected String doInBackground(String... name) {
//Go to url = name and then gets String below.
String outfromjson = "new dog name"; //This will be a function that gets a name from JSON
return outfromjson;
}
}
I tried using something like
Log.e("Out", task.d.getName());
but I keep getting the default name of the dog which is "DogName". How to I carry values out of AsyncTask?
OK, The thing what is happening here is:
You want to pass Dog as reference (pointers as in C / C++ / Objective-C),
and you want to reflect change in original variable using other variable.
but keep in mind that Java doesn't pass object by reference, Java passes objects by value (only value is transferred, another object is created and assigned value).
So what you can do is you can assign that result-holder object again as a value to the original object.
You can do the following,
Declare and implement an interface in your activity and then use it's methods as a callback from the onPostExecute method.