I have the following generally happening for an AsyncTask:
private class backgroundTask extends AsyncTask<Object, Object, Object> {
protected void onPreExecute() {
this.dialog.setMessage("Doing stuff...");
this.dialog.show();
}
#Override
protected Object[] doInBackground(Object... params) {
// stuff happens here
ResultsObject results = new ResultsObject(processValue);
Object[] values = new Object[2];
values[0] = "STATUS STRING";
values[1] = results;
return values;
}
protected void onPostExecute(Object... result) {
Log.d("actions", "onPostExecute");
if (this.dialog.isShowing())
this.dialog.dismiss();
}
}
However, onPostExecute does not appear to be getting triggered. I can validate that everything up until doInBackground makes a return call is getting executed. This has to be something obscenely simple that I'm missing here, but I'm stumped. I have other AsyncTasks in this same project, and I have no trouble with them reaching onPostExecute.
You're overloading onPostExecute method and it doesn't get used. Use this:
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
Log.d("actions", "onPostExecute");
if (this.dialog.isShowing())
this.dialog.dismiss();
}
Note the #Override annotation, it comes very useful in times like this. It will show an error if the method you are trying to override doesn't exist.
Related
private class exampleTask extends AsyncTask<String, Void, SomeResult>{
#Override
protected SomeResult doInBackground(String... urls) {
SomeResult res ;
someMethod(new CallBack<T>(){
#Override
public void onResponse(SomeResult something) {
res = something ;
}
#Override
public void onFailure() {
//
}
});
return res ;
}
#Override
protected void onPostExecute() {
//
}
}
Please I want to assign "res" to "something" witch is inside the callback in the onResponse method. In this code it's impossible to assign res inside the onResponse method.
Please any help is welcome.
Thank you :)
my original code : I'd like to assign "url" ;
private class GetBeaconInfosTask extends AsyncTask<String, Void, Call<Url>> {
Url url ;
#Override
protected Call<Url> doInBackground(String... urls) {
ProxService service = ProxService.Factory.makeProxService(ProxService.ENDPOINT);
return service.getUrlDetails(urls[0]);
}
// onPostExecute return the results of the AsyncTask.
#Override
protected void onPostExecute(Call<Url> call) {
call.enqueue(new Callback<Url>() {
#Override
public void onResponse(Call<Url> call, Response<Url> response) {
url = response.body();
}
#Override
public void onFailure(Call<Url> call, Throwable t) {
//
}
});
if(url == null){
Log.i("url is null", "url is null !!!!! ....");
}
else {
setShopLogo(url.icon) ;
setShopName(url.title);
setDescription(url.description);
setlongUrl(url.longUrl); }
}
}
Assuming the problem is due to the variable having to be declared as final to be accessible from the callback, you could move it out of the doInBackground method and declare it as a member of the exampleTask class.
private class exampleTask extends AsyncTask<String, Void, SomeResult>{
SomeResult res;
#Override
protected SomeResult doInBackground(String... urls) {
someMethod(new CallBack<T>(){
#Override
public void onResponse(SomeResult something) {
res = something ;
}
#Override
public void onFailure() {
//
}
});
return res ;
}
#Override
protected void onPostExecute() {
//
}
}
While this should answer your question, it's hard to tell what you're trying to achieve. Further to #Gabe Sechan's answer - your variable may never get assigned, or it would be assigned after a certain length of time. Ordinarily you would carry out work in the doInBackground and when that has been carried out onPostExecute is called, but in your case you'll likely have onPostExecute called before hitting the onRespons of your callback. I don't think it's good practice to use a Callback in doInBackground the way you're trying to use it.
If you have other work that needs to be carried out asynchronously in doInBackground, do that, but move the someMethod call to onPostExecute and do whatever you need to do with res in there.
private class exampleTask extends AsyncTask<String, Void, SomeResult>{
SomeResult res;
#Override
protected SomeResult doInBackground(String... urls) {
// background work
}
#Override
protected void onPostExecute() {
someMethod(new CallBack<T>(){
#Override
public void onResponse(SomeResult something) {
res = something ;
// DO STUFF WITH RES HERE AFTER IT'S BEEN ASSIGNED OR YOU WON'T HAVE ACCESS TO IT
}
#Override
public void onFailure() {
//
}
});
}
}
EDIT: Now that the question contains real code, I can provide a flow that should work for you. Note in the code I pasted above the comment in onResponse stating this is where you should have the code that uses the variable. Look at onResponse below for example using your code. The value doesn't exist until you get to the onResponse callback method, so you have to wait until it gets there. Your code below is being carried out before onResponse so the variable is inevitably null. The code isn't executed sequentially. I'd suggest studying callbacks to fully understand them :)
private class GetBeaconInfosTask extends AsyncTask<String, Void, Call<Url>> {
Url url ;
#Override
protected Call<Url> doInBackground(String... urls) {
ProxService service = ProxService.Factory.makeProxService(ProxService.ENDPOINT);
return service.getUrlDetails(urls[0]);
}
// onPostExecute return the results of the AsyncTask.
#Override
protected void onPostExecute(Call<Url> call) {
call.enqueue(new Callback<Url>() {
#Override
public void onResponse(Call<Url> call, Response<Url> response) {
url = response.body();
setShopLogo(url.icon) ;
setShopName(url.title);
setDescription(url.description);
setlongUrl(url.longUrl); }
}
#Override
public void onFailure(Call<Url> call, Throwable t) {
//
}
});
}
You seem to not understand the purpose of a callback. A callback is called at some point in the future. Not now. So the function that sets up the callback won't be assured its called by the end of its execution. What you want will never work. Instead, you should execute whatever you wanted to do in onPostExecute with that value in the body of the callback.
I am trying to return a boolean from my method checkInvited(). This method contains a class which extends AsyncTask<Void,Void,String>. This is the full method
public boolean checkInvited(String player_id){
final String g_id = game_id;
final String fr_id = player_id;
class CheckInvited extends AsyncTask<Void, Void, String>{
boolean invited;
ProgressDialog loading;
#Override
protected void onPreExecute(){
super.onPreExecute();
loading = ProgressDialog.show(InviteFriends.this,"Checking Invite Status","Please Wait...",false,false);
}
#Override
protected void onPostExecute(String s){
super.onPostExecute(s);
loading.dismiss();
JSON_STRING = s;
if (s.trim().equals("0")){
invited = false;
} else {
invited = true;
}
}
#Override
protected String doInBackground(Void... params){
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put(Config.KEY_INVITES_GAME_ID, g_id);
hashMap.put(Config.KEY_INVITES_PLAYER_ID, fr_id);
RequestHandler rh = new RequestHandler();
String s = rh.sendPostRequest(Config.URL_CHECK_INVITED, hashMap);
return s;
}
}
CheckInvited ci = new CheckInvited();
ci.execute();
return ci.invited;
}
This method calls a predefined method of sendPostRequest() which contacts the mySql database through php. My problem is getting the checkInvited() method to return true or false. Currently it will only return false when I know at least one of the results should be true.
Thanks in advance for any help.
It only returns false because async task runs in a seperate thread and might take long to execute depending on carious factors. You are returning value even before async task completes.
I would suggest calling a method which requires the true or false from onPostexecute, as onPostExecute runs after doInBackground completes.
I have a list of objects with certain states
private ArrayList<MyObjectMap> MyList;
MyList = new ArrayList<>();
Every object in that list contains a certain value, that can be updated via the internet (say active, inactive). To update each element I use an AsyncTask, so something like this
for(int i=0;i<MyList.size();i++) {
new myAsyncTask(MyList.get(i)).execute();
}
Later, to update the List in my GUI, I use notifyDataSetChanged for the BaseAdapter of my list.
Is this somehow possible? How do I need to change my AsyncTask?
public class myAsyncTask extends AsyncTask<Void, Void, Void> {
private MyObjectMap myObject;
protected void onPreExecute() {
}
public myAsyncTask(MyObjectMap mom) {
myObject = mom;
}
#Override
protected Void doInBackground(Void... voids) {
myObject.updateThisItem();
return null;
}
}
Pass the full arrayList and baseAdapter object to the asyncTask. and update the current element of arrayList and then make notifyDatasetchanged()
public class MyAsyncTask extends AsyncTask<Void, Void, Void>
{
private ArrayList<MyObjectMap> myList;
private BaseAdapter baseAdapter;
private int position;
public MyAsyncTask(ArrayList myList, int position, BaseAdapter baseAdapter) {
this.myList = myList;
this.position = position;
this.baseAdapter = baseAdapter;
}
protected void onPreExecute()
{
}
#Override
protected Void doInBackground(Void... voids)
{
myList.get(position).updateThisItem(); //or
/*
MyObjectMap mop = myList.get(position);
mop.updateThisItem();
myList.remove(position);
myList.add(position, mop);
*/
return null;
}
protected void onPostExecute()
{
baseAdapter.notifyDataSetChanged();
}
}
you can update ui components in asyncTask in both onPreExecute and onPostExcute...
#Prassana has already shown you how to pass objects to AsyncTask by using a constructor, but there is another elegant way to do it, by altering the AsyncTask class type paramers. If I wanted to pass an ArrayList< String> to AsyncTask, and receive an ArrayList< Integer> back, the class layout would look something like this.
// notice the return type and parameter type
public class myAsyncTask extends AsyncTask <ArrayList<String>, Void, ArrayList<Integer> {
...
// Make sure this method receives and returns the correct types.
// the params are specified when you make the call to execute the asynctask and
// are accessed in a usual varargs way (like an array).
#Override
public ArrayList<Integer> doInBackground(ArrayList<String>... params) {
...
// onPostExecute takes the ArrayList returned by doInBackground
#Override
public void onPostExecute(ArrayList<Integer> result) {
// do something with your newly acquired ArrayList<Integer>
Note that this is the main structure, just to give you an idea. I cannot garauntee that this is typo-less code. Good luck!
public class myAsyncTaskextends AsyncTask<Object, Void, Void> {
private MyObjectMap myObject;
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Object... voids) {
myObject = (MyObjectMap)param[0];
myObject.updateThisItem();
return null;
}
}
when we execute asyn task use this code to send object
Asyntask.execute(loginRequestBean);
inside background method you can get object like this
#Override
protected Object doInBackground(Object... params) {
Object responseObject = null;
try {
Object object = params[0];
if (object instanceof LoginRequestBean) {
//login webservice
} else if (object instanceof RegisterBean) {
//registration webservice
}
}
Just to start this isn't a question I need an answer too. But I think it would be an interesting way of making code cleaner.
In some code I am writing Ive built a module for retrieving HTTP requests on a new thread and then returning the result to the main thread using a callback.
Code example:
public interface MyCallback {
void Callback_done(String Data);
}
public void HTTP_process(String get_vars, List<NameValuePair> post_vars,MyCallback callback){
Task = new GET_Task();
Task.get_vars = get_vars;
Task.post_vars = post_vars;
Task.callback = callback;
Task.execute();
}
public class GET_Task extends AsyncTask<String, Integer, String> {
public MyCallback callback;
public String get_vars="";
public List<NameValuePair> post_vars = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
//displayProgressBar("Downloading...");
}
#Override
protected String doInBackground(String... params) {
//CODE HERE
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
callback.Callback_done(result);
}
}
Then to use the above "library":
Globals.mData_Handler.HTTP_process("",null,new Data_Handler.MyCallback() {
public void Callback_done(String Data) {//Callback code here
}
});
When I say shorthand I want to be able to type this instead:
Globals.mData_Handler.HTTP_process("",null,new ^{//Callback code here
});
I know this is how objective C handles callbacks, is there a way to setup things like this in java? Using custom short hand expressions?
Use Java 8 and you get lambda expressions
Globals.mData_Handler.HTTP_process("",null, (String data) -> {
//Callback code here
});
If you're only doing a one-liner you can even omit the braces:
Globals.mData_Handler.HTTP_process("",null, (String data) -> log.info(data));
Of course, the above can also be written using Java8 method references:
Globals.mData_Handler.HTTP_process("",null, log::info);
I am trying to unzip a folder using Android's AsyncTask. The class (called Decompress) is an inner class of Unzip where Unzip itself is a non-Activity class. The pseudo-code is:
public class Unzip {
private String index;
private String unzipDest; //destination file for storing folder.
private Activity activity;
private boolean result; //result of decompress.
public void unzip(String loc) {
Decompress workThread = new Decompress(loc, activity);
workThread.execute();
if(unzip operation was successful) {
display(index);
}
//Class Decompress:
class Decompress extends AsyncTask<Void, Integer, Boolean> {
private ProgressDialog pd = null;
private Context mContext;
private String loc;
private int nEntries;
private int entriesUnzipped;
public Decompress(String location, Context c) {
loc = location;
mContext = c;
nEntries = 0;
entriesUnzipped = 0;
Log.v(this.toString(), "Exiting decompress constructor.");
}
#Override
protected void onPreExecute() {
Log.v(this.toString(), "Inside onPreExecute.");
pd = new ProgressDialog(mContext);
pd.setTitle("Unzipping folder.");
pd.setMessage("Unzip in progress.");
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
Log.v(this.toString(), "Showing dialog and exiting.");
pd.show();
}
#Override
protected Boolean doInBackground(Void... params) {
//unzip operation goes here.
unzipDest = something; //unzip destination is set here.
if(unzip operation is successful) {
result = true;
index = url pointing to location of unzipped folder.
} else {
result = false;
}
}
#Override
protected void onPostExecute(Boolean result) {
if(result) {
if(pd != null) {
pd.setTitle("Success");
pd.setMessage("folder is now ready for use.");
pd.show();
pd.dismiss();
pd = null;
Log.v(this.toString(), "Unzipped.");
index = unzipDest + "/someURL";
Log.v(this.toString(), "index present in: " + index);
}
} else {
pd = ProgressDialog.show(mContext, "Failure", "Cannot unzip.");
pd.dismiss();
}
}
}
Problems I am facing:
1. The value of unzipDest and index, updated in doInBackground, remain null to Unzip and all its objects. How can I ensure that the values remain updated?
2. I know that doInBackground occurs in a thread separate from the main UI thread. Does that mean that any values updated in the new thread will be lost once that thread returns?
How can I ensure that the values remain updated?
They will be updated since they are member variables. However, since AsyncTask is asynchrounous, they might not be updated yet when you check them. You can use an interface to create a callback when these values are updated. This SO answer covers how to do this
Does that mean that any values updated in the new thread will be lost once that thread returns?
No they shouldn't be "lost". They probably just haven't been changed in the AsyncTask when you check them.
Since this isn't your actual code I can't see when you are trying to access them but you can use the interface method or call the functions that need these values in onPostExecute(). You also can do a null check before trying to access them. It just depends on the functionality and flow that you need as to which is the best way. Hope that helps.
Edit
In the answer I linked to, you tell the Activity that you will use that interface and override its method(s) with implements AsyncResponse in your Activity declaration after creating the separate interface class
public class MainActivity implements AsyncResponse{
then, in your Activity still, you override the method you declared in that class (void processFinish(String output);)
#Override
void processFinish(String output){ // using same params as onPostExecute()
//this you will received result fired from async class of onPostExecute(result) method.
}
then this is called in onPostExecute() when the listener sees that it is done with delegate.processFinish(result); delegate is an instance of AsyncResponse (your interface class)
public class AasyncTask extends AsyncTask{
public AsyncResponse delegate=null;
#Override
protected void onPostExecute(String result) {
delegate.processFinish(result);
}
Interface example taken from linked answer above and adjusted/commented for clarity. So be sure to upvote that answer if it helps anyone.