I admit, I'm new at this whole Android stuff. I am trying to make an app but randomly I get Force close errors and I really don't know why. My application has many activities, none of them finish() when I start a new one. I get data from the web (via web services and direct image downloading) and I use AsyncTask a lot. Most of the time it crashes on the asynctask. Here is a sample on how I do things:
private BackTask backTask;
Activity ctx = this;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.trackslist);
backTask = new BackTask();
backTask.execute();
}
protected class BackTask extends AsyncTask<Context, String, myObject>
{
#Override
protected myObject doInBackground(Context... params)
{
try{
if (hasInternet(ctx)==true)
{
//access the web SERVICE here
//initialize myObject WITH result FROM the web
return myObject
}
else
{
return null
}
}catch(Exception ex){
return null;
}
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values)
{
super.onProgressUpdate(values);
}
#Override
protected void onCancelled()
{
super.onCancelled();
}
#Override
protected void onPostExecute( myObject result )
{
super.onPostExecute(result);
if (result==null || result.isEmpty())
{
//no valid result, show a message
}
else
{
//result valid do something with it
}
}
}
#Override
public void onPause()
{
if (backTask!=null && ! backTask.isCancelled())
{
backTask.cancel(true);
}
super.onPause();
}
public void btnStartOnClick(View target) {
Intent intent = new Intent(this, MyNewActivity.class);
startActivity(intent);
}
When the activity gets onPause() the task is being canceled. I am not sure what happens during the try/catch if a error appears, from what I've did, it should return null, but I think here I miss something. As I said before, randomly I get a force close even if I am on another Activity. This is really frustrating as I can't offer a app that has this behavior. So, what am I doing wrong ?
There is problem in your code. I have corrected as follows: You find I have added this while calling async task.
Your async task accept context as argument and you was not passing that.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.trackslist);
backTask = new BackTask();
backTask.execute(this);
}
You need to ask inside your AsyncTask class for isCancelled() and then decide what to do.
Check this question. It has a good explanation by Romain Guy:
You can stop an AsyncTask. If you call
cancel(true), an interrupt will be
sent to the background thread, which
may help interruptible tasks.
Otherwise, you should simply make sure
to check isCancelled() regularly in
your doInBackground() method. You can
see examples of this at
code.google.com/p/shelves.
Related
I use an async task to upload an image and get some results.
While uploading the image I see a progress dialog, written in onPreExecute() method like this:
protected void onPreExecute() {
uploadingDialog = new ProgressDialog(MyActivity.this);
uploadingDialog.setMessage("uploading");
uploadingDialog.setCancelable(true);
uploadingDialog.show();
}
Ok when I press the back button, obviously the dialog disappears because of the setCancelable(true).
But (obviously) the async task doesn't stop.
So how can I fix this? I want to cancel both dialog and async task when I press the back button. Any ideas?
From SDK:
Cancelling a task
A task can be cancelled at any time by invoking cancel(boolean).
Invoking this method will cause subsequent calls to isCancelled()
to return true.
After invoking this method, onCancelled(Object), instead of
onPostExecute(Object) will be invoked after doInBackground(Object[]) returns.
To ensure that a task is cancelled as quickly as possible,
you should always check the return value of isCancelled() periodically from
doInBackground(Object[]), if possible (inside a loop for instance.)
So your code is right for dialog listener:
uploadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
myTask.cancel(true);
//finish();
}
});
Now, as I have mentioned earlier from SDK, you have to check whether the task is cancelled or not, for that you have to check isCancelled() inside the onPreExecute() method.
For example:
if (isCancelled())
break;
else
{
// do your work here
}
FOUND THE SOLUTION:
I added an action listener before uploadingDialog.show() like this:
uploadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener(){
public void onCancel(DialogInterface dialog) {
myTask.cancel(true);
//finish();
}
});
That way when I press the back button, the above OnCancelListener cancels both dialog and task. Also you can add finish() if you want to finish the whole activity on back pressed. Remember to declare your async task as a variable like this:
MyAsyncTask myTask=null;
and execute your async task like this:
myTask = new MyAsyncTask();
myTask.execute();
I spent a while figuring this out, all I wanted was a simple example of how to do it, so I thought I'd post how I did it. This is some code that updates a library and has a progress dialog showing how many books have been updated and cancels when a user dismisses the dialog:
private class UpdateLibrary extends AsyncTask<Void, Integer, Boolean>{
private ProgressDialog dialog = new ProgressDialog(Library.this);
private int total = Library.instance.appState.getAvailableText().length;
private int count = 0;
//Used as handler to cancel task if back button is pressed
private AsyncTask<Void, Integer, Boolean> updateTask = null;
#Override
protected void onPreExecute(){
updateTask = this;
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
updateTask.cancel(true);
}
});
dialog.setMessage("Updating Library...");
dialog.setMax(total);
dialog.show();
}
#Override
protected Boolean doInBackground(Void... arg0) {
for (int i = 0; i < appState.getAvailableText().length;i++){
if(isCancelled()){
break;
}
//Do your updating stuff here
}
}
#Override
protected void onProgressUpdate(Integer... progress){
count += progress[0];
dialog.setProgress(count);
}
#Override
protected void onPostExecute(Boolean finished){
dialog.dismiss();
if (finished)
DialogHelper.showMessage(Str.TEXT_UPDATELIBRARY, Str.TEXT_UPDATECOMPLETED, Library.instance);
else
DialogHelper.showMessage(Str.TEXT_UPDATELIBRARY,Str.TEXT_NOUPDATE , Library.instance);
}
}
create some member variables in your activity like
YourAsyncTask mTask;
Dialog mDialog;
use these for your dialog and task;
in onPause() simply call
if(mTask!=null) mTask.cancel();
if(mDialog!=null) mDialog.dismiss();
I would like to improve the code. When you canel the aSyncTask the onCancelled() (callback method of aSyncTask) gets automatically called, and there you can hide your progressBarDialog.
You can include this code as well:
public class information extends AsyncTask<String, String, String>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... arg0) {
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
this.cancel(true);
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected void onCancelled() {
Toast.makeText(getApplicationContext(), "asynctack cancelled.....", Toast.LENGTH_SHORT).show();
dialog.hide(); /*hide the progressbar dialog here...*/
super.onCancelled();
}
}
Most of the time that I use AsyncTask my business logic is on a separated business class instead of being on the UI. In that case, I couldn't have a loop at doInBackground(). An example would be a synchronization process that consumes services and persist data one after another.
I end up handing on my task to the business object so it can handle cancelation. My setup is like this:
public abstract class MyActivity extends Activity {
private Task mTask;
private Business mBusiness;
public void startTask() {
if (mTask != null) {
mTask.cancel(true);
}
mTask = new mTask();
mTask.execute();
}
}
protected class Task extends AsyncTask<Void, Void, Boolean> {
#Override
protected void onCancelled() {
super.onCancelled();
mTask.cancel(true);
// ask if user wants to try again
}
#Override
protected Boolean doInBackground(Void... params) {
return mBusiness.synchronize(this);
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
mTask = null;
if (result) {
// done!
}
else {
// ask if user wants to try again
}
}
}
public class Business {
public boolean synchronize(AsyncTask<?, ?, ?> task) {
boolean response = false;
response = loadStuff(task);
if (response)
response = loadMoreStuff(task);
return response;
}
private boolean loadStuff(AsyncTask<?, ?, ?> task) {
if (task != null && task.isCancelled()) return false;
// load stuff
return true;
}
}
I had a similar problem - essentially I was getting a NPE in an async task after the user had destroyed the activity. After researching the problem on Stack Overflow, I adopted the following solution:
volatile boolean running;
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
running=true;
...
}
public void onDestroy() {
super.onDestroy();
running=false;
...
}
Then, I check "if running" periodically in my async code. I have stress tested this and I am now unable to "break" my activity. This works perfectly and has the advantage of being simpler than some of the solutions I have seen on SO.
You can just ask for cancellation but not really terminate it. See this answer.
How to cancel AsyncTask
Full answer is here - Android AsyncTask Example
AsyncTask provides a better cancellation strategy, to terminate currently running task.
cancel(boolean mayInterruptIfitRunning)
myTask.cancel(false)- It makes isCancelled returns true. Helps to cancel the task.
myTask.cancel(true) – It also makes isCancelled() returns true, interrupt the background thread and relieves resources .
It is considered as an arrogant way, If there is any thread.sleep() method performing in background thread, cancel(true) will interrupt background thread at that time. But cancel(false) will wait for it and cancel task when that method completes.
If you invoke cancel() and doInBackground() hasn’t begun execute yet. onCancelled() will invoke.
After invoking cancel(…) you should check value returned by isCancelled() on doInbackground() periodically. just like shown below.
protected Object doInBackground(Params… params) {
while (condition)
{
...
if (isCancelled())
break;
}
return null;
}
I've been using AsyncTasks for a while however, I've recently encountered a scenario where I'm unsure of how to handle correctly. Since I thought it would be a somewhat common scenario I decided to ask the question here.
So, I'm trying to use an AsyncTask to make a simple call to sign a user in to the app. After the call completes, if it succeeds, the user should be taken to another activity. This logic is simple. The problem arrises when the user navigates away from the app before the sign in call returns. In such a case, what should I do in onPostExecute()?
What I've seen some apps do is they continue with the call anyways, as long as the activity is still around, and will launch the next activity. However this creates a weird experience where the user navigates away from the app, then several seconds later, the app just pops back up in their face. Of course, I would like to avoid doing this.
Update
Example code:
public class ExampleActivity extends Activity {
private boolean mIsPaused;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Button btnSignIn = (Button) findViewById(R.id.btn_sign_in);
btnSignIn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new SignInTask(ExampleActivity.this).execute();
}
});
...
}
#Override
protected void onPause() {
super.onPause();
mIsPaused = true;
}
#Override
protected void onResume() {
super.onResume();
mIsPaused = false;
}
private boolean isPaused() {
return mIsPaused;
}
...
private static class SignInTask extends AsyncTask<Void, Void, SomeResult> {
private final WeakReference<ExampleActivity> mAct;
public SignInTask(ExampleActivity act) {
mAct = new WeakReference<ExampleActivity>(act);
}
#Override
protected SomeResult doInBackground(Void... params) {
return mApi.signIn(creds);
}
#Override
protected void onPostExecute(SomeResult result) {
if (result.getCode() == OK) {
ExampleActivity act = mAct.get();
if (act != null) {
if (act.isPaused()) {
// do something
} else {
startActivity(new Intent(act, NextActivity.class));
}
} else {
// do something
}
}
}
}
}
made your AsyncTask class as static inner class.
Pretty interesting problem... Going with what you've started by using booleans, you could save the response the Activity receives to the SharedPreferences in the event it is paused, or continue processing normally if it is not. If the Activity later resumes (or is recreated), check whether or not there is a saved response and handle accordingly. I was thinking something along the lines of:
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
public class TaskActivity extends Activity {
private static final String KEY_RESPONSE_JSON = "returned_response";
private boolean paused = false;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// don't setup here, wait for onPostResume() to figure out what to do
}
#Override
public void onPostResume(){
super.onPostResume();
paused = false;
if(isSavedResponseAvailable()) processResponse(getSavedResponse());
else setup();
}
#Override
public void onPause(){
paused = true;
super.onPause();
}
private void setup(){
// normal setup
}
public void onReceiveResponse(JSONObject response){
if(paused) setSavedResponse(response);
else processResponse(response);
}
private void processResponse(JSONObject response){
// Continue with processing as if they never left
getSharedPreferences(this.getClass().getName(), 0).edit().clear().commit(); // Clear everything so re-entering won't parse old data
}
private boolean isSavedResponseAvailable(){
return getSavedResponse() != null;
}
private JSONObject getSavedResponse(){
try{
return new JSONObject(getSharedPreferences(this.getClass().getName(), 0).getString(KEY_RESPONSE_JSON, ""));
}
catch(Exception e){ }
return null;
}
private void setSavedResponse(JSONObject response){
getSharedPreferences(this.getClass().getName(), 0).edit().putString(KEY_RESPONSE_JSON, response.toString()).commit();
}
}
Clearly that's assuming your response from the task is JSON, but there's no reason you couldn't extend that to save the data individually and rebuild the necessary response object from the saved preference data.
As far as clean approaches go, though... I give this about a 3/10, but I can't think of anything better (well, other than making the TaskActivity abstract and forcing implementations to override setup(), processResponse(), isResponseAvailable(), getSavedResponse(), and setSavedResponse(), but that would only be mildly better for like a 4/10)
I would suggest putting a try/catch statement in the post execute - as far as I know what would happen in this situation is that you would get some kind of Window Manager exception.
What I would STRONGLY recommend, however, is stopping any async tasks (with the cancel method) on the onPause method, meaning that you won't interrupt them.
http://developer.android.com/reference/android/os/AsyncTask.html#cancel(boolean)
public final boolean cancel (boolean mayInterruptIfRunning)
Added in API level 3
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
Calling this method will result in onCancelled(Object) being invoked on the UI thread after doInBackground(Object[]) returns. Calling this method guarantees that onPostExecute(Object) is never invoked. After invoking this method, you should check the value returned by isCancelled() periodically from doInBackground(Object[]) to finish the task as early as possible.
Parameters
mayInterruptIfRunning true if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete.
Returns
false if the task could not be cancelled, typically because it has already completed normally; true otherwise
See Also
isCancelled()
onCancelled(Object)
boolean isRunning; //set it to true in onResume, and false in onStop
boolean isWaiting; // set it to true in onPostExecute, if "isRunning" is false
check in onResume whether isWaiting is true, if yes, take user to another screen.
Use the cancel() of AsynchTask class onBackPress() of Activty class
public class ExampleActivity extends Activity {
private boolean mIsPaused;
SignInTask singleTaskObj;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Button btnSignIn = (Button) findViewById(R.id.btn_sign_in);
btnSignIn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
singleTaskObj = new SignInTask(ExampleActivity.this).execute();
}
});
...
}
#Override
protected void onPause() {
super.onPause();
mIsPaused = true;
}
#Override
protected void onResume() {
super.onResume();
mIsPaused = false;
}
protected void onBackPressed()
{
singleTaskObj.cancel();
}
private boolean isPaused() {
return mIsPaused;
}
...
private static class SignInTask extends AsyncTask<Void, Void, SomeResult> {
private final WeakReference<ExampleActivity> mAct;
public SignInTask(ExampleActivity act) {
mAct = new WeakReference<ExampleActivity>(act);
}
#Override
protected SomeResult doInBackground(Void... params) {
return mApi.signIn(creds);
}
#Override
protected void onPostExecute(SomeResult result) {
if (result.getCode() == OK) {
ExampleActivity act = mAct.get();
if (act != null) {
if (act.isPaused()) {
// do something
} else {
startActivity(new Intent(act, NextActivity.class));
}
} else {
// do something
}
}
}
}
}
I made an application for Android that originally targeted a lower version (2.3). After I got my proof-of-concept working, I tried to get it to work on Android 4. That's when I got the NetworkOnMainThread exception.
After doing some research, I quickly found the AsyncTask, which sounded awesome. The problem is, I'm having a hard time wrapping my mind around it. For instance, here's my original code:
public void Refresh(Context c)
{
SummaryModel model = MobileController.FetchSummary(c);
TextView txtCurrentWeight = (TextView)findViewById(R.id.txtCurrentWeight);
TextView txtWeightChange = (TextView)findViewById(R.id.txtWeightChange);
TextView txtAvgPerWeek = (TextView)findViewById(R.id.txtAvgPerWeek);
if(model.ErrorMessage == "")
{
txtCurrentWeight.setText(model.CurrentWeight);
txtWeightChange.setText(model.WeightChange);
txtAvgPerWeek.setText(model.Average);
}
else
{
Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();
txtCurrentWeight.setText("");
txtWeightChange.setText("");
txtAvgPerWeek.setText("");
}
}
I created an AsychTask like this:
public class WebMethodTask extends AsyncTask<Object, Integer, Object> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
SummaryModel model = (SummaryModel)result;
// Can't seem to access UI items here??
}
#Override
protected Object doInBackground(Object... params) {
Context c = (Context)params[0];
return MobileController.FetchSummary(c);
}
}
How do I access the UI items from the onPostExecute method? Or, do I have the wrong idea on how to use AsyncTask?
Thanks!
You should be able to accessUI where you put your comments (in the postExecute method)
Additionally, I would suggest to use more specialized class with for AsyncTask, so that your code looks better :
public class WebMethodTask extends AsyncTask<Object, Integer, SummaryModel> {
private Activity source;
public WebMethodTask(Activity activity) {
this.source=activity;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(SummaryModel model) {
super.onPostExecute(model );
TextView txtCurrentWeight = (TextView)source.findViewById(R.id.txtCurrentWeight);
TextView txtWeightChange = (TextView)source.findViewById(R.id.txtWeightChange);
TextView txtAvgPerWeek = (TextView)source.findViewById(R.id.txtAvgPerWeek);
if(model.ErrorMessage.length()==0)
{
txtCurrentWeight.setText(model.CurrentWeight);
txtWeightChange.setText(model.WeightChange);
txtAvgPerWeek.setText(model.Average);
}
else
{
Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();
txtCurrentWeight.setText("");
txtWeightChange.setText("");
txtAvgPerWeek.setText("");
}
}
#Override
protected SummaryModel doInBackground(Context ... params) {
Context c = params[0];
return MobileController.FetchSummary(c);
}
}
Edit : Added a reference to your activity, to take your last comment into account.
However, if you acynctask can be long, it's maybe not a very good idea to keep a reference on an activity.
It would be a better design to create a listenerclass that will accept some displayModel(CummaryModel) method, and whose responsability is to cal the setText methods if the activity has not been paused / stopped in the meanwhile...
Fill the ui items with the loaded model data in the WebMethodTask#onPostExecute method.
You need a reference to your UI controls. When passing references to your UI controls to the ASyncTask you will create problems.
Assume the following scenario:
show activity (activity instance 1)
call async task with te activity as reference.
rotate your device (by default a device rotation will create a new activity) -> (activity instance 2)
when the sync task is finished, activity instance 1 is used to display the results. However the activity no longer exists causing exceptions.
The conclusion is that the ASyncTask should not be used for network activity related background tasks.
Fortunately there is a solution: RoboSpice.
RoboSpice uses another approach. Look at https://github.com/octo-online/robospice/wiki/Understand-the-basics-of-RoboSpice-in-30-seconds for a good explanation.
More information: https://github.com/octo-online/robospice
create an inner class in refresh method as
enter code herepublic void Refresh(Context c)
{
SummaryModel model = MobileController.FetchSummary(c);
TextView txtCurrentWeight = (TextView)findViewById(R.id.txtCurrentWeight);
TextView txtWeightChange = (TextView)findViewById(R.id.txtWeightChange);
TextView txtAvgPerWeek = (TextView)findViewById(R.id.txtAvgPerWeek);
if(model.ErrorMessage == "")
{
txtCurrentWeight.setText(model.CurrentWeight);
txtWeightChange.setText(model.WeightChange);
txtAvgPerWeek.setText(model.Average);
}
else
{
Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();
txtCurrentWeight.setText("");
txtWeightChange.setText("");
txtAvgPerWeek.setText("");
}
class WebMethodTask extends AsyncTask<Object, Integer, Object> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
SummaryModel model = (SummaryModel)result;
// Can't seem to access UI items here??
}
#Override
protected Object doInBackground(Object... params) {
Context c = (Context)params[0];
return MobileController.FetchSummary(c);
}
}
}
I have two activities. While switching to second activity by intent, it takes 3-4 seconds because it has lots of components with adapters fetching data from SQLite etc. Thus, I want to show a progress dialog while switching.
I have been digging topics for this purpose and tried many of them:
1-) Using AsyncTask on the second activity. It doesn't show the progress dialog as soon as I click on a component to switch to the second activity. It waits for 3-4 seconds and then progress dialog shows up for less then a second which is not user-friendly way.
2-) Using AsyncTask on the first activity. It shows as soon as I click on that component but the progress wheel doesn't spin. The progress dialog freezes.
3-) Using AsyncTask onStart() method on the second activity. This results as the first way.
The code below implements the second way above, using AsyncTask on the first activity.
public void toVisitRegister(Event event) { //Switching to the second activity
new startingThread().execute();
Intent toVisitRegister = new Intent(MainCalendar.this, VisitRegister.class);
startActivity(toVisitRegister);
finish();
}
And here is the AsyncTask
public class startingThread extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
startingProgress = new ProgressDialog(MainCalendar.this);
startingProgress.setTitle("Visit Register");
startingProgress.setMessage("Initializing...");
startingProgress.show();
}
#Override
protected String doInBackground(String... params) {
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(MainCalendar.this.startingProgress != null) {
MainCalendar.this.startingProgress.dismiss();
}
}
}
I also tried to call startActivity in onPostExecute, but it didn't work. Therefore, I am waiting for your opinions and suggessions about this issue. Any help will be appreciated.
Thanks.
I also tried to call startActivity in onPostExecute,
Pass the Activity context to startingThread AsyncTask and put your start activity code in onPostExecute() of AsyncTask.
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(MainCalendar.this.startingProgress != null) {
MainCalendar.this.startingProgress.dismiss();
Intent toVisitRegister = new Intent(MainCalendar.this, VisitRegister.class);
mContext.startActivity(toVisitRegister);
mContext.finish();
}
}
Here mContext is the Context of your current MainCalendar Activity.
Looking at your implementation, the AsyncTask wont have time to work because you will be jumping to the next Activity right away. Try calling the next activity in PostExecute().
I also tried to call startActivity in onPostExecute, but it didn't work.
Did you did it like this:
public void toVisitRegister(Event event) { //Switching to the second activity
new startingThread().execute();
}
public class startingThread extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
startingProgress = new ProgressDialog(MainCalendar.this);
startingProgress.setTitle("Visit Register");
startingProgress.setMessage("Initializing...");
startingProgress.show();
}
#Override
protected String doInBackground(String... params) {
return null;
}
#Override
protected void onPostExecute(String result) {
if(MainCalendar.this.startingProgress != null) {
MainCalendar.this.startingProgress.dismiss();
}
Intent toVisitRegister = new Intent(MainCalendar.this, VisitRegister.class);
startActivity(toVisitRegister);
finish();
}
}
friends,
i am using following code to fill android listview asynchronously
now problem is while running this thread i press back button or home button and comes back to activity
multiple threads are started....
can i avoid these multiple threads
actually i want if thread is running then it should not get called again and again.
it should be called when previous thread is complete.
private static String[] items={.......};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setListAdapter(
new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
new ArrayList()));
AddStringTask test= new AddStringTask();
test.execute();
}
class AddStringTask extends AsyncTask<Void, String, Void> {
#Override
protected Void doInBackground(Void... unused) {
for (String item : items) {
publishProgress(item);
SystemClock.sleep(1000);
}
return(null);
}
#Override
protected void onProgressUpdate(String... item) {
((ArrayAdapter)getListAdapter()).add(item[0]);
}
#Override
protected void onPostExecute(Void unused) {
Toast
.makeText(AsyncThread.this,
"Done - Finished updating Java Book List!",
Toast.LENGTH_SHORT)
.show();
}
}
}
any useful solution?
thanks in advance.
You can intercept the Activity Closing by overriding onStop() or onPause() or even onBackPressed() and terminate the update when it does...
If you don't wish to terminate it and instead just want NOT to initiate it again, just use static variables (or any other method) such that the test variable is created only once...
To terminate a AsyncTask, i believe there's a cancel() method...Use true as its parameter.
From API Reference
final boolean cancel(boolean mayInterruptIfRunning)
//Attempts to cancel execution of this task.