Back to Xutils3

2.任务和回调

xutils/docs/2.任务和回调.md

3.9.04.7 KB
Original Source

xUtils中的任务和回调接口

任务和回调是网络请求的基础接口, xUtils的任务接口支持异步和同步任务的实现.

  1. 为什么要设计新的接口, 而不使用Android系统API AsyncTask? 原因有几个方面, AsyncTask在各个版本系统中表现不一致, 包括默认任务的并发数, 是否可在子线程中使用等.

  2. xUtils中的任务和回调接口特点是什么?

    • 可以在任何线程中直接使用.
    • 支持设置优先级.
    • 支持异步调用和同步调用.
    • 默认支持FIFO和FILO, 也可以使用自定义Executor.
    • 异步任务中所有错误(包括异步过程和回调操作)都会进入onError, onFinished任何情况总是会被调用, 安全可靠.
  3. 使用xUtils中的任务使用

java
x.task().start(task); // 执行一个异步任务
result = x.task().startSync(task); // 同步执行该任务

看到上面的接口是不是很简单, 定义一个任务后可以很方便的异步执行或同步执行. 接下来我们开始接受怎样定义一个任务.

java
// task的hello world
x.task().start(new AbsTask<String>() {
    @Override
    protected String doBackground() throws Throwable {
        return "hello world!";
    }

    @Override
    protected void onSuccess(String result) {
        Log.d("test", result);
    }

    @Override
    protected void onError(Throwable ex, boolean isCallbackError) {
        Log.e("test", ex.getMessage(), ex);
    }

    @Override
    protected void onFinished() {
        Log.d("test", "finished");
    }
});

实例中使用task的基类AbsTask定义了一个task的实例, 并使用异步的方式调用, doBackground在默认线程池中进行(后面会介绍怎样自定义线程池). start的返回值类型为AbsTask<T>(示例中T为String), 但它并非被执行的task的实例, 而是task的代理, 对代理实例的所有方法调用不必关心线程的问题, 框架会自动处理. 如果使用startSync执行这个任务, 则doBackground在当前线程同步执行, 并且doBackground的返回值作为startSync的返回值.

  1. AbsTask的重要属性和方法(以on开头的方法为UI线程的回调方法, 简称回调方法)

    • doBackground 执行任务的主要过程, 上面已经介绍了它的特性, 虽然它可以同步执行但仍然被这样命名.
    • onWaiting 任务startstartSync之后会立即执行, 任务尚未被分配执行线程.
    • onStarted 任务被分配执行线程后立即执行, 接下来会执行doBackground.
    • onSuccessdoBackground执行完成后立即执行.
    • onCancelled 任务onSuccess之前任何线程调用AbsTask#canceldoBackground中抛出CancelledException之后执行.
    • onUpdate(int flag, Object... args) 任何线程调用了AbsTask#update(int flag, Object... args)之后执行.
    • onError(Throwable ex, boolean isCallbackError) 以上任何方法中出现异常时执行, 参数isCallbackError表示是否回调方法中的错误.
    • onFinished 总是在最终调用, 即使任务出现error会被cancel.
  2. 取消任务 AbsTask#cancel() 示例:

java
AbsTask<?> proxy = x.task().start(task);
...
proxy.cancel(); // 在任何线程调用
// 如果在任务内部取消, 建议使用抛出CancelledException的方法, 这样可以使用message或自定义的CancelledException表明取消的原因.
...
  1. 自定义更新通知 AbsTask#update(int flag, Object... args) 示例:
java
x.task().start(new AbsTask<String>() {

    private static final int FLAG_UPDATE = 1;

    @Override
    protected String doBackground() throws Throwable {
        this.update(FLAG_UPDATE, 0);
        ...
        this.update(FLAG_UPDATE, 50);
        ...
        this.update(FLAG_UPDATE, 100);
        return "hello world!";
    }

    @Override
    protected void onUpdate(int flag, Object... args) {
        switch (flag) {
            case FLAG_UPDATE: {
                if (args == null || args.length != 1) return;
                int value = (Integer) args[0];
                ...
                break;
            }
            default: {
                break;
            }
        }
    }

    ...
});
  1. 设置优先级, 覆盖方法 AbsTask#getPriority

  2. 设置自定义线程池, 覆盖方法 AbsTask#getExecutor

  3. 取消任务时是否不等待任务彻底结束, 立即收到取消的通知, 覆盖方法 AbsTask#isCancelFast

  4. 任务是否被取消 final AbsTask#isCancelled,

  5. 任务是都已经执行完成 final AbsTask#isFinished

  6. 获取任务的状态 final AbsTask#getState

  7. 获取执行结果 final AbsTask#getResult

  8. 其他, 使用AbsTask(Callback.Cancelable cancelHandler)构造函数可自定义可扩展的取消逻辑.