Android: AsyncTask behaving weird in onCreate - android

I'm executing the practically identical code (besides the return statement) in onCreate() in two different ways:
once in a Thread (that works)
and once in an AsyncTask
Somehow the Exception thrown in the AsyncTask can't even be debugged... do you have an idea why this code doesn't work in the AsyncTask and why I can't debug de Exception? (It is not present as a variable)
public class TrainingProgressActivity extends ActivityTemplate {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_training_progress);
// the not working AsyncTask variant
new ProgressGetterTask().execute("");
// the working Thread variant
new Thread(new Runnable() {
public void run() {
try {
RestTemplate restTemplate = RestTemplateFactory.createRestTemplate();
FeatureSetCollectionProgress i = restTemplate.postForObject(URLHelper.BASE_PATH+"training/progress", getDevice(), FeatureSetCollectionProgress.class);
System.out.println(i.getMobilityProgress().get(0).getTransportationMeanType().toString());
} catch(Exception e) {
System.out.println("ex");
e.printStackTrace();
}
}}).start();
}
/**
* ProgressGetterTask. (not working ???)
*/
private class ProgressGetterTask extends AsyncTask<String, FeatureSetCollectionProgress, FeatureSetCollectionProgress> {
protected FeatureSetCollectionProgress doInBackground(String... urls) {
try {
RestTemplate restTemplate = RestTemplateFactory.createRestTemplate();
return restTemplate.postForObject(URLHelper.BASE_PATH+"training/progress", getDevice(), FeatureSetCollectionProgress.class);
} catch(Exception e) {
e.printStackTrace();
return null; // setting breakpoint here, 'e' cannot be resolved to a variable.
}
}
protected void onPostExecute(FeatureSetCollectionProgress featureSetCollectionProgress) {
if(featureSetCollectionProgress!=null) {
} else {
}
}
}
}

Related

Series of AsyncTask does not go for execution instantaneously

My MainActivity has 2 views: TextView and a Button. On button click, I am running an AsyncTask which further creates 10 new AsyncTasks for network operations. Every new task creation is delayed by 1 sec. The code is:
public class MainActivity extends ActionBarActivity
{
TextView tv;
Button t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
t = (Button) findViewById(R.id.toggleButton1);
t.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
getData();
}
});
}
void getData()
{
SuperNetworkAsyncTask s = new SuperNetworkAsyncTask();
s.execute("");
}
private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
for(int i=0;i<10;i++)
{
{
nTask = new NetworkAsyncTask();
nTask.execute("");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return "";
}
#Override
protected void onPostExecute(String result)
{
}
}
private class NetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
return String.valueOf(System.currentTimeMillis());
}
#Override
protected void onPostExecute(String result)
{
tv.setText(result);
}
}
}
I was expecting that the moment first NetworkAsyncTask execute method is called, it will start execution. But when I run it, I do not find any NetworkAsyncTask begin its execution until the control comes out of SuperNetworkAsyncTask. Is there any way to push the execution of NetworkAsyncTask thread as soon as execute method is called?
Some clarifications:
Why NetworkAsyncTask are created by SuperNetworkAsyncTask? Because If I create the NetworkAsyncTask in main thread, I get my UI freeze for some time.
Why making 10 object? The purpose of NetworkAsyncTask is to read data from a server at interval of 1 sec for n seconds, here n=10.
Part 2: Updates after doing some tests.
Observation 1:
As a fellow Brian shared a way to avoid creating AsyncTasks in nested way, I tried his code:
void getData() {
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
nTask = new NetworkAsyncTask();
nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
}
This freezes my UI for few seconds and then the screen is updated in a fraction of second. It is quite surprising to me too.
Observation 2:
With java.lang.Thread, I experimented to make sure that 1) The threads should be executed right away when run() called. 2) The next task will be created only after previous task is finished.
Code:
public static void main(String[] args) {
myThread m;
for (int i=0;i<10;i++)
{
m=new myThread(String.valueOf(i));
m.start();
synchronized (m)
{
try {
m.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class myThread extends Thread
{
public String name = "";
public myThread(String n)
{
name = n;
}
public void run()
{
synchronized (this)
{
System.out.println(" Thread Name = " + name);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll();
}
}
}
Output:
Thread Name = 0
Thread Name = 1
Thread Name = 2
Thread Name = 3
Thread Name = 4
Thread Name = 5
Thread Name = 6
Thread Name = 7
Thread Name = 8
Thread Name = 9
Based in this, I updated my NetworkAsyncTask & SuperNetworkAsyncTask as:
private class NetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
synchronized (this)
{
return String.valueOf(System.currentTimeMillis());
}
}
#Override
protected void onPostExecute(String result)
{
synchronized (this)
{
tv.setText(result);
notifyAll();
}
}
}
private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
for(int i=0;i<10;i++)
{
nTask = new NetworkAsyncTask();
nTask.execute(url);
synchronized (nTask)
{
try {
nTask.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return "";
}
#Override
protected void onPostExecute(String result)
{
}
}
With this code the wait() keeps on waiting indefinitely.
Finally I replaced:
nTask.execute(url);
with
nTask.executeOnExecutor(THREAD_POOL_EXECUTOR, "");
This worked well as expected.
The UI will be updated only at onPostExecute(). See notes on AsyncTask
Click here! And Try to avoid 10 AysncTasks, it does not make any sense.
You don't need to use a "super async task" use a runnable and then create new async tasks in parallel
void getData() {
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
nTask = new NetworkAsyncTask();
nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
}
Post honeycomb you can specify to run async tasks in parallel
An AsyncTask should be started in the UI thread, not on the one doInBackground runs on. You could call publishProgress after every sleep, and spawn each AsyncTask in the resulting calls to onProgressUpdate, which run on the UI thread.

Can't get async task to work

I was calling a class which was performing network operations on the main thread, causing my app to blow up on more recent devices. So I've tried moving the call to the class into a AsyncTask inner class in my main activity. However now i'm getting null reference expections.
Here's my AsyncTask:
private class RetreiveAmazonNodesXML extends AsyncTask {
private Exception exception;
#Override
protected Object doInBackground(Object... params) {
try {
childrenBrowseNodesXml = new Amazon(browseNodeId, locality);
} catch (Exception e) {
this.exception = e;
}
return null;
}
}
And here's where I call it in my activity:
RetreiveAmazonNodesXML test = new RetreiveAmazonNodesXML();
test.execute();
parseXmlFile(childrenBrowseNodesXml.getBrowseNodesXML());
childrenBrowseNodesXml isn't getting updated and returning null. I know my Amazon class works fine so its something im doing with AsyncTask, but I have no idea?
Use callback for get result from async task. Here interface callback class:
public interface Callback {
public void onSuccess(Object data);
public void onError(String errorMsg);
}
And create instance this class and implement its:
final Callback resCallback = new Callback() {
#Override
public void onSuccess(Object data) {
parseXmlFile(data);
}
#Override
public void onError(String errorMsg) {
//show error with Alert or Toast
}
};
And create asynctask class with your callback:
RetreiveAmazonNodesXML test = new RetreiveAmazonNodesXML(resCallback);
test.execute(yourObjectsParams);
Write asynctask class like this:
private class RetreiveAmazonNodesXML extends AsyncTask {
private Callback responderCallback;
private Exception exception;
public GeneralHttpTask(Callback callback){
this.responderCallback = callback;
}
#Override
protected Object doInBackground(Object... params) {
try {
Amazon childrenBrowseNodesXml = new Amazon(browseNodeId, locality);
return childrenBrowseNodesXml;
} catch (Exception e) {
this.exception = e;
}
return null;
}
#Override
protected void onPostExecute(Object result) {
if(result != null) {
responderCallback.onSuccess(result);
} else {
responderCallback.onError(exception);
}
}
}
It is because you're trying to use the value that AsyncTask hasn't returned, as AsyncTask is running asyncronously.
You should put parseXmlFile(childrenBrowseNodesXml.getBrowseNodesXML()); into your AsyncTask's onPostExecute() method, like this:
private class RetreiveAmazonNodesXML extends AsyncTask {
private Exception exception;
#Override
protected Object doInBackground(Object... params) {
try {
childrenBrowseNodesXml = new Amazon(browseNodeId, locality);
} catch (Exception e) {
this.exception = e;
}
return null;
}
#Override
protected void onPostExecute(Object obj) {
parseXmlFile(childrenBrowseNodesXml.getBrowseNodesXML());
}
}
Also, return null in doInBackground method may not be a good manner, the stuff that doInBackground returns will be passed as a parameter to onPostExecute() method automatically by AsyncTask.
For more about the AsyncTask, please refer to the Android Developers: AsyncTask
The problem is, that you create a background thread (AsyncTask) that fills the childrenBrowseNodesXml after a while (when it's actually executed), but you try to use it immediately in your activity code.
Move your parseXMLFile to onPostExecute(Void result) method of AsyncTask instead.

Performing data loading unitl succesfull or user break

In my app I performing loading data from web and then displaying it to user. Before loading data app shows progress dialog. I have problem if user locks phone in the middle of loading operation, or server is overloaded and can't respond in time my application freezes, because it doesn't dismiss progress dialog, or in some cases it crashes because lack on needed data.
If some error happened while loading data I want show some dialog to user to let him know about error and ask him should application repeat last request. I tried to use AlertDialog for it, but I haven't succeed.
Here is code of one activity (There is no progress dialog here, but it demonstrates how I loading data):
#EActivity(R.layout.layout_splash)
#RoboGuice
public class SplashScreenActivity extends Activity {
#Inject
private AvtopoiskParserImpl parser;
#Bean
BrandsAndRegionsHolder brandsAndRegionsHolder;
#ViewById(R.id.splash_progress)
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();
}
#Background
protected void loadData() {
publishProgress(10);
LinkedHashMap<String, Integer> brands = null;
try {
brands = parser.getBrands();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(50);
LinkedHashMap<String, Integer> regions = null;
try {
regions = parser.getRegions();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(70);
populateData(brands, regions);
}
#UiThread
protected void populateData(LinkedHashMap<String, Integer> brands, LinkedHashMap<String, Integer> regions) {
Intent intent = new Intent(SplashScreenActivity.this, SearchActivity_.class);
brandsAndRegionsHolder.brandsMap = brands;
brandsAndRegionsHolder.regionsMap = regions;
publishProgress(100);
startActivity(intent);
finish();
}
#UiThread
void publishProgress(int progress) {
progressBar.setProgress(progress);
}
}
parser.getBrands() and parser.getRegions() are loading data from the web.
I want to do something like this:
boolean repeatRequest = true;
while (repeatRequest) {
try {
brands = parser.getBrands();
repeatRequest = false;
} catch (IOException e) {
Log.e(e.getMessage());
repeatRequest = showErrorDialog();
}
}
But I didn't manage to do so because this code executes in background thread, but dialog should be shown in UI thread.
I believe that it should be standard approach of doing so, but didn't manage to find it.
Any ides how can I implement this?
The best way is to use AsyncTask.
private class LoadDataTask extends AsyncTask<Void, Integer, Object> {
private ProgressDialog mProgress;
protected Object doInBackground(Void... params) {
// This method runs in background
Object result = null;
try {
result = parser.parse();
} catch (Exception e) {
result = e.getMessage();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
// This method runs in UI thread
mProgress.setProgress(progress[0]);
}
protected void onPreExecute() {
// This method runs in UI thread
mProgress = new ProgressDialog(context);
mProgress.show();
}
protected void onPostExecute(Object result) {
// This method runs in UI thread
mProgress.dismiss();
if (result instance of String) {
// Here you can launch AlertDialog with error message and proposal to retry
showErrorDialog((String) result);
} else {
populateData(result);
}
}
}

How can I call a statement after two asyncTask calls in Android?

I have a method like:
void doStuffs() {
new asyncCall1().execute();
new asyncCall2().execute();
}
How can I call another method after the two async calls have ended?
Use the get method to wait for the work to complete in a third async task:
(new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
asyncCall1.execute((Void)null);
asyncCall2.execute((Void)null);
try {
asyncCall1.get();
asyncCall2.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return (Void)null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}).execute((Void)null);
You need to invoke the method from the AsyncTask. The easiest way would be to wrap the statement in a public static method within your activity. Otherwise, you can pass the AsyncTask a reference to the activity. The classiest way to do it would be to use a Handler
Either way, your AsyncTask should go
#Override
onPostExecute(Result r)
{
//logic goes here
}
Maybe pass a Handler in to both the AsyncTasks which get called onPostExecute and build logic in to the handler :
Handler asyncTaskHandler = new Handler() {
private boolean firstTaskComplete = false;
#Override
public void handleMessage(Message msg) {
synchronized (firstTaskComplete ) {
if(!firstTaskComplete) {
firstTaskComplete = true;
} else {
// call some other code
}
}
}
};

AsyncTask and error handling on Android

I'm converting my code from using Handler to AsyncTask. The latter is great at what it does - asynchronous updates and handling of results in the main UI thread. What's unclear to me is how to handle exceptions if something goes haywire in AsyncTask#doInBackground.
The way I do it is to have an error Handler and send messages to it. It works fine, but is it the "right" approach or is there better alternative?
Also I understand that if I define the error Handler as an Activity field, it should execute in the UI thread. However, sometimes (very unpredictably) I will get an Exception saying that code triggered from Handler#handleMessage is executing on the wrong thread. Should I initialize error Handler in Activity#onCreate instead? Placing runOnUiThread into Handler#handleMessage seems redundant but it executes very reliably.
It works fine but is it the "right"
approach and is there better
alternative?
I hold onto the Throwable or Exception in the AsyncTask instance itself and then do something with it in onPostExecute(), so my error handling has the option of displaying a dialog on-screen.
Create an AsyncResult object ( which you can also use in other projects)
public class AsyncTaskResult<T> {
private T result;
private Exception error;
public T getResult() {
return result;
}
public Exception getError() {
return error;
}
public AsyncTaskResult(T result) {
super();
this.result = result;
}
public AsyncTaskResult(Exception error) {
super();
this.error = error;
}
}
Return this object from your AsyncTask doInBackground methods and check it in the postExecute. ( You can use this class as a base class for your other async tasks )
Below is a mockup of a task that gets a JSON response from the web server.
AsyncTask<Object,String,AsyncTaskResult<JSONObject>> jsonLoader = new AsyncTask<Object, String, AsyncTaskResult<JSONObject>>() {
#Override
protected AsyncTaskResult<JSONObject> doInBackground(
Object... params) {
try {
// get your JSONObject from the server
return new AsyncTaskResult<JSONObject>(your json object);
} catch ( Exception anyError) {
return new AsyncTaskResult<JSONObject>(anyError);
}
}
protected void onPostExecute(AsyncTaskResult<JSONObject> result) {
if ( result.getError() != null ) {
// error handling here
} else if ( isCancelled()) {
// cancel handling here
} else {
JSONObject realResult = result.getResult();
// result handling here
}
};
}
When I feel the need to handle Exceptions in AsyncTask properly, I use this as super class:
public abstract class ExceptionAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
private Exception exception=null;
private Params[] params;
#Override
final protected Result doInBackground(Params... params) {
try {
this.params = params;
return doInBackground();
}
catch (Exception e) {
exception = e;
return null;
}
}
abstract protected Result doInBackground() throws Exception;
#Override
final protected void onPostExecute(Result result) {
super.onPostExecute(result);
onPostExecute(exception, result);
}
abstract protected void onPostExecute(Exception exception, Result result);
public Params[] getParams() {
return params;
}
}
As normal, you override doInBackground in your subclass to do background work, happily throwing Exceptions where needed. You are then forced to implement onPostExecute (because it's abstract) and this gently reminds you to handle all types of Exception, which are passed as parameter. In most cases, Exceptions lead to some type of ui output, so onPostExecute is a perfect place to do that.
If you want to use the RoboGuice framework which brings you other benefits you can try the RoboAsyncTask which has an extra Callback onException(). Works real good and I use it.
http://code.google.com/p/roboguice/wiki/RoboAsyncTask
I made my own AsyncTask subclass with an interface that defines callbacks for success and failure. So if an exception is thrown in your AsyncTask, the onFailure function gets passed the exception, otherwise the onSuccess callback gets passed your result. Why android doesn't have something better available is beyond me.
public class SafeAsyncTask<inBackgroundType, progressType, resultType>
extends AsyncTask<inBackgroundType, progressType, resultType> {
protected Exception cancelledForEx = null;
protected SafeAsyncTaskInterface callbackInterface;
public interface SafeAsyncTaskInterface <cbInBackgroundType, cbResultType> {
public Object backgroundTask(cbInBackgroundType[] params) throws Exception;
public void onCancel(cbResultType result);
public void onFailure(Exception ex);
public void onSuccess(cbResultType result);
}
#Override
protected void onPreExecute() {
this.callbackInterface = (SafeAsyncTaskInterface) this;
}
#Override
protected resultType doInBackground(inBackgroundType... params) {
try {
return (resultType) this.callbackInterface.backgroundTask(params);
} catch (Exception ex) {
this.cancelledForEx = ex;
this.cancel(false);
return null;
}
}
#Override
protected void onCancelled(resultType result) {
if(this.cancelledForEx != null) {
this.callbackInterface.onFailure(this.cancelledForEx);
} else {
this.callbackInterface.onCancel(result);
}
}
#Override
protected void onPostExecute(resultType result) {
this.callbackInterface.onSuccess(result);
}
}
A more comprehensive solution to Cagatay Kalan's solution is shown below:
AsyncTaskResult
public class AsyncTaskResult<T>
{
private T result;
private Exception error;
public T getResult()
{
return result;
}
public Exception getError()
{
return error;
}
public AsyncTaskResult(T result)
{
super();
this.result = result;
}
public AsyncTaskResult(Exception error) {
super();
this.error = error;
}
}
ExceptionHandlingAsyncTask
public abstract class ExceptionHandlingAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, AsyncTaskResult<Result>>
{
private Context context;
public ExceptionHandlingAsyncTask(Context context)
{
this.context = context;
}
public Context getContext()
{
return context;
}
#Override
protected AsyncTaskResult<Result> doInBackground(Params... params)
{
try
{
return new AsyncTaskResult<Result>(doInBackground2(params));
}
catch (Exception e)
{
return new AsyncTaskResult<Result>(e);
}
}
#Override
protected void onPostExecute(AsyncTaskResult<Result> result)
{
if (result.getError() != null)
{
onPostException(result.getError());
}
else
{
onPostExecute2(result.getResult());
}
super.onPostExecute(result);
}
protected abstract Result doInBackground2(Params... params);
protected abstract void onPostExecute2(Result result);
protected void onPostException(Exception exception)
{
new AlertDialog.Builder(context).setTitle(R.string.dialog_title_generic_error).setMessage(exception.getMessage())
.setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
//Nothing to do
}
}).show();
}
}
Example Task
public class ExampleTask extends ExceptionHandlingAsyncTask<String, Void, Result>
{
private ProgressDialog dialog;
public ExampleTask(Context ctx)
{
super(ctx);
dialog = new ProgressDialog(ctx);
}
#Override
protected void onPreExecute()
{
dialog.setMessage(getResources().getString(R.string.dialog_logging_in));
dialog.show();
}
#Override
protected Result doInBackground2(String... params)
{
return new Result();
}
#Override
protected void onPostExecute2(Result result)
{
if (dialog.isShowing())
dialog.dismiss();
//handle result
}
#Override
protected void onPostException(Exception exception)
{
if (dialog.isShowing())
dialog.dismiss();
super.onPostException(exception);
}
}
This simple class can help you
public abstract class ExceptionAsyncTask<Param, Progress, Result, Except extends Throwable> extends AsyncTask<Param, Progress, Result> {
private Except thrown;
#SuppressWarnings("unchecked")
#Override
/**
* Do not override this method, override doInBackgroundWithException instead
*/
protected Result doInBackground(Param... params) {
Result res = null;
try {
res = doInBackgroundWithException(params);
} catch (Throwable e) {
thrown = (Except) e;
}
return res;
}
protected abstract Result doInBackgroundWithException(Param... params) throws Except;
#Override
/**
* Don not override this method, override void onPostExecute(Result result, Except exception) instead
*/
protected void onPostExecute(Result result) {
onPostExecute(result, thrown);
super.onPostExecute(result);
}
protected abstract void onPostExecute(Result result, Except exception);
}
Another way that doesn't depend on variable member sharing is to use cancel.
This is from android docs:
public final boolean cancel (boolean mayInterruptIfRunning)
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.
So you can call cancel in catch statement and be sure that onPostExcute is never called, but instead onCancelled is invoked on UI thread. So you can show the error message.
Actually, AsyncTask use FutureTask & Executor, FutureTask support exception-chain
First let's define a helper class
public static class AsyncFutureTask<T> extends FutureTask<T> {
public AsyncFutureTask(#NonNull Callable<T> callable) {
super(callable);
}
public AsyncFutureTask<T> execute(#NonNull Executor executor) {
executor.execute(this);
return this;
}
public AsyncFutureTask<T> execute() {
return execute(AsyncTask.THREAD_POOL_EXECUTOR);
}
#Override
protected void done() {
super.done();
//work done, complete or abort or any exception happen
}
}
Second, let's use
try {
Log.d(TAG, new AsyncFutureTask<String>(new Callable<String>() {
#Override
public String call() throws Exception {
//throw Exception in worker thread
throw new Exception("TEST");
}
}).execute().get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
//catch the exception throw by worker thread in main thread
e.printStackTrace();
}
or use FutureTask directly like below
FutureTask<?> futureTask = new FutureTask(() -> {throw new RuntimeException("Exception in TaskRunnable");}) {
#Override
protected void done() {
super.done();
//do something
Log.d(TAG,"FutureTask done");
}
};
AsyncTask.THREAD_POOL_EXECUTOR.execute(futureTask);
try {
futureTask.get();
} catch (ExecutionException | InterruptedException e) {
Log.d(TAG, "Detect exception in futureTask", e);
}
logcat as below
Personally, I will use this approach.
You can just catch the exceptions and print out the stack trace if you need the info.
make your task in background return a boolean value.
it's like this:
#Override
protected Boolean doInBackground(String... params) {
return readXmlFromWeb(params[0]);
}
#Override
protected void onPostExecute(Boolean result) {
if(result){
// no error
}
else{
// error handling
}
}
Another possibility would be to use Object as return type, and in onPostExecute() check for the object type. It is short.
class MyAsyncTask extends AsyncTask<MyInObject, Void, Object> {
#Override
protected AsyncTaskResult<JSONObject> doInBackground(MyInObject... myInObjects) {
try {
MyOutObject result;
// ... do something that produces the result
return result;
} catch (Exception e) {
return e;
}
}
protected void onPostExecute(AsyncTaskResult<JSONObject> outcome) {
if (outcome instanceof MyOutObject) {
MyOutObject result = (MyOutObject) outcome;
// use the result
} else if (outcome instanceof Exception) {
Exception e = (Exception) outcome;
// show error message
} else throw new IllegalStateException();
}
}
If you know the correct exception then you can call the
Exception e = null;
publishProgress(int ...);
eg:
#Override
protected Object doInBackground(final String... params) {
// TODO Auto-generated method stub
try {
return mClient.call(params[0], params[1]);
} catch(final XMLRPCException e) {
// TODO Auto-generated catch block
this.e = e;
publishProgress(0);
return null;
}
}
and go to "onProgressUpdate" and do the folowing
#Override
protected void onProgressUpdate(final Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
mDialog.dismiss();
OptionPane.showMessage(mActivity, "Connection error", e.getMessage());
}
This will be helpful in some cases only. Also you can keep a Global Exception variable and access the exception.

Categories

Resources