EDIT
Okay really simplified version, let's call this my Activity2
public class test {
String username, id;
TextView view1, view2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view1 = (TextView)findViewById(R.id.textView1);
view2 = (TextView)findViewById(R.id.textView2);
new testFunction().execute();
view1.setText(username);
view2.setText(id);
}
private class testFunction extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... x) {
username = "1";
id = "2";
return null;
}
}
}
Activity1 has a submit button that starts Activity2 (this activity). After Activity2 calls onCreate(), "12" will appear on the screen. When I click back (destroy Activity2 and go back to Activity1), AND THEN go back to Activity2 again, nothing appears on the screen. Why is this?
This is one problem
new testFunction().execute("1", "2").get();
You should not use get(). It blocks the ui thread waiting for the result. And you should never block the ui thread. Use
new testFunction().execute("1", "2");
Declare the variables as instance variables
TextView view1,view2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_data);
view1 = (TextView)findViewById(R.id.textView1);
view2 = (TextView)findViewById(R.id.textView2);
new testFunction().execute("1", "2")
Then in Asynctask onPostExecute update the views
#override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
// update view here
}
finish the actvity when you have pressed back button like
Intent i = new Intent(this,Here is your class name.Class);
startActivity(i);
finish();
by this whenever you will go in second act by press submit button that time on create call
and you can also call your asnyc task in on resume method every time on resume will call.
You have to store the username and id value when closing the fragment.
Have a look into Fragment lifecycle onSaveInstanceState.
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(ARG_NAME, username);
outState.putBoolean(ARG_ID, id);
I have add some code lines to your onCreate method
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_data);
//get the values from previous avtivity
Bundle bundle=getIntent().getExtras();
username=bundle.getString("username").toString();
id=bundle.getString("id").toString();
String result = new testFunction().execute("1", "2").get();
TextView view1 = (TextView)findViewById(R.id.textView1);
TextView view2 = (TextView)findViewById(R.id.textView2);
view1.setText(username);
view2.setText(id);
}
in order to get the values you must pass the values from previous activity, I guess you have did it correctly, what you missed is, you forgot to get the Intent values and assign them to username,id variables
I am working on push notifications. The issue is when i am loading a form which is very huge and i recieve notification, before the form is completely loaded i try to click on the notification i get a blank screen after 5-6 seconds. The exception is due to dialog.dismiss.
According to my understanding, while opening notification the current activity is destroyed a new activity is created. while creating a new activity i am using asynctask to accomplish some other functionality in my app. So when the current activity is destroyed, activity context is null but the asynctask is still running also progress dialog. As soon as the activity is destroyed there is no window to show the dialog and hence window leaked exception.
Can anybody help me to get me out of this issue.I also get the blank screen when app is idle for a long time then i open the notifications.
Is there a way to stop running the asynctask as soon as the activity is destroyed.
My code is :
public class MainActivity extends Activity {
private MyProgressDialog myProgressDialog;
public LinearLayout mainPanel;
private VMobilet mobilet = null;
private String mobiletId;
private String formId ;
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(mainPanel);
Intent i = getIntent();
mobiletId = i.getStringExtra("Mobilet Id");
formId = i.getStringExtra("Form ID");
VUiHelper.getInstance().setIsFinish(false);
myProgressDialog = MyProgressDialog.show(MainActivity.this,"","",true);
BackgroundTask backgroundTask = new BackgroundTask();
backgroundTask.execute(MainActivity.this);
}
#Override
protected void onPause() {
super.onPause();
if(VUiHelper.getInstance().isFinish())
{
this.finish();
}
else {
System.out.println("pausing mainactivity");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
System.out.println("mainactivity ondestroy called");
if(mobilet != null)
mobilet.getForms().clear();
mobilet = null;
mainPanel = null;
VUiHelper.getInstance().clearControlCache();
VUiHelper.getInstance().MediaInput.clear();
System.gc();
}
private class BackgroundTask extends AsyncTask<Context, String, Boolean> {
#Override
public void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(Context... arg0) {
if (mobiletId != null) {
** some logic **
}
return true;
}
#Override
public void onPostExecute(Boolean status){
super.onPostExecute(status);
myProgressDialog.dismiss(); //dismissing the progress dialogs
if (mobilet != null) {
** some logic **
} else {
** some logic **
}
}
}
}
}
I tried printing the activity context in onDestroy() and it is null.
You can stop running an Asynctask (as long as you have a reference to it). You might want to do something like this
when starting:
Task ref = new Task();
ref.execute()
then in onPause()
if(ref != null)
ref.cancel(true);
then inside your doInBackground() if you are doing something periodically (like downloading) have something like this:
if(isCanceled())
{
return;
}
The above snippets should allow you to gracefully exit the asynctask.
Also in your onPause
if(myProgressDialog != null)
{
if(myProgressDialog.isShowing())
{
myProgressDialog.dismiss()
}
myProgressDialog = null
}
then in your onPostExecute
if(myProgressDialog != null)
{
if(myProgressDialog.isShowing())
{
myProgessDialog.dismiss;
myProgessDialog = null;
}
}
the setting of myProgessDialog to null in onPuase should make it null in onPOstExecute()
You can cancel an AsyncTask by calling cancel(Boolean). For more usage info ctrl-f for "Cancelling a task" on that page
I think the best solution to the problem is let your asyntask check whether there is still an application running. If not simply exit. Set a flag in Activity.onPause and the let the asynctask check it before sending some output.
I have looked around on the API and through a few questions on here, and I think I am on the right path. My app is based on a webView object and the initial load has quite a few cached pages so I want progressDialog on the initial start up instead of the blank black screen. Right now the app just crashes but I believe it is because I am creating and calling the AsyncTask object in the wrong place. Right now it is being called in the onCreate() method. I’m not new to Java but I am new to Android and this idea of not working with a main() function is confusing to me.
So where should I call the execute() function if I only want the ProgressDialog shown on the initial launch? And is my AsyncTask object even set up correctly?
public class site extends Activity {
private WebView engine;
private String urlSave;
private WebViewClient yourWebClient;
private ProgressDialog initLoadDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
yourWebClient = new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("tel:") == true) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
}
else if(url.contains(“blah") == true && url.contains(“blah2") == false) {
view.loadUrl(url);
}
else if(url.contains(“blah3") == true) {
double[] loc = getGPS();
url += "&cLat=" + loc[0] + "&cLong=" + loc[1];
view.loadUrl(url);
}
else {
/*Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("url"));
startActivity(browserIntent);*/
}
return true;
}
};
}
#Override
public void onStart() {
progressSetup();
setContentView(R.layout.main);
}
public void progressSetup () {
initLoadDialog = new ProgressDialog(site.this);
initLoadDialog.setMessage("A message");
initLoadDialog.setIndeterminate(false);
initLoadDialog.setMax(100);
initLoadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
urlLoad loading = new urlLoad();
loading.execute();
}
private class urlLoad extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String... url) {
try {
engine = (WebView) findViewById(R.id.web_engine);
engine.getSettings().setJavaScriptEnabled(true);
engine.getSettings().setBuiltInZoomControls(true);
engine.getSettings().setSupportZoom(true);
engine.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
engine.getSettings().setGeolocationEnabled(true);
engine.setWebViewClient(yourWebClient);
engine.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
engine.loadUrl(“albhal");
} catch (Exception e) {}
return null;
}
protected void onProgressUpdate(Integer... progress) {
initLoadDialog.setProgress(engine.getProgress());
}
}
}
Check your adb log, the error will pretty much explain to you what you didn't do right.
There's a lot of bad practice in your code. For example you call setContentView() in two Methods with different Layouts. The Flow of a android application is to call "onCreate", then "onStart". There is no reason to distinguish between those methods for you. Merge them and decide which layout to populate.
Also it is recommended to change the user-interface (this means also the dialogs) through the managing activity. In your case you are creating a ProgressDialog in the activity which then gets modified by the task. This is something you should avoid.
I read a lot on how to save my instance state or how to deal with my activity getting destroyed during screen rotation.
There seem to be a lot of possibilities but I haven't figured out which one works best for retrieving results of an AsyncTask.
I have some AsyncTasks that are simply started again and call the isFinishing() method of the activity and if the activity is finishing they wont update anything.
The problem is that I have one Task that does a request to a web service that can fail or succeed and restarting the task would result in a financial loss for the user.
How would you solve this? What are the advantages or disadvantages of the possible solutions?
You can check out how I handle AsyncTasks and orientation changes at code.google.com/p/shelves. There are various ways to do it, the one I chose in this app is to cancel any currently running task, save its state and start a new one with the saved state when the new Activity is created. It's easy to do, it works well and as a bonus it takes care of stopping your tasks when the user leaves the app.
You can also use onRetainNonConfigurationInstance() to pass your AsyncTask to the new Activity (be careful about not leaking the previous Activity this way though.)
This is the most interesting question I've seen regarding to Android!!! Actually I've been already looking for the solution during the last months. Still haven't solved.
Be careful, simply overriding the
android:configChanges="keyboardHidden|orientation"
stuff is not enough.
Consider the case when user receives a phone call while your AsyncTask is running. Your request is already being processed by server, so the AsyncTask is awaiting for response. In this moment your app goes in background, because the Phone app has just come in foreground. OS may kill your activity since it's in the background.
My first suggestion would be to make sure you actually need your activity to be reset on a screen rotation (the default behavior). Every time I've had issues with rotation I've added this attribute to my <activity> tag in the AndroidManifest.xml, and been just fine.
android:configChanges="keyboardHidden|orientation"
It looks weird, but what it does it hand off to your onConfigurationChanged() method, if you don't supply one it just does nothing other than re-measure the layout, which seems to be a perfectly adequate way of handling the rotate most of the time.
Why don't you always keep a reference to the current AsyncTask on the Singleton provided by Android?
Whenever a task starts, on PreExecute or on the builder, you define:
((Application) getApplication()).setCurrentTask(asyncTask);
Whenever it finishes you set it to null.
That way you always have a reference which allows you to do something like, onCreate or onResume as appropriated for your specific logic:
this.asyncTaskReference = ((Application) getApplication()).getCurrentTask();
If it's null you know that currently there is none running!
:-)
The most proper way to this is to use a fragment to retain the instance of the async task, over rotations.
Here is a link to very simple example making it easy to follow integrate this technique into your apps.
https://gist.github.com/daichan4649/2480065
In Pro android 4. author has suggest a nice way, that you should use weak reference.
Weak reference note
To my point of view, it's better to store asynctask via onRetainNonConfigurationInstance decoupling it from the current Activity object and binding it to a new Activity object after the orientation change. Here I found a very nice example how to work with AsyncTask and ProgressDialog.
Android : background processing/Async Opeartion with configuration change
To maintain the states of async opeartion during background process:
you can take an help of fragments.
See the following steps :
Step 1: Create a headerless fragment let say background task and add a private async task class with in it.
Step 2 (Optional Step): if you want to put a loading cursor on top of your activity use below code:
Step 3: In your main Activity implement BackgroundTaskCallbacks interface defined in step 1
class BackgroundTask extends Fragment {
public BackgroundTask() {
}
// Add a static interface
static interface BackgroundTaskCallbacks {
void onPreExecute();
void onCancelled();
void onPostExecute();
void doInBackground();
}
private BackgroundTaskCallbacks callbacks;
private PerformAsyncOpeation asyncOperation;
private boolean isRunning;
private final String TAG = BackgroundTask.class.getSimpleName();
/**
* Start the async operation.
*/
public void start() {
Log.d(TAG, "********* BACKGROUND TASK START OPERATION ENTER *********");
if (!isRunning) {
asyncOperation = new PerformAsyncOpeation();
asyncOperation.execute();
isRunning = true;
}
Log.d(TAG, "********* BACKGROUND TASK START OPERATION EXIT *********");
}
/**
* Cancel the background task.
*/
public void cancel() {
Log.d(TAG, "********* BACKGROUND TASK CANCEL OPERATION ENTER *********");
if (isRunning) {
asyncOperation.cancel(false);
asyncOperation = null;
isRunning = false;
}
Log.d(TAG, "********* BACKGROUND TASK CANCEL OPERATION EXIT *********");
}
/**
* Returns the current state of the background task.
*/
public boolean isRunning() {
return isRunning;
}
/**
* Android passes us a reference to the newly created Activity by calling
* this method after each configuration change.
*/
public void onAttach(Activity activity) {
Log.d(TAG, "********* BACKGROUND TASK ON ATTACH ENTER *********");
super.onAttach(activity);
if (!(activity instanceof BackgroundTaskCallbacks)) {
throw new IllegalStateException(
"Activity must implement the LoginCallbacks interface.");
}
// Hold a reference to the parent Activity so we can report back the
// task's
// current progress and results.
callbacks = (BackgroundTaskCallbacks) activity;
Log.d(TAG, "********* BACKGROUND TASK ON ATTACH EXIT *********");
}
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "********* BACKGROUND TASK ON CREATE ENTER *********");
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
Log.d(TAG, "********* BACKGROUND TASK ON CREATE EXIT *********");
}
public void onDetach() {
super.onDetach();
callbacks = null;
}
private class PerformAsyncOpeation extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > ON PRE EXECUTE ENTER *********");
if (callbacks != null) {
callbacks.onPreExecute();
}
isRunning = true;
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > ON PRE EXECUTE EXIT *********");
}
protected Void doInBackground(Void... params) {
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > DO IN BACKGROUND ENTER *********");
if (callbacks != null) {
callbacks.doInBackground();
}
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > DO IN BACKGROUND EXIT *********");
return null;
}
protected void onCancelled() {
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > ON CANCEL ENTER *********");
if (callbacks != null) {
callbacks.onCancelled();
}
isRunning = false;
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > ON CANCEL EXIT *********");
}
protected void onPostExecute(Void ignore) {
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > ON POST EXECUTE ENTER *********");
if (callbacks != null) {
callbacks.onPostExecute();
}
isRunning = false;
Log.d(TAG,
"********* BACKGROUND TASK :-> ASYNC OPERATION :- > ON POST EXECUTE EXIT *********");
}
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
}
public void onStart() {
super.onStart();
}
public void onResume() {
super.onResume();
}
public void onPause() {
super.onPause();
}
public void onStop() {
super.onStop();
}
public class ProgressIndicator extends Dialog {
public ProgressIndicator(Context context, int theme) {
super(context, theme);
}
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.progress_indicator);
this.setCancelable(false);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.getIndeterminateDrawable().setColorFilter(R.color.DarkBlue, android.graphics.PorterDuff.Mode.SCREEN);
}
#Override
public void show() {
super.show();
}
#Override
public void dismiss() {
super.dismiss();
}
#Override
public void cancel() {
super.cancel();
}
public class MyActivity extends FragmentActivity implements BackgroundTaskCallbacks,{
private static final String KEY_CURRENT_PROGRESS = "current_progress";
ProgressIndicator progressIndicator = null;
private final static String TAG = MyActivity.class.getSimpleName();
private BackgroundTask task = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(//"set your layout here");
initialize your views and widget here .............
FragmentManager fm = getSupportFragmentManager();
task = (BackgroundTask) fm.findFragmentByTag("login");
// If the Fragment is non-null, then it is currently being
// retained across a configuration change.
if (task == null) {
task = new BackgroundTask();
fm.beginTransaction().add(task, "login").commit();
}
// Restore saved state
if (savedInstanceState != null) {
Log.i(TAG, "KEY_CURRENT_PROGRESS_VALUE ON CREATE :: "
+ task.isRunning());
if (task.isRunning()) {
progressIndicator = new ProgressIndicator(this,
R.style.TransparentDialog);
if (progressIndicator != null) {
progressIndicator.show();
}
}
}
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// save the current state of your operation here by saying this
super.onSaveInstanceState(outState);
Log.i(TAG, "KEY_CURRENT_PROGRESS_VALUE ON SAVE INSTANCE :: "
+ task.isRunning());
outState.putBoolean(KEY_CURRENT_PROGRESS, task.isRunning());
if (progressIndicator != null) {
progressIndicator.dismiss();
progressIndicator.cancel();
}
progressIndicator = null;
}
private void performOperation() {
if (!task.isRunning() && progressIndicator == null) {
progressIndicator = new ProgressIndicator(this,
R.style.TransparentDialog);
progressIndicator.show();
}
if (task.isRunning()) {
task.cancel();
} else {
task.start();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (progressIndicator != null) {
progressIndicator.dismiss();
progressIndicator.cancel();
}
progressIndicator = null;
}
#Override
public void onPreExecute() {
Log.i(TAG, "CALLING ON PRE EXECUTE");
}
#Override
public void onCancelled() {
Log.i(TAG, "CALLING ON CANCELLED");
if (progressIndicator != null) {
progressIndicator.dismiss();
progressIndicator.cancel();
}
public void onPostExecute() {
Log.i(TAG, "CALLING ON POST EXECUTE");
if (progressIndicator != null) {
progressIndicator.dismiss();
progressIndicator.cancel();
progressIndicator = null;
}
}
#Override
public void doInBackground() {
// put your code here for background operation
}
}
One thing to consider is whether the result of the AsyncTask should be available only to the activity that started the task. If yes, then Romain Guy's answer is best. If it should be available to other activities of your application, then in onPostExecute you can use LocalBroadcastManager.
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(new Intent("finished"));
You will also need to make sure that activity correctly handles situation when broadcast is sent while activity is paused.
Have a look at this post. This Post involves AsyncTask performing long running operation and memory leak when screen rotation happens both in one sample application. The sample app is available on the source forge
My solution.
In my case i've got a chain of AsyncTasks with the same context. Activity had an access only to first one. To cancel any running task i did the following:
public final class TaskLoader {
private static AsyncTask task;
private TaskLoader() {
throw new UnsupportedOperationException();
}
public static void setTask(AsyncTask task) {
TaskLoader.task = task;
}
public static void cancel() {
TaskLoader.task.cancel(true);
}
}
Task doInBackground():
protected Void doInBackground(Params... params) {
TaskLoader.setTask(this);
....
}
Activity onStop() or onPause():
protected void onStop() {
super.onStop();
TaskLoader.cancel();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
final AddTask task = mAddTask;
if (task != null && task.getStatus() != UserTask.Status.FINISHED) {
final String bookId = task.getBookId();
task.cancel(true);
if (bookId != null) {
outState.putBoolean(STATE_ADD_IN_PROGRESS, true);
outState.putString(STATE_ADD_BOOK, bookId);
}
mAddTask = null;
}
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState.getBoolean(STATE_ADD_IN_PROGRESS)) {
final String id = savedInstanceState.getString(STATE_ADD_BOOK);
if (!BooksManager.bookExists(getContentResolver(), id)) {
mAddTask = (AddTask) new AddTask().execute(id);
}
}
}
you can also add
android:configChanges="keyboardHidden|orientation|screenSize"
to your manifest example i hope it help
<application
android:name=".AppController"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="#style/AppTheme">
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.