AsyncTask's onPostExecute gets called: But doInBackground Does Not - android

I'm having a bizarre problem and I'm not sure if I'm doing something wrong or something.
For some reason, my AsyncTask won't call doInBackground but it calls onPostExecute(). It's essential that this AsyncTask gets called because it initializes a variable I will need throughout the rest of the app.
I have a nested class in my main activity that extends AsyncTask. This class takes care of downloading file names from the user's Dropbox account:
protected class FilesLister extends AsyncTask<String, Integer, Long>
{
#Override
protected Long doInBackground(String... params)
{
Log.i("Entries", "We believe Entries has some values now.");
ArrayList<Entry> theFiles = new ArrayList<Entry>();
try
{
Entry entries = mDBApi.metadata("/", 20000, null, true, null);
for (Entry e : entries.contents)
{
Log.i("Hm", e.fileName());
if (!e.isDeleted)
{
if(!e.isDir)
{
theFiles.add(e);
}
}
}
theEntries = theFiles.toArray(new Entry[theFiles.size()]);
} catch (DropboxException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
return null;
}
protected void onPostExecute(Long result)
{
super.onPostExecute(result);
Log.i("Now", "Calling refresh.");
refresh();
}
}
Like you can see, onPostExecute calls a method called refresh(). refresh() is implemented as follows:
public void refresh()
{
//Sort all this files by last modified date.
Arrays.sort(theEntries, new Comparator<Entry>()
{
#Override
public int compare(Entry firstFile, Entry secondFile)
{
//"EEE, dd MMM yyyy kk:mm:ss ZZZZZ"
SimpleDateFormat formater = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss ZZZZZ");
try
{
Date date1 = (Date)formater.parse(firstFile.modified);
Date date2 = (Date)formater.parse(secondFile.modified);
return date1.compareTo(date2);
} catch (ParseException e1)
{
e1.printStackTrace();
}
return 0;
}
});
//Now we create a String[] array to hold the names of all the fetched files...
ArrayList<String>txtFilesNames = new ArrayList<String>();
for(int i = theEntries.length - 1; i >= 0; i--)
{
//Loops goes from top to bottom so the latest file appears at the top of the ListView.
txtFilesNames.add(theEntries[i].fileName());
}
actualFileNames = txtFilesNames.toArray(new String[txtFilesNames.size()]);
ArrayAdapter<String> ad = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, actualFileNames);
lv.setAdapter(ad);
}
I know refresh() is being called for two reasons: LogCat logs "Calling refresh." and then the app crashes because of a NullPointerException. The null pointer exceptions is thrown because theEntries is indeed null, and it will be null unless doInBackground() gets called. And I know doInBackground is never called due to the null pointer and because the Log I put on it's body never gets called. So what could cause my doInBackground() method not to get called? If it matters, I execute the AsyncTask in my onResume method, and I don't execute any other AsyncTasks in either onCreate or onStart.

Are you sure doInBackground isn't getting called? There are plenty of other ways which could cause theEntries to be null. For instance, an exception here:
Entry entries = mDBApi.metadata("/", 20000, null, true, null);
for (Entry e : entries.contents)
{
Log.i("Hm", e.fileName());
if (!e.isDeleted)
{
if(!e.isDir)
{
theFiles.add(e);
}
}
}
could cause theEntries to be null. Also, I think you could do this a better way. Instead of setting theEntries within doInBackground (which is in a different thread than your object was created in) you should instead have that function return the entries which will pass them to onPostExecute.I believe the code would look like this:
protected class FilesLister extends AsyncTask<String, Integer, Entry[]>
{
#Override
protected Entry[] doInBackground(String... params)
{
Log.i("Entries", "We believe Entries has some values now.");
Entry[] entriesReturn = null;
ArrayList<Entry> theFiles = new ArrayList<Entry>();
try
{
Entry entries = mDBApi.metadata("/", 20000, null, true, null);
for (Entry e : entries.contents)
{
Log.i("Hm", e.fileName());
if (!e.isDeleted)
{
if(!e.isDir)
{
theFiles.add(e);
}
}
}
entriesReturn = theFiles.toArray(new Entry[theFiles.size()]);
} catch (DropboxException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
return entriesReturn;
}
protected void onPostExecute(Entry[] result)
{
super.onPostExecute(result);
Log.i("Now", "Calling refresh.");
refresh(result);
}
}
Then in your refresh method do the assignment.. Also you should check for null in the refresh method.

This problem has been posted by others (see sidebar for related questions). As of now, there is still no solution for this issue. I have ran into this myself, and after struggling for a few days I accepted this as a bug.
What you could do is use Activity.runOnUiThread(). It will fix this issue you're having, but not the issue with AsyncTasks. It's how I worked around this issue.

you able to check that doInBackground() is call or not in onPostExecute() by this way.
protected Long doInBackground(String... params)
{
/////your code...
return 200;
}
protected void onPostExecute(Long result)
{
if(result==200)
{
super.onPostExecute(result);
Log.i("Now", "Calling refresh.");
refresh();
}
}
I am not sure that your entries gives null value or not. In this way you able to know doInBackground() is execute or not.
I think it gives some help .
Thanks.

Related

In what lifecycle state should I execute an Async Task in Fragment?

I have to make an expensive call to a remote server when a Fragment is loaded. I am using the default Dashboard activity with NavigationView to change the fragments. However whenever a fragment is loaded, it freezes the UI for a few seconds while executing the AsyncTask containing the SOAP Request code.
I have already tried to execute the AsyncTask from onAttach() and onStart() but it still freezes the UI.
How can I fix the UI freezing?
Edit :- The async task code:-
private class BindTreasuryTask extends AsyncTask<Void,Void,ArrayList<TreasuryData>> {
private boolean NO_INTERNET;
#Override
protected ArrayList<TreasuryData> doInBackground(Void... voids) {
try {
// SOAP Call returns a JSONArray
JSONArray jsonArray = apiHandler.performBindTreasury(payeeid);
ArrayList<TreasuryData> td = new ArrayList<>();
td.add(new TreasuryData("Select a treasury","none","none"));
for(int i =0; i<jsonArray.size(); i++){
JSONObject j = (JSONObject) jsonArray.get(i);
td.add(new TreasuryData(j.get("TREASURY_NAME"),j.get("TREAS_CODE"),j.get("SCHEMA_NM")));
}
return td;
} catch (IOException e) {
NO_INTERNET = true;
e.printStackTrace();
} catch (XmlPullParserException | ParseException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(ArrayList<TreasuryData> treasuryData ) {
if (treasuryData == null){
if (NO_INTERNET){
Toast.makeText(getActivity(),"No Internet Connection",Toast.LENGTH_LONG).show();
}
} else {
ArrayList<String> treasury = new ArrayList<>();
for(int i=0;i<treasuryData.size();i++){
treasury.add(treasuryData.get(i).getTreasuryName());
}
setUpView();
}
}
}
As Ashok answered you can call AsyncTask in onActivityCreated() method. You may use thread or handler to start the SOAP request with 1-2 secs delay that may avoid freezing of fragment upon calling Api. Or if UI is freezing whenever you're switching fragments from navigation drawer then you may have to manage your own fragment queue.
onActivityCreated() can be your choice and expensive work should be done in doInBackGround() method.

Android AsyncTask getting NetworkOnMainThreadException when called a second time

I'm getting some data off Parse.com in my app
When it first starts up, it checks the cache if available and displays it, then the user can pull-to-refresh to get the latest data
When the first refresh action is called, everything works great, but when I try to refresh a second time I get the NetworkOnMainThreadException force close
This is the calling method (I'm using Android support's swipe-to-refresh view)
#Override
public void onRefresh() {
// this part is merely a check, crashes both with or without this
if(!runningTask.getClass().equals(AsyncTask.Status.FINISHED))
runningTask.cancel(true);
runningTask = new DownloadEvents(true).execute();
}
This is the async task
private class DownloadEvents extends AsyncTask<Void, Void, ArrayList<Event>> {
boolean forceDownload;
String errorString = "";
public DownloadEvents(boolean forceDownload) {
this.forceDownload = forceDownload;
Parse.initialize(getActivity(), #API KEY CENSORED#);
}
// Do the long-running work in here
protected ArrayList<Event> doInBackground(Void... params) {
List<ParseObject> events = null;
PreferencesHelper ph = new PreferencesHelper(getActivity());
ParseQuery<ParseObject> eventsQuery = new ParseQuery<ParseObject>("events");
try {
eventsQuery.setCachePolicy(ParseQuery.CachePolicy.CACHE_ONLY);
events = eventsQuery.find();
} catch (ParseException e1) {
e1.printStackTrace();
}
if(forceDownload || System.currentTimeMillis() - ph.getLastEventsDownloadTime() > 43200000 || events == null)
{
swipeLayout.setRefreshing(true);
try {
eventsQuery.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ELSE_CACHE);
events = eventsQuery.find();
ph.setLastEventsDownloadTime();
} catch (ParseException e) {
e.printStackTrace();
}
}
// creating classes and sorting goes here
return eventsList;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(ArrayList<Event> events) {
if(events.size() > 0)
{
EventsAdapter adapter = new EventsAdapter(getActivity(), R.layout.events_card, events);
adapter.notifyDataSetChanged();
getListView().setAdapter(adapter);
}
if(errorString != "")
Toast.makeText(getActivity(), errorString, Toast.LENGTH_SHORT).show();
swipeLayout.setRefreshing(false);
}
}
Even if I force the download as the app start, it's always the second pulldown that crashes it, not the second time it downloads something
Please don't suggest turning off the NetworkOnMainThread strict rule, that's not a solution
Edit: here's the logcat
FATAL EXCEPTION: main
Process: com.mdk.test, PID: 24048
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
at com.android.org.conscrypt.OpenSSLSocketImpl.shutdownAndFreeSslNative(OpenSSLSocketImpl.java:1102)
at com.android.org.conscrypt.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:1097)
at org.apache.http.impl.SocketHttpClientConnection.close(SocketHttpClientConnection.java:205)
at org.apache.http.impl.conn.DefaultClientConnection.close(DefaultClientConnection.java:161)
at org.apache.http.impl.conn.tsccm.AbstractConnPool.closeConnection(AbstractConnPool.java:320)
at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.shutdown(ConnPoolByRoute.java:678)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.shutdown(ThreadSafeClientConnManager.java:256)
at com.parse.ParseRequest.initialize(ParseRequest.java:118)
at com.parse.Parse.initialize(Parse.java:109)
at com.mdk.test.EventsFragment$DownloadEvents.<init>(EventsFragment.java:136)
at com.mdk.test.EventsFragment.onRefresh(EventsFragment.java:223)
at android.support.v4.widget.SwipeRefreshLayout.startRefresh(SwipeRefreshLayout.java:441)
at android.support.v4.widget.SwipeRefreshLayout.onTouchEvent(SwipeRefreshLayout.java:399)
at android.view.View.dispatchTouchEvent(View.java:8073)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2253)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1987)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2198)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1649)
at android.app.Activity.dispatchTouchEvent(Activity.java:2717)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2159)
at android.view.View.dispatchPointerEvent(View.java:8263)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4013)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3892)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3454)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3473)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3583)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3481)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3640)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3454)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3473)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3481)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3454)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5682)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5656)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5627)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5761)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.view.InputEv
Parse.initialize() is in the async task constructor that gets executed in the main thread and it invokes a network operation.
Move the call to doInBackground().
It's hard to tell exactly where the problem occurs, because you didn't post the stacktrace, but this line looks suspicious:
swipeLayout.setRefreshing(true);
You can't modify any views on your doInBackground, and it looks like this might be doing just that.
Another fishy line is:
PreferencesHelper ph = new PreferencesHelper(getActivity());
Apparantly this object needs the activity, which may or may not cause a NetworkOnMainThread exception later on. You can't touch the UI in your doInBackGround method.
Just keep the doInBackground clean and only do the network stuff there, don't entangle it with other things.
event.size()
For null data will throw an exception error, however not sure if that is the exact issue you are facing.

AsyncTask Cancel is not working

I am learning how to cancel asyncTask so there is no uses on the code below.
I tried to called the asyncTask and execute it then cancel it and execute it.
MyAsyncTask asyncTask = new MyAsyncTask();
Log.i("cancel","cancel 1");
asyncTask.execute();
Log.i("cancel","cancel 2");
asyncTask.onCancelled();
Log.i("cancel","cancel 3");
asyncTask.execute();
Log.i("cancel","cancel done");
"cancel 1" and "cancel 2" is executed finely as it shown on logcat but ActivityThread.performLaunchActivity error is thrown when "cancel 3" is trying to execute.
(cancel 3 is not showing on logcat) Anything wrong with my asyncTask code?
private class MyAsyncTask extends AsyncTask<String,Integer,Void>{
private ArrayList<Map<String, String>> list;
private ProgressBar progressBar;
#Override
protected Void doInBackground(String... arg0) {
progressBar = (ProgressBar)findViewById(R.id.year_expense_progressbar);
progressBar.setVisibility(View.VISIBLE);
getListView().setVisibility(View.GONE);
textView.setVisibility(View.GONE);
list = new ArrayList<Map<String, String>>();
String time = "";
String category = "";
String expense = "";
String day = "";
String month = "";
totalExpense = 0;
Cursor c = SQLLiteAdapter.fetchAllItems();
while(c.moveToNext() != false){
if(isCancelled()){
Log.e("cancel","cancel inside background");
break;
}
// if there is nothing is input, don't execute verifyLevel
if(tokenizedResult.isEmpty()) break;
category = c.getString(c.getColumnIndex(SQLLiteAdapter.col_category));
expense = c.getString(c.getColumnIndex(SQLLiteAdapter.col_price));
time = c.getString(c.getColumnIndex(SQLLiteAdapter.col_time));
day = c.getString(c.getColumnIndex(SQLLiteAdapter.col_day));
month = c.getString(c.getColumnIndex(SQLLiteAdapter.col_month));
VerifyLevel a = new VerifyLevel(tokenizedResult,category,expense,time,day,month);
if(!a.isEmpty()){
list.add(a.addToList());
}
totalExpense += a.totalExpense;
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
progressBar.setVisibility(View.GONE);
getListView().setVisibility(View.VISIBLE);
textView.setVisibility(View.VISIBLE);
fillData(list);
textView.setText("Total Expense is "+convertNumeric(totalExpense));
Log.i("yearExpense","buildList is finished");
}
#Override
protected void onCancelled(){
super.onCancelled();
list.clear();
progressBar.setVisibility(View.GONE);
totalExpense = 0;
Log.i("yearEx","Cancel asyncTask");
Toast.makeText(getApplicationContext(), "cancelled", Toast.LENGTH_SHORT).show();
}
}
My approach is slightly different and perhaps, a little lengthy. But it has always worked without any issues.
This piece of code goes in the doInBackground(). If you have a for... loop in it, then use the break; statement. If you do not use a for.... loop, remove it.
// CHECK IF THE USER HAS CANCELLED THE TASK
if (isCancelled()) {
cancelTask = true; // (OPTIONAL) THIS IS AN ADDITIONAL CHECK I HAVE USED. THINK OF IT AS A FAIL SAFE.
break; // REMOVE IF NOT USED IN A FOR LOOP
}
You already have an Asynctask declared: MyAsyncTask asyncTask = new MyAsyncTask();. Along with that, also create two instances of boolean. Call them, for example:
boolean blMyAsyncTask;
boolean cancelTask;
Now, in the onPreExecute(), toggle the status of the blMyAsyncTask instance:
blMyAsyncTask = true;
And in the onPostExecute():
blMyAsyncTask = false;
And, in the same onPostExecute(), I also do the remainder functions after checking the state of the cancelTask boolean. For example:
if (cancelTask == false) {
// THE NORMAL CODE YOU HAVE IN YOUR onPostExecute()
}
Finally, in the onDestroy() (I use this, but I suspect the onPause() could work too. Never done it in the onPause() in all honesty), check the status of the boolean blMyAsyncTask
if (blMyAsyncTask== true) {
asyncTask.cancel(true);
}
As I said at the start, it is lengthy, perhaps even complicated, but it has never failed. I also think of this as a little modular if you would. If I have more Asycntasks added to the Activity, I can add another check in the onDestroy().
you should not call asyncTask.onCancelled(); directly. You can call cancel(true) and inside your doInBackground() you check for isCancelled().
To cancel a AsyncTask call the below line.
asyncTask.cancel();
onCancelled() is a override method that is executed when ever cancel is called.
You can use either
asynctask.cancel(true);
or
asyncTask.wait();
"true " if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete

Access closed cursor / AsyncTask

the following code works without problems on my N1. But from time to time I get a CrashReport from my users:
"android.database.StaleDataException: Access closed cursor
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:217)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:41)
at android.database.CursorWrapper.getString(CursorWrapper.java:135)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView.setRelationInfo(PartnerZodiacsView.java:456)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView.setReleationInfoAfterPostExecute(PartnerZodiacsView.java:449)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView.access$10(PartnerZodiacsView.java:447)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView$5.onPostExecute(PartnerZodiacsView.java:440)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView$5.onPostExecute(PartnerZodiacsView.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:417)
at android.os.AsyncTask.access$300(AsyncTask.java:127)
The code-part is:
public void updateRelationInfoAsync() {
new AsyncTask<Void, Void, Void>() {
private Cursor cursorRelation = null;
#Override
protected Void doInBackground(final Void... voids) {
try {
cursorRelation = ProviderQueries.getInstance().getRelationByID(PartnerZodiacsView.this, firstRelationUID, secondRelationUID);
}
catch (final RelationNotSetException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final Void result) {
super.onPostExecute(result);
setReleationInfoAfterPostExecute(cursorRelation);
cursorRelation = null;
}
}.execute();
}
private synchronized void setReleationInfoAfterPostExecute(final Cursor cursorRelation) {
if (cursorRelation != null && (!cursorRelation.isClosed())) {
setRelationInfo(cursorRelation);
setRatings(cursorRelation);
cursorRelation.close();
}
}
private void setRelationInfo(final Cursor cursor) {
maininfo.setText(cursor.getString(cursor.getColumnIndex(RelationDAO.Colums.DESCRIPTION)));
final String name = cursor.getString(cursor.getColumnIndex(RelationDAO.Colums.RELATIONNAME));
AnalyticsUtils.getInstance(this).trackPageView("/relationdisplayed?name=" + URLEncoder.encode(name));
}
I don't know what causes this error, as said it's not reproducible on my N1 and in the emulator but the more important thing is that it's absolutely unclear to me why this can happen if I check for Cursor.isClosed
The method doInBackground always runs in the background thread and the method onPostExecute runs on the UI Thread.
You have created the object of the cursor in the background thread scope and by the time you reach the onPostExecute the background thread might have been closed thus ending the lifetime of the cursor object.
So, create the cursor object in your UI thread a pass a reference of the cursor object to your ASyncTask.
Since this completely depends on the timing of the closure of the background thread it is definitely becomes device specific
It could very well be related to the timing of specific orientation changes: if the parent Activity is killed due to an orientation change while the task is running, the cursor may very well be closed.

Asynctask Error Handling

I am using AsyncTask to perform some background calculations but I am unable to find a correct way to handle exceptions. Currently I am using the following code:
private class MyTask extends AsyncTask<String, Void, String>
{
private int e = 0;
#Override
protected String doInBackground(String... params)
{
try
{
URL url = new URL("http://www.example.com/");
}
catch (MalformedURLException e)
{
e = 1;
}
// Other code here...
return null;
}
#Override
protected void onPostExecute(String result)
{
if (e == 1)
Log.i("Some Tag", "An error occurred.");
// Perform post processing here...
}
}
I believe that the variable e maye be written/accessed by both the main and worker thread. As I know that onPostExecute() will only be run after doInBackround() has finished, can I omit any synchronization?
Is this bad code? Is there an agreed or correct way to handle exceptions in an AsyncTask?
I've been doing that in my apps, I guess there is not a better way.
You can also read Mark Murphy answer about it.
I think your code would to the job but there is already some kind of error handling built into the AsyncTask class.
You can avoid to use an extra variable by using the cancel() method and its handler method onCancelled(). When you call cancel within the doInBackground() method the onCancelled method in the UI thread. Whether you call cancel(true) or cancel(false) depends on your needs.
private class MyTask extends AsyncTask<String, Void, String>
{
#Override
protected NewsItem doInBackground(String... params)
{
try
{
URL url = new URL("http://www.example.com/");
}
catch (MalformedURLException e)
{
cancel(false/true);
}
// Other code here...
return null;
}
#Override
protected void onPostExecute(String result)
{
// Perform successful post processing here...
}
#Override
protected void onCancelled() {
super.onCancelled();
// Perform error post processing here...
}
}
This is guaranteed to work, even on SMP architecture. All the synchronization is done for you. It would however be better to use the return value to do this.

Categories

Resources