AsyncTask的一些疑问

使用:新建类继承AsyncTask,实现其doInBackground方法

protected void onPreExecute()
protected String doInBackground(String... params)
protected void onProgressUpdate(Integer... values)
protected void onCancelled()
protected void onCancelled(String s)
protected void onPostExecute(String s)

或者直接new

AsyncTask asyncTask
                = new AsyncTask() {
    @Override
    protected String doInBackground(String... params) {
        return null;
    }
};
asyncTask.execute("hii");

doInBackground(String... params) 中要更新UI可以调用 publishProgress(Progress... values) , publishProgress() 方法本身执行在异步线程,但会调用 Handler 发 MESSAGE_POST_PROGRESS事件抛到主线程,让 onProgressUpdate(Integer... values) 处理,不要手动调用 onProgressUpdate(Integer... values)

为什么只能在UI线程创建?

因为Android老的版本上用于线程间通信的 InternalHandler 创建时没有为其指定Looper,所以它会默认使用当前线程的Looper,如果当前线程没有事先调用过 Looper.prepare() ,就会报 RuntimeException("Can't create handler inside thread that has not called Looper.prepare()") 异常,即使调用过 Looper.prepare() 由于不是主线程,也不能去修改UI。至少在API 16上是这样,后来的版本里面这条被修改了,AsyncTask 在实例化 InternalHandler 是为其指定主线程。

public InternalHandler() {
    super(Looper.getMainLooper());
}

为什么只能在主线程中调用 AsyncTask#execute() ?

先看执行代码:

@MainThread
public final AsyncTask execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

@MainThread
public final AsyncTask executeOnExecutor(Executor exec,
        Params... params) {
    if (mStatus != Status.PENDING) {
        switch (mStatus) {
            case RUNNING:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task is already running.");
            case FINISHED:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task has already been executed "
                        + "(a task can be executed only once)");
        }
    }

    mStatus = Status.RUNNING;

    onPreExecute();

    mWorker.mParams = params;
    exec.execute(mFuture);

    return this;
}

并没有为 onPreExecute() 方法的执行特别指定线程,所以 onPreExecute() 是执行在当前线程,如果要在 onPreExecute() 中修改UI的话,AsyncTask#execute() 就要在UI线程中执行。

为什么一个AsyncTask实例只能执行一次?

在并发条件下多次执行execute(),会让线程内的数据不安全,并没有加锁机制,而是限制一个Task只能被执行一次。

其他

仿 AsyncTask 做的一个单线程执行工具(从《Android开发进阶》这本书上看到的)

DbCommand.java

可以改单线程为多个线程:

private static int coreThreadNum = Runtime.getRuntime().availableProcessors();
private final static ExecutorService executor = new ThreadPoolExecutor(
         coreThreadNum, coreThreadNum, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());

你可能感兴趣的:(AsyncTask的一些疑问)