public class Calculate extends AsyncTask<Void, Integer, Integer> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(Void... arg0) {
int a = 1;
int b = 2
return a+b;
}
#Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
my app use asynctask class (below), and a function to call this class,
my question is how to know when this class is finished ? every time i check, its always Running !
In your onPostExecute(...) method, you could simply call a method in your caller Activity which would set a boolean terminated_activity to true. You can do this in several ways, most probably the easiest ones are Intents combined with a Handler, or a local BroadcastReceiver.
An example on Handlers and Intents is in an answer I posted today in other question, here.
A nice explaination on local BroadcastReceivers is here.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Directly from the docs
Related
So as the title probably suggests - I've done a lot of research on the topic, but I am still confused and unable of achieving what I want.
In very simplified scenario, I have a LoginActivity in which is method boolean validateUserInput(String mail, String password) and I want to do the check input in the separate thread. I suppose I will extend it in the future to do the log-in itself as well (http request). Naturally I would like to get boolean value if the operation was successful or not - and in the process of operation I want to show progressbar dialog.
Make a thread, run the code, return its result, show the progress bar in a meantime, piece of cake right?
Should I use asynctask or runnable? How do I do this so I do not block the UI thread?
This is code I tried to use in LoginActivity:
new Thread(new Runnable() {
#Override
public void run() {
mUserInputValidated = validateUserInput(inputEmail.getText().toString(), inputPassword.getText().toString());
}
}).start();
if(mUserInputValidated)
{
attemptUserLogin(inputEmail.getText().toString(), inputPassword.getText().toString());
}
I also tried asynctask approach, but ended up with various errors since I started progress dialog in onPreExecute() and ended it in onPostExecute(), using reference like LoginActivity.this where was the problem with memory leak which I was also unable to fix?
I assume this is pretty usual scenarios, since almost every app use it, so - what are common approaches? How do I fix my code?
You have to use asynctask this will take the work off from main-thread and place it on background thread once the work is done
This is a sample that shows how to do it
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// might want to change "executed" for the returned string passed
// into onPostExecute() but that is upto you
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
Reference
I have been trying to change textView after I'm done networking in an another thread with AsyncTask. I've tried countless solutions, but none have worked so far.
The only way I was able to achieve my goal was to use .get(), but it stops the UI thread for a while, and that's something I don't want.
I've also tried using the AsyncTask as an outer class, and using a wrapper class in the middle.
So my question here is, what is the easiest way to get hold of a variable used in doInBackground() and onPostExecute(), without freezing the main thread?
Here is a way to do it. You can give a callback in parameter of your async task, do whatever you want and them get the value back from the async task.
Callback interface :
public interface AsyncTaskCompleteListener<T> {
public void onTaskComplete(T result, int number);
}
AsyncTask :
public class LoadURL extends AsyncTask<String, Process, String> {
private AsyncTaskCompleteListener<String> callback;
public LoadURL(AsyncTaskCompleteListener<String> cb) {
this.callback = cb;
}
protected void onPreExecute() {}
protected String doInBackground(String... arg0) {
// do something
return content;
}
protected void onPostExecute(String content) {
if (callback != null)
callback.onTaskComplete(content,number);
}
}
Activity :
public class LoginActivity extends Activity implements AsyncTaskCompleteListener<String> {
#Override
protected void onCreate(Bundle savedInstanceState) {
LoadURL loadUrl = new LoadURL(LoginActivity.this);
loadUrl.execute(...);
}
#Override
public void onTaskComplete(String result, int number) {...}
}
in onTaskComplete, you can easily modify your TextView
Just update the UI in the following code inside the AsyncTask:
#Override
protected void onPostExecute(Int result) {
textView.setText(result.toString());
}
Check this link if you need extra help.
You should return the variable from doInBackground(). Framework will make sure you will get the returned value in onPostExecute().
onPostExecute runs on the UI thread so you should be able to refresh any UI element here.
I have a problem regarding Async task
Async from android
Using 2 activities "A" and "B"
by entering a word to search from the url and and store value in DTO and then fetching values from getter and setter.
My complication is that i have implemented async in my activity "B" and that activity is fetching value from same DTO.
Problem is that how my post know that do in background have fetched value from DTO and DTO have fetched value from internet...in case of slow internet connection.
I m sending intent from "A" to "B" and showing the results on "B"
PROBLEM:
1. If i remove async then app shows black page and also freezes (in case of slow connection only) but data is displayed
2. If i use aync then sometimes progress dialog show for long time and inspite of knowing that data is already displayed in UI
code links https://www.dropbox.com/s/p27rpokz68sryv3/SearchData.java
https://www.dropbox.com/s/rm3i52djiay327u/SearchData_DTO.java
https://www.dropbox.com/s/2hpufx2a12480on/Search.java
Pls suggest me the possible solution for this
Regards
You need to listen for asyntask complete listener, For that let your activity A impliment interface and call that method from Activity B,s Asyntask,s onpostexecute method
Thus your activity A will come to know that B has finished his task and you can do next thing..
Hope this helps
public interface AsyncTaskCompletedListener {
public void OnResultSucceeded(String result);
}
public class LoginAsyncTask extends AsyncTask<String, Void, String> {
AsyncTaskCompletedListener mAsyncTaskCompletedListener;
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
mAsyncTaskCompletedListener.OnResultSucceeded(result);
}
}
Here is the interface Let Activity A impliment this and from Activity invoke this from onpostexecute
From Activity A
LoginAsyncTask customloginasync = new LoginAsyncTask(getActivity(),
FATCH_USER_LIST, arglist);
customloginasync.execute();
customloginasync.setOnResultsListener(new AsyncTaskCompletedListener() {
#Override
public void OnResultSucceeded(String result, int asyncTaskNo) {
Logger.logInfo("CustomLogin data=========" + result);
ParseAvailableUserData(result);
}
});
I am writing a very simple unit test case for my Android project, the test case simplely execute a AsyncTask which does network operation in background. I am extending AndroidTestCase class for my test case:
public class MyTest extends AndroidTestCase{
//use CountDownLatch to perform wait-notify behavior
private CountDownLatch signal;
#Override
public void setUp() throws Exception{
super.setUp();
//I use CountDownLatch to perform wait-notify behaviour
signal = new CountDownLatch(1);
}
#Override
public void runTest() throws Exception{
String params = "some params";
//MyAsyncTask does the networking tasks
new MyAsyncTask().execute(params);
//wait until MyAsyncTask is done
try {
signal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class MyAsyncTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
//Do networking task e.g. access a remote database
}
#Override
protected void onPostExecute(String result){
super.onPostExecute(result);
//this never get called when run this test case, why?
Log.i("Debug","post execute");
signal.countDown();
}
}
}
As you see above, I am using CountDownLatch to perform wait-notify behavior.
After MyAsicTask starts, I invoke signal.await() to wait for MyAsyncTask to finish.
In onPostExecute() callback of MyAsyncTask, I call signal.countDown() to notify that the task is done.
But when I run this test case, the onPostExecute is never called, why & how to fix it?
========Update==========
After I added Thread.sleep(30*1000) as the last line in runTest(), I can see more logs from network operations. It proves that the teardown() is invoked before my network operation finished. I did nothing in tearDown(), android test framework. invokes it automatically.
Seems my wait-notify by using CountDownLatch is not working... Why?
Since I had the same problem... here's what solvede it for me.
Instead of letting the class extend AndroidTestCase I let it extend InstrumentationTestCase.
Then i start the asyncTask like this:
runTestOnUiThread(new Runnable()
{
#Override
public void run()
{
startAsyncTask();
}
});
Be sure that your doInBackground method is not the reason this problem. Try this sample task. And share the log result please.
private class MyAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("Debug", "onPreExecute");
}
#Override
protected String doInBackground(String... params) {
Log.i("Debug", "doInBackground");
return "operation finished";
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i("Debug", "onPostExecute");
signal.countDown();
}
#Override
protected void onCancelled() {
super.onCancelled();
Log.i("Debug", "onCancelled");
}
}
Edit: I wondered that there may be a problem while working with AndroidTestCases and AsyncTasks. I just copied your code to my project and tested it with an AsyncTask(see my task above). On every launch after doInBackground, onPostExecute method is called successfully. I simulated a long running task with sleep 2 minutes, and that also entered to onPostExecute method. And tearDown method invoked after onPostExecute.
So, your problem here is probably a loop inside your doInBackground method. Or it is cancelled somehow and task's onCancelled method invoked.
I think your network operation is very time consuming process so it takes so long time that why its can not called onPostExecute() method.
The onPostExecute() is supposed to be run in the caller thread of execute(). If that thread becomes suspended by calling something like signal.await(), the onPostExecute() won't be able to run. So you cannot have signal.await() after calling execute().
For some reason my onPostExecute() is not called after my AsyncTask finishes.
My class decleration:
public class setWallpaperForeground extends AsyncTask<String, Integer, Boolean>
My onPostExecute():
protected void onPostExecute(Boolean result)
Everything works fine, my doInBackground() completes successfully and returns a Boolean but then it just finishes.
Thanks
Did you start the task with execute() method? The onPostExecute wouldn't run if you just invoke the doInBackground.
Did you create your AsyncTask on the UI thread? Also add an #Override annotaiton on your onPostExecute() method to make sure you declared it correctly.
Found/Made another nasty mistake:
If your params of onPostExecute(Param param) don't match the one you defined with extends AsyncTask<...,...,Param> and you didn't use the #Override annotation, it will never be executed and you don't get a warning from Eclipse.
Note to myself:
Just always use the #Override annotation and Eclipse will help you.
Another easy way to avoid all named mistakes:
in Eclipse: Right-click in code > Source > Override/Implement Methods
After having the same problem and none of these answers helped me, I found out that my UI thread was blocked (I used a CountDownLatch.await()) and therefore the onPostExecute() method that is supposed to be called by the UI thread was never called.
Made another nasty mistake that can result in this same error. When defining the AsyncTask and calling it, I was not calling execute but was calling doInBackground
new AsyncTask<String,Void,Void>() {
....
}.doInBackground("parameter");
rather than
new AsyncTask<String,Void,Void>() {
....
}.execute("parameter");
I have faced the same problem. None of the above solutions worked for me. Then i figured out the problem maybe it helps someone else .
In UI thread i call the following codes:
public class XActivity ...{
onCreate(){
....
new SaveDrawingAsync(this).execute();
while(true)
{
if(MandalaActivity.saveOperationInProgress){
continue;
}
super.onBackPressed();
break;
}
...
}
}
My AsyncTask class definition :
public class SaveAsync extends AsyncTask<Object, Void, Void> {
#Override
public Void doInBackground(Object... params) {
saveThem(); // long running operation
return null;
}
#Override
public void onPostExecute(Void param) {
XActivity.saveOperationInProgress = false;
}
#Override
public void onPreExecute() {
XActivity.saveOperationInProgress = true;
}
}
in the above code onPostExecute is not called. It is because of an infinite loop after asynctask execution .
asynctask and inifinite loop both waits eachother to finish. Thus the code stucks!
The solution is changing the design!
I had the same behaviour, and the cause was that I have been posting a lot of messages as a progress inside doInBackground with following code:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// .. some UI updates
}
});
this must have overloaded main thrad message queue, and caused long delay before onPostExecute would get called. The solution was to post only once every second.
For me it was user error. I was ending the AsyncTask by invoking cancel(true) on it and not reading the documentation closely enough to know that onPostExecute is not called in this case, onCancelled is.