我想在doInBackground中捕获线程的异常并在onPostExcecute中打印错误消息。问题是我在onPostExecute中没有Throwable对象。如何在非UI线程中捕获异常并在UI线程中打印错误消息?
public class TestTask extends AsyncTask<Void, Void, List<String>> {
@Override
protected List<String> doInBackground(final Void... params) {
try {
...
return listOfString;
} catch(SomeCustomException e) {
...
return null;
}
}
@Override
protected void onPostExecute(final List<String> result) {
if(result == null) {
// print the error of the Throwable "e".
// The problem is I don't have the Throwable object here! So I can't check the type of exception.
}
}
}
Arun回答后更新:
这是我的AsyncTask包装类。它打算在doInBackground中处理异常,但我找不到一个好的解决方案。
public abstract class AbstractWorkerTask<Params, Progress, Result>
extends AsyncTask<Params, Progress, Result>
implements Workable {
protected OnPreExecuteListener onPreExecuteListener;
protected OnPostExecuteListener<Result> onPostExecuteListener;
protected ExceptionHappenedListener exceptionHappendedListener;
private boolean working;
@Override
protected void onPreExecute() {
if (onPreExecuteListener != null) {
onPreExecuteListener.onPreExecute();
}
working = true;
}
@Override
protected void onPostExecute(final Result result) {
working = false;
if(/* .........*/ ) {
exceptionHappendedListener.exceptionHappended(e);
}
if (onPostExecuteListener != null) {
onPostExecuteListener.onPostExecute(result);
}
}
@Override
public boolean isWorking() {
return working;
}
public void setOnPreExecuteListener(final OnPreExecuteListener onPreExecuteListener) {
this.onPreExecuteListener = onPreExecuteListener;
}
public void setOnPostExecuteListener(final OnPostExecuteListener<Result> onPostExecuteListener) {
this.onPostExecuteListener = onPostExecuteListener;
}
public void setExceptionHappendedListener(final ExceptionHappenedListener exceptionHappendedListener) {
this.exceptionHappendedListener = exceptionHappendedListener;
}
public interface OnPreExecuteListener {
void onPreExecute();
}
public interface OnPostExecuteListener<Result> {
void onPostExecute(final Result result);
}
public interface ExceptionHappenedListener {
void exceptionHappended(Exception e);
}
}
答案 0 :(得分:7)
将doInBackground()
的返回类型更改为Object
,当您在onPostExecute(Object result)
收到结果时,请使用instanceOf
运算符检查返回的结果是否为{{1 }或Exception
。
修改强>
由于结果可以是Exception,也可以是正确的List,您可以使用以下命令:
List<String>
同时更改以下声明:
protected void onPostExecute(final Object result) {
working = false;
if(result instanceof SomeCustomException) {
exceptionHappendedListener.exceptionHappended(result);
}
else{
if (onPostExecuteListener != null) {
onPostExecuteListener.onPostExecute(result);
}
}
}
答案 1 :(得分:4)
只需将Exception存储到列表中并稍后处理,因为onPostExecute()总是在doInBackground()之后调用:
public class TestTask extends AsyncTask<Params, Progress, Result> {
List<Exception> exceptions = new ArrayList<Exception>();
@Override
protected Result doInBackground(Params... params) {
try {
...
} catch(SomeCustomException e) {
exceptions.add(e);
}
return result;
}
@Override
protected void onPostExecute(Result result) {
for (Exception e : exceptions) {
// Do whatever you want for the exception here
...
}
}
}
这是可行但很少使用,因为在大多数情况下,我们希望一旦被抛出并捕获就处理异常:
public class TestTask extends AsyncTask<Params, Progress, Result> {
@Override
protected Result doInBackground(Params... params) {
try {
...
} catch(SomeCustomException e) {
// If you need update UI, simply do this:
runOnUiThread(new Runnable() {
public void run() {
// update your UI component here.
myTextView.setText("Exception!!!");
}
});
}
return result;
}
}
希望这是有道理的。
答案 2 :(得分:4)
将doInBackground
的返回类型更改为Object
可能会传递Exception
,然后使用instanceof()
是代码异味的来源(糟糕的编程习惯)。最好将返回类型限制为您想要返回的特定内容。
根据此answer,只需添加一个私有成员来存储doInBackground
中抛出的异常,然后在onPostExecute
中首先检查它。
只需要捕获一个Exception
因为您应该在抛出异常后立即停止doInBackground
中的操作,并在onPostExecute
中正常处理它,您可以访问UI元素和所以可以告知用户不幸事故。
通用示例(AsyncTask的主体):
private Exception mException
@Override
protected Result doInBackground(Params... params) {
try {
// --- Do something --- //
}
catch( SomeException e ){ mException = e; return null; }
}
@Override
protected void onPostExecute(Result result) {
if (mException != null) {
// --- handle exception --- //
return;
}
// --- Perform normal post execution actions --- //
}