我正在使用使用代码 HandlerAsyncTask. 。后者的作用非常出色 - 主UI线程中的异步更新和结果处理。我不清楚的是如何处理异常吗? AsyncTask#doInBackground.

我这样做的方法是拥有一个错误处理程序并向其发送消息。它可以正常工作,但是它是“正确的”方法还是更好的选择?

另外,我了解,如果将错误处理程序定义为活动字段,则应在UI线程中执行。但是,有时(非常不可预测)我会得到一个例外,说代码是从 Handler#handleMessage 在错误的线程上执行。我应该初始化错误处理程序 Activity#onCreate 反而?放置 runOnUiThread 进入 Handler#handleMessage 似乎是多余的,但执行非常可靠。

有帮助吗?

解决方案

它运行良好,但这是“正确”的方法,还有更好的选择吗?

我坚持 Throwable 或者 Exception 在里面 AsyncTask 实例本身,然后在其中做某事 onPostExecute(), ,因此我的错误处理可以选择在屏幕上显示对话框。

其他提示

创建一个异步对象(您也可以在其他项目中使用)

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;
    }
}

从您的异步back doinbackground方法返回此对象,然后在执行后检查。 (您可以将此类用作其他异步任务的基类)

以下是对Web服务器获得JSON响应的任务的模型。

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
            }
        };

    }

当我觉得需要处理例外 AsyncTask 正确地,我将其用作超级类:

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;
    }

}

正常,你覆盖 doInBackground 在您的子类中进行背景工作,在需要时愉快地抛出例外。然后,您被迫实施 onPostExecute (因为它是抽象的),这轻轻地提醒您处理所有类型的 Exception, ,作为参数传递。在大多数情况下,异常导致某种类型的UI输出,因此 onPostExecute 是这样做的理想场所。

如果您想使用Roboguice框架,该框架带来了其他好处,则可以尝试具有额外回调Onexception()的RoboAsynctask。效果非常好,我使用它。http://code.google.com/p/roboguice/wiki/roboasynctask

我用一个界面制作了自己的异步子类,该接口定义了成功和失败的回调。因此,如果在异步箱中抛出异常,则通过onfailure函数将通过异常,否则启用回调将通过您的结果。为什么Android没有更好可用的东西。

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);
    }
}

一个更全面的解决方案 卡加泰·卡兰(Cagatay Kalan)解决方案如下所示:

异步

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;
    }
}

异常handlingasynctask

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();
    }
}

示例任务

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);
    }
}

这个简单的课可以帮助您

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);
}

不依赖可变成员共享的另一种方法是使用取消。

这是来自Android文档:

公共最终布尔式取消(布尔梅特雷特iruptrument)

试图取消执行此任务。如果任务已经完成,已经被取消或由于某些其他原因无法取消,则此尝试将失败。如果成功,并且在调用取消时尚未开始此任务,则该任务绝不应运行。如果任务已经启动,则可能会中断执行此任务的线程是否应中断,以试图停止任务。

调用此方法将导致在doinbackground(Object [])返回后在UI线程上调用的OnCancell(对象)。称此方法可以确保永远不会调用OnPostExecute(对象)。调用此方法后,您应该定期从doinbackground(object [])定期检查Iscancelled()返回的值,以尽早完成任务。

因此,您可以在Catch语句中调用CAMPUL,并确保从未调用OnPostExcute,而是在UI线程上调用了OnCancell。因此,您可以显示错误消息。

实际上,异步使用FutureTask&Executor,FutureTask支持异常链首先定义一个助手类

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
    }
}

其次,让我们使用

    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();
    }

就个人而言,我将使用这种方法。如果需要信息,您只需捕获异常并打印出堆栈跟踪即可。

使您的任务在后台返回布尔值。

就像这样:

    @Override
                protected Boolean doInBackground(String... params) {
                    return readXmlFromWeb(params[0]);
         }

        @Override
                protected void onPostExecute(Boolean result) {

              if(result){
              // no error
               }
              else{
                // error handling
               }
}

另一个可能是使用 Object 作为返回类型,在 onPostExecute() 检查对象类型。很短。

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();
    }
}

如果您知道正确的例外,则可以致电

Exception e = null;

publishProgress(int ...);

例如:

@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;
    }
}

然后转到“ OnProgressupdate”并进行效果

@Override
protected void onProgressUpdate(final Integer... values) {

    // TODO Auto-generated method stub
    super.onProgressUpdate(values);
    mDialog.dismiss();
    OptionPane.showMessage(mActivity, "Connection error", e.getMessage());
}

这仅在某些情况下会有所帮助。您也可以保留 Global Exception 变量并访问异常。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top