How to do something after all asynchronous tasks finished? - android

I'm using AsyncTask to download some files, and want to do something after all tasks finished.
Is there any easy way to do this?

Keep track of how many async tasks you have running and do something when the total is 0.
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
public int numOfTasks = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void addTask(){
numOfTasks++;
}
public void removeTask(){
numOfTasks--;
}
public void allTasksComplete(){
if(numOfTasks ==0){
//do what you want to do if all tasks are finished
}
}
class RequestTask extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... uri) {
String responseString = "";
return responseString;
}
#Override
protected void onPreExecute()
{
addTask(); // adds one to task count.
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
removeTask(); // subtracts one from task count.
allTasksComplete(); // checks to see if all tasks are done... task count is 0
}
}
}

AsyncTask has a callback method name onPostExecute. It will be execute when the background task finish.

You can use onPostExecute() callback when Asyn task finishes background processing, In a typical scenarion you would notify the UI (list adapter or UI Activity) that download of the File is finished and UI can refresh or populate the data.
onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
Please have a look at this Android Ref example:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
http://developer.android.com/reference/android/os/AsyncTask.html
Example2:
https://github.com/ashutoshchauhan13/TwitterFeedApp/blob/master/TwitterFeedApp/src/com/sixthsense/twitterfeed/ui/TwitterFeedActivity.java

Related

Why doesn't AsyncTask executes when the execute method is called using an instance but without the instance works fine? [duplicate]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I don't want to pass any arguments to doInBackground method of the AsyncTask.
So what should be the code like?
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
public class AsyncExample extends Activity{
private String url="http://www.google.co.in";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
new AsyncCaller().execute();
}
private class AsyncCaller extends AsyncTask<Void, Void, Void>
{
ProgressDialog pdLoading = new ProgressDialog(AsyncExample.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.show();
}
#Override
protected Void doInBackground(Void... params) {
//this method will be running on background thread so don't update UI frome here
//do your long running http tasks here,you dont want to pass argument and u can access the parent class' variable url over here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//this method will be running on UI thread
pdLoading.dismiss();
}
}
}
According to AsyncTask, its
AsyncTask<Params, Progress, Result>
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the background computation.
So if you want to pass void in doInBackground just pass void in place of Params.
Example code:
class DownloadLink extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
//Do Your stuff here..
return null;
}
}
And call it as:
new DownloadLink().execute();
Create your AsyncTask class as if you don't want to pass any parameter to doInBackground :
public class LongOperation extends AsyncTask<Void, Void, String> {
public LongOperation(Context context) {
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
and start AsyncTask as without passing any parameter to execute :
LongOperation longOperation = new LongOperation(this);
longOperation.execute();
Why don't you want to pass any arguments to it? You should explain...
This is how it usually works (example):
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
And to execute it you call:
new DownloadFilesTask().execute(url1, url2, url3);
Source: Android docs

Updating a TextView in ASyncTask

After trawling for ages trying to find an understandable solution to my problems i gave up and came here to see if you can help.
My Objective : Update a TextView to count from 1 to 99999 every second without hanging the main thread.
package com.myapp.counter;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBackgroundThread myThread = new myBackgroundThread();
myThread.execute();
}
private class myBackgroundThread extends AsyncTask<Void,Integer,Void>
{
int maxTimer = 99999;
int i = 0;
//Assign the textView in MainActivity to a variable myCounter.
TextView myCounter = (TextView)findViewById(R.id.idCounter);
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
// Toast.makeText(getApplicationContext(),"InBackground",Toast.LENGTH_SHORT).show();
//Tried Toasting a message upon this starting but just threw an error
//Guess because i tried to add a UI component in a background task.
for(int i = 0; i < maxTimer; i++)
{
publishProgress(i);
}
return null;
}
//onProgressUpdate is never firing from publishProgress...
protected void onProgressUpdate(Integer i) {
Toast.makeText(getApplicationContext(),i,Toast.LENGTH_SHORT).show();
//Updatet he counter from 000 to 1,2,3,4 etc.
myCounter.setText(i);
}
protected void onPostExecute(Void result)
{
}
}
public void startTimer(View view)
{
TextView myText = (TextView)findViewById(R.id.textView);
// Toast.makeText(this,"Started...", Toast.LENGTH_SHORT).show();
}
public void stopTimer(View view) {
Toast.makeText(this, "Stopped...", Toast.LENGTH_SHORT).show();
}
}
I cannot seem to see why publishProgress does NOT fire from and I wanted to execute the ASyncTask from an button press.
I have 3 elements 2 buttons startTimer and stopTimer and 1 textview to update in the background.
Many thanks all.
Ty something like this :
protected class InitTask extends AsyncTask<Context, Integer, String> {
// -- run intensive processes here
// -- notice that the datatype of the first param in the class definition matches the param passed to this
// method
// -- and that the datatype of the last param in the class definition matches the return type of this method
#Override
protected String doInBackground(Context... params) {
// -- on every iteration
// -- runs a while loop that causes the thread to sleep for 50 milliseconds
// -- publishes the progress - calls the onProgressUpdate handler defined below
// -- and increments the counter variable i by one
int i = 0;
while (i <= 50) {
try {
Thread.sleep(50);
publishProgress(i);
i++;
}
catch (Exception e) {
Log.i("makemachine", e.getMessage());
}
}
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
Log.i("makemachine", "onPreExecute()");
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this method
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.i("makemachine", "onProgressUpdate(): " + String.valueOf(values[0]));
_percentField.setText((values[0] * 2) + "%");
_percentField.setTextSize(values[0]);
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
Log.i("makemachine", "onCancelled()");
_percentField.setText("Cancelled!");
_percentField.setTextColor(0xFFFF0000);
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i("makemachine", "onPostExecute(): " + result);
_percentField.setText(result);
_percentField.setTextColor(0xFF69adea);
_cancelButton.setVisibility(View.INVISIBLE);
}
}
}

ListView Adapter item Asynktask Stop Issue

I have activity with listview and custom listadapter. EveryItem of List starting a AsyncTask request. Now when i click onback it finish the activity but asynctask isn't finishing. How to finish this all AsyncTask ?
public class MyListAdapter extends ArrayAdapter<String>
{
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
......
if(!status.get(position).isFetch)
{
statusList.get(position).FetchingData=true;
GetRequest request=new GetRequest();
request.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, id);
}
.....
}
class GetRequest extends AsyncTask<String, String, String>
{......}
}
if i pressed backbutton before completing all item task then its finishing activity but not task. How to stop asynctask as activity finish..
You should stop all the tasks manually. Activity lifecycle won't take care of your tasks automatically.
You should manage all the tasks in somewhere(I suggest Activity or Fragment, not in ListView). Gather all the tasks in list and stop'em on onDestroy(or onPause depending your situation).
public MyActivity extends Activity {
private ArrayList<SomeTask> mTasks;
private void startTasks() {
SomeTask task = new SomeTask();
task.execute();
mTasks.add(task);
}
#Override void onDestroy() {
for (SomeTask task : mTasks) {
tasks.cancel(true);
}
}
private class SomeTask extends AsyncTask<Void, Void, Void> {
private MyListItem mItem;
private int mIndex;
public SomeTask(MyListItem item, int index) {
mItem = item;
mIndex = index;
}
protected Long doInBackground(Void... urls) {
// do whatever you want
return null;
}
protected void onPostExecute(Void result) {
// update your adapter here
}
}
}
Sadly, AsyncTask won't just stop even if you call task.cancel(true).
You also have to check if the task is cancelled inside the AsyncTask.
Below is a sample taken from AsyncTask reference page:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Checkout Cancelling a task section for more information.

How to use AsyncTask correctly in Android [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I don't want to pass any arguments to doInBackground method of the AsyncTask.
So what should be the code like?
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
public class AsyncExample extends Activity{
private String url="http://www.google.co.in";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
new AsyncCaller().execute();
}
private class AsyncCaller extends AsyncTask<Void, Void, Void>
{
ProgressDialog pdLoading = new ProgressDialog(AsyncExample.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.show();
}
#Override
protected Void doInBackground(Void... params) {
//this method will be running on background thread so don't update UI frome here
//do your long running http tasks here,you dont want to pass argument and u can access the parent class' variable url over here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//this method will be running on UI thread
pdLoading.dismiss();
}
}
}
According to AsyncTask, its
AsyncTask<Params, Progress, Result>
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the background computation.
So if you want to pass void in doInBackground just pass void in place of Params.
Example code:
class DownloadLink extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
//Do Your stuff here..
return null;
}
}
And call it as:
new DownloadLink().execute();
Create your AsyncTask class as if you don't want to pass any parameter to doInBackground :
public class LongOperation extends AsyncTask<Void, Void, String> {
public LongOperation(Context context) {
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
and start AsyncTask as without passing any parameter to execute :
LongOperation longOperation = new LongOperation(this);
longOperation.execute();
Why don't you want to pass any arguments to it? You should explain...
This is how it usually works (example):
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
And to execute it you call:
new DownloadFilesTask().execute(url1, url2, url3);
Source: Android docs

AsyncTask - after execution, how to update view?

In the onCreate() event of an Activity, I have started an AsyncTask to retrieve Product data from a database. After this has been completed successfully, how can I update the display?
Metacode:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.venueviewbasic);
(..)
new GetProductDetails().execute();
class GetProductDetails extends AsyncTask<String, String, String> {
protected String doInBackground(String... params) {
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// Check for success tag
int success;
try {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id", vid));
(.. retrieve and parse data and set new textview contents ..)
The textviews etc. don't get updated however.
If you want to update the view from async after complete process in then
you can use
protected void onPostExecute(String result)
{
textView.setText(result);
}
But if you want to update data while running background process then use.
For ex...
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));<------
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) { <-------
setProgressPercent(progress[0]);
}
for more detail see this link
Hope this will help you...!
I am guessing the question is more about how to get hold of the UI View if the asyncTask is in a separate file .
In that case you have to pass the context to the Async task and use that to get the view.
class MyAsyncTask extends AsyncTask<URL, Integer, Long> {
Activity mActivity;
public MyAsyncTask(Activity activity) {
mActivity = ativity;
}
And then in your onPostExecute use
int id = mActivity.findViewById(...);
Remember you cannot update the View from "doInBackground" since its not the UI thread.
In your AsyncTask class, add a onPostExecute method. This method executes on the UI thread and can update any UI component.
class GetProductDetails extends AsyncTask<...>
{
...
private TextView textView;
...
protected void onPostExecute(String result)
{
textView.setText(result);
}
}
(The result parameter is the value returned from the doInBackground method of your class.)

Categories

Resources