I am creating a program that fetch the value from online . I have use AsynTask class for background process. i am fetching the some values from web and set value in class variables.My problem is that values are setting in variables in very late. and my execution processed further and find variables values null. How can i check that doInBackground() method is processed completely and values are sets in variable. so that i can use these variables values.
One of the best method is to use a kind of observer design pattern.
So first create an Interface with contain a method (depend on your return value, etc) :
public interface OnTaskCompleted{
void onTaskCompleted(String xml);
}
Then you need to implement this interface to your activity wich instantiate your asynctack, see:
public class MainActivity extends SherlockFragmentActivity implements OnTaskCompleted
Then to finish, you gonna pass the instance of MainActivity (wich by polymorphisme is also OnTaskCompleted) to your asyntask. Here my asyntask class handler is named XMLParser
public class XMLParser {
private OnTaskCompleted listener;
public XMLParser(OnTaskCompleted mainActivity, String url){
getXMLFromURL(mainActivity,url);
}
[......]
//here when the work is done you call the OnTaskComplete Method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//CALL HERE
listener.onTaskCompleted(result);
}
}
I hope it'll help you. Works like a charm for me.
Related
can someone tell me, how do get a Stringvalue from a thread to the mainActivity?
i have a thread like this:
public class XMLHandler extends DefaultHandler {
XMLDataCollected data = new XMLDataCollected();
......
......
public String getInformation() {
String information = "";
if (data.getData().equals("residential")) {
information = "Stadt";
}
return information;
}
}
in the mainActivity i tried to set the value into a textview like this:
textView.setText(xmlHandler.getInformation());
i does not work after all. what i am doing wrong? any solutions and advices? thanks in advance
If you have a SeparateThread class then you need to create one Interface say
public interface FetchValueListener{
public void sendValue(String value_to_send);
}
And your acctivity will be implementing this interface and thus sendValue(value_to_send) method will be added to your activity.
Next step would be when you create the object of the THread class then you need to pass the object of that interface in the paramater as follows:
public class myThreadClass{
FetchValueListener mllistener;
myThreadClass(FetchValueListener listenerObj){
mllistener=listenerObj;
}
}
Now when you want to send some value to the activity from thread you can just simply call
mllistener.sendValue(value_you_wan_to_send);
And inside your actiivty you will get the value in the sendValue() method..
In that method you need to post the data to runnable using the handler so that you can make changes to the UI like setText etc.....
If you directly try to set the value of text view in that method you will get an exception.
Ok so now I have Class A that contains some spinners that values will be populated by Class B that extends AsnycTask which grabs the spinner values from a web service. In class B i manage to retrieve the values, showing in a Toast. The problem now is how do I pass those spinner values back to Class A?
I've tried
Can OnPostExcecute method in AsyncTask RETURN values?
by passing Class A to Class B and store the value in a public variable of Class A like below
#Override
protected void onPostExecute(String result)
{
classA.classAvariable = result;
}
However whenever I try to read the classAvariable i always get a NullPointer Exception.
Seems like the variable was never assigned with the result.
For readability purpose I needed to seperate Class B instead of using as an inline class.
Any ideas my fellow Java programmers?
Problem here is that when you execute your AsynchTask, its doInBackground() methode run in separate thread and the thread that have started this AsynchTask move forward, Thereby changes occur on your variable by AsynchTask does not reflect on parent thread (who stated this AsynchTask) immediately.
Example --
class MyAsynchTask
{
doInbackground()
{
a = 2;
}
}
int a = 5;
new MyAsynchTask().execute();
// here a still be 5
Create a interface like OnCompletRequest() then pass this to your ClassB constructor and simply call the method inside this interface such as complete(yourList list) in the method of onPostExecute(String result)
You can retrieve the return value of protected Boolean doInBackground() by calling the get() method of AsyncTask class :
E.g. you have AsyncTask class as dbClass like
dbClass bg = new dbClass(this);
String Order_id = bg.execute(constr,data).get();
Here I am passing constr as URL and data as string of inputs to make my class dynamic.
But be careful of the responsiveness of the UI, because get() waits for the computation to complete and will block the UI thread.
I'm trying to make an application that uses Asynctask. Particularly, I want to make different http petitions with different JSON in different activities without the activity being frozen while the communication is done.
At first I thought to use asynctask as a private inner class in those activities, but I saw that they share a lot of code. So I thought to make a single class and play with broadcast receivers as I need to monitorize when I receive the result of the http petition, and isn't good to interfere with activity directly in the onPostExecute while in a different class.
What I want to know is, what is more efficient and better practice. Make a class that has the shared code and extends asynctask, then doing inner classes for each activity that extends that one or make a single asynctask that sends broadcast and receive them with each activity when needed.
Excuse my poor english, if needed I'll try to specify more clearly.
Thanks in advance
Background
What I want to know is, what is more efficient and better practice. Make a class that has the shared code and extends asynctask, then doing inner classes for each activity that extends that one or make a single asynctask that sends broadcast and receive them with each activity when needed.
I'm unclear as to why these are your only two options. Create a single AsyncTask, such as JsonPetitionTask, then push a new JsonPetitionTask.Data object. This object would contain your URL, your JSON, and any other data you need.
Setting up the AsyncTask
Something like this:
public class JsonPetitionTask extends AsyncTask<JsonPetitionTask.Data, Integer, Boolean> {
protected Boolean doInBackground(JsonPetitionTask.Data... args) {
for (int i = 0; i < args.length; i++) {
JsonPetitionTask.Data data = args[i];
// Send your JSON; check for errors, and return false if needed.
if (isCancelled()) break;
}
return true;
}
protected void onProgressUpdate(Integer... progress) {
// Show progress?
}
protected void onPostExecute(Boolean result) {
// result is your success true/false.
}
public static class Data {
public String jsonContent;
public String petitionUrl;
public Data(String content, String url) {
jsonContent = content;
petitionUrl = url;
}
}
}
Calling the JsonPetitionTask
Then you can call it like so:
JsonPetitionTask.Data data = new JsonPetitionTask.Data(myJSON, myURL);
new JsonPetitionTask().execute(data);
And voilĂ , you've executed your AsyncTask using only one class with no receivers.
Implementing a callback
Now, if you want to register a callback (something to execute that is specific to the calling code), that's a bit trickier. If this is part of what you're looking for, I'll be glad to edit this post and explain it.
To add a callback, we can use the Runnable class to execute some code after the job is done.
Firstly, we need to add a new field in the Data inner class:
public Runnable callback;
Next, before we call execute(), we need to add a new callback to our data object.
data.callback = new Runnable() {
public void run() {
// Whatever code you want to run on completion.
}
};
Third, in the JsonPetitionTask class, we need a list of things to run:
private ArrayList<Runnable> mRunnables = new ArrayList<Runnable>();
Make sure, in each iteration of the doInBackground() loop, that you do mRunnables.add(data.callback);.
Lastly, in onPostExecute(), we need to call this:
protected void onPostExecute(Boolean result) {
for (Runnable r : mRunnables)
if (r != null) r.run();
}
I do realize I didn't send result to the Runnable, however I didn't feel like implementing a new Runnable type just to handle that. If you need this, I guess that's a bit of homework for you!
The way I found the best is just simply create public class that extends AsyncTask and then you just override onPostExecute function in every activity you use it.
Example:
MyDataTask dataTask = new MyDataTask() //you can add your parameters in class constructor
{
#Override
protected void onPostExecute(Object result) //replace Object with your result type
{
MyActivity.this.doStuff(result); //use result in current activity
}
};
you can also create some custom functions to set private variables in datatask
dataTask.AddParam("user", username);
dataTask.AddParam("pass", pass);
and then just execute it with your args...
dataTask.execute(myArgs);
I have used Async task class as single class. And for every Webservice call i have used unique IntentFilter to Broadcast response.
Put that Broadcast receiver in every class. You have perfect solution.
Its working well.
I am using async task as below. But I need to be able to call a different function inside onPostExecute based on different activities I am using the class below. For example when an activity loads I will use the below class as it is but when user clicks on a listitem in the activity I want to use the same class below but the callback functon needs to be different? Is there a way to do this in android.
class PerformOPTask extends AsyncTask<Void, String, ServerOutput> {
// connector=new JSONConnector();
Connector connector;
String curUrl;
ServerOutput currentSO;
PerformOPTask(String url,ServerOutput serverOutput){
//connector = new UnitTestConnector();
connector = new JSONConnector();
curUrl=url;
currentSO=serverOutput;
}
#Override
protected ServerOutput doInBackground(Void... params) {
return connector.getData(URLUtils.getFormattedUrl(curUrl),currentSO);
}
#Override
protected void onPostExecute(ServerOutput output) {
displayData(output);
Toast.makeText(BaseFragmentActivity.this, "Done!", Toast.LENGTH_SHORT).show();
}
}
You can add an interface in the adapter which contains an onComplete method or something like that. You can then add the interface in your constructor of your AsyncTask. Like this:
public interface OnTaskCompleteListener {
void onComplete(ServerOuptput output);
}
In your onPostExecute() you can then just call the onComplete()
You can pass some Object to PerformOPTask(maybe Activity instance for example, or some enumaration, or boolean if there are 2 options) which will identify who uses this class and which function to call on onPostExecute().
Both answer are right, you need to inject a dependency for that. And personnaly I prefer to inject them inside the constructor of my own subclasses of AsyncTasks.
The advantages of the solution of #Maria Neumayer is that it will provide something more generic, more abstract and more extensible than using the solution of #narek.gevorgyan
I have two AsyncTasks as inner classes in my Activity. One returns an ArrayList in doInBackground and asigns a ListAdapter to it on postExecute. The other AsyncTask returns a StringArray and sets some TextViews.
On Rotation everything is gone, also the layout changes on Rotation.
I'd like to have access to the results of the doInBackground-Methods. If I had access I could just simply save the variables in onSaveInstanceState and reasign the values manually.
You can access the results of doInBackground in onPostExecute.
Simply change your class to:
public class YourTask extends AsyncTask<Void, Void, ObjectYouWantToReturn> {
#Override
protected ObjectYouWantToReturn doInBackground(Beneficiary... params) {
ObjectYouWantToReturn obj = new ObjectYouWantToReturn();
//... do your stuff
return obj;
}
#Override
protected void onPostExecute(ObjectYouWantToReturn result) {
//there you go, here you have the results from doInBackground
}
}
Shared preferences is solution of your problem i think.
revise the link given below.
http://developer.android.com/guide/topics/data/data-storage.html#pref
http://thedevelopersinfo.com/2009/11/25/getting-sharedpreferences-from-other-application-in-android/