Android UI操作是线程不安全的,若想在子线程红进行UI操作,需要借助Android提供的Handler。Android提供的AsyncTask其实是对Handler的封装,方便我们在子线程中更新UI元素。AsyncTask是一个泛型类,书写格式为: AsyncTask<Params, Progress, Result>。这三个参数的用途如下:

1. Params

这三个参数的用途如下:
1. Params
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
2. Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3. Result
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

Android SDK中给出的一个AsyncTask用法如下:

 private class DownloadFilesTask extends AsyncTask(URL, Integer, Long) {      protected Long doInBackground(URL... urls) {          int count = urls.length;          long totalSize = 0;          for (int i = 0; i < count; i++) {              totalSize += Downloader.downloadFile(urls[i]);              publishProgress((int) ((i / (float) count)  100));              // Escape early if cancel() is called              if (isCancelled()) break;          }          return totalSize;      }       protected void onProgressUpdate(Integer... progress) {          setProgressPercent(progress[0]);      }       protected void onPostExecute(Long result) {          showDialog("Downloaded " + result + " bytes");      }  } new DownloadFilesTask().execute(url1, url2, url3);

AsyncTask是个抽象类,有四个方法需要被重写,这四个方法的的调用过程如下:
第1步. onPreExecute()方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作。
第2步. doInBackground(Params...)方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回。如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
第3步. 当在后台任务中调用了publishProgress(Progress...)方法后,onProgressUpdate(Progress...)方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
第4步. 当后台任务执行完毕并通过return语句进行返回时,onPostExecute(Result)很快会被调用。此处可以
进行UI操作。

AsyncTask的源码
当初使用AsyncTask的时候,一直不明白onProcessUpdate为何会定期被调用。后来在工作中要实现一个定时更新任务进度的功能,我们用的是一个Handler给自己发送消息来进行定时刷新。现在研究了一下AsyncTask的实现原理,发现它也是使用Handler给自己发送消息的原理来实现定时刷新。当我选用的是Android 4.4的源码,若大家能搞懂AsyncTask的实现原理,也能自己写一个简单的AsyncTask。
首先看看构造函数:注意,构造函数一定要在UI中调用。

   /**     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.     */    public AsyncTask() {        mWorker = new WorkerRunnable<Params, Result>() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                //noinspection unchecked                return postResult(doInBackground(mParams));            }        };        mFuture = new FutureTask<Result>(mWorker) {            @Override            protected void done() {                try {                    postResultIfNotInvoked(get());                } catch (InterruptedException e) {                    android.util.Log.w(LOG_TAG, e);                } catch (ExecutionException e) {                    throw new RuntimeException("An error occured while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }        };    }
这个函数初试化了两个变量:mWorker和mFuture。mWorker是一个Callable对象,mFuture是一个实现了Runnable和Future的对象。启动AsyncTask调用的是execute(Params)
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }
该方法调用了executeOnExecutor()方法,代码如下:

    public final AsyncTask<Params, Progress, Result> 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,最后调用exec.execute(mFuture).传入的exec是sDefaultExecutor, sDefaultExecutor是一个SerialExecutor对象,源代码如下:

private static class SerialExecutor implements Executor {        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();        Runnable mActive;        public synchronized void execute(final Runnable r) {            mTasks.offer(new Runnable() {                public void run() {                    try {                        r.run();                    } finally {                        scheduleNext();                    }                }            });            if (mActive == null) {                scheduleNext();            }        }        protected synchronized void scheduleNext() {            if ((mActive = mTasks.poll()) != null) {                THREAD_POOL_EXECUTOR.execute(mActive);            }        }    }
当调用sDefaultExecutor.execute(runnable),该方法用一个ArrayDeque来保存runnable,runnable会在合适的时候被调用。第一次运行mActivity等于null了,于是会调用scheduleNext()方法。在这个方法中会从队列的头部取值,并赋值给mActive对象,然后调用THREAD_POOL_EXECUTOR去执行取出的取出的Runnable对象。这里使用了一个try finally代码块,并在finally中调用了scheduleNext()方法,每次当一个任务执行完毕后,下一个任务才会得到执行,SerialExecutor模仿的是单一线程池的效果,如果我们快速地启动了很多任务,同一时刻只会有一个线程正在执行,其余的均处于等待状态。

sDefaultExecutor.execute(Runnable)传入的对象是mFuture,mFuture是一个FutureTask对象,其构造函数如下所示:

 public FutureTask(Callable<V> callable) {        if (callable == null)            throw new NullPointerException();        this.callable = callable;        this.state = NEW;       // ensure visibility of callable    }
由AsyncTask的构造函数可知,FutureTask中的callable是mWorkder对象。FutureTask的run()代码如下所示:
    public void run() {        if (state != NEW ||            !UNSAFE.compareAndSwapObject(this, runnerOffset,                                         null, Thread.currentThread()))            return;        try {            Callable<V> c = callable;            if (c != null && state == NEW) {                V result;                boolean ran;                try {                    result = c.call();                    ran = true;                } catch (Throwable ex) {                    result = null;                    ran = false;                    setException(ex);                }                if (ran)                    set(result);            }        } finally {            // runner must be non-null until state is settled to            // prevent concurrent calls to run()            runner = null;            // state must be re-read after nulling runner to prevent            // leaked interrupts            int s = state;            if (s >= INTERRUPTING)                handlePossibleCancellationInterrupt(s);        }    }
因此,最终会调用mWorker的call()。mWorker的call()位于AsyncTask的构造函数中,大家可以发现其先调用doInBackgroud(Params),然后调用postResult().postResult(Result)的源代码如下:

    private Result postResult(Result result) {        @SuppressWarnings("unchecked")        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult<Result>(this, result));        message.sendToTarget();        return result;    }
sHandler是一个InternalHandler,代码如下:

 private static class InternalHandler extends Handler {        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})        @Override        public void handleMessage(Message msg) {            AsyncTaskResult result = (AsyncTaskResult) msg.obj;            switch (msg.what) {                case MESSAGE_POST_RESULT:                    // There is only one result                    result.mTask.finish(result.mData[0]);                    break;                case MESSAGE_POST_PROGRESS:                    result.mTask.onProgressUpdate(result.mData);                    break;            }        }    }
当传入的是一条MESSAGE_POST_RESULT消息,就会去执行AsyncTask.finish()方法,如果这是一条MESSAGE_POST_PROGRESS消息,就会去执行onProgressUpdate()方法。当我们在doInBackgroud(Params)中利用for循环来调用publishProgress(Progress... values),就会模拟出
定时调用onProgressUpdate(Progress... values)的效果。publishProgress(Progress... values)的源码如下:

    protected final void publishProgress(Progress... values) {        if (!isCancelled()) {            sHandler.obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();        }    }
它首先会判断线程是否已经结束,若没结束,则sHandler给自己发送一个消息,消息的类型为MESSAGE_POST_PROGRESS,sHandler.handleMessage(Message)则会调用onProgressUpdate(Progress...values)。
由上可知sDefaultExecutor先调用mFuture的run(), 而mFuture的run()又会调用mWorker的call()。当执行完一个任务后,mFuture的done()会被回调。done()会调用ppostResultIfNotInvoked(Result result),源码如下:

    private void postResultIfNotInvoked(Result result) {        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }
postResult(Result)已经在前面有过讲解,在此不再赘述。






更多相关文章

  1. 编写android对google地图的调用
  2. android各版本新特性
  3. Android设备Root检测方法
  4. Android(安卓)Studio中创建Selector文件的方法
  5. Android与JS代码交互
  6. Android屏幕旋转时Activity的生命周期
  7. Android(安卓)异步消息处理机制 让你深入理解 Looper、Handler、
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. android中,显示圆形图片
  2. Ubuntu12.04 eclipse DDMS卡死-解决办法
  3. toast的五种效果
  4. Android中Telephony学习总结
  5. android 横竖屏切换,activity的生命周期
  6. Android开发所需的Android(安卓)SDK、开
  7. android.hardware.USB类介绍
  8. IdleHandler类在android中的使用
  9. Lifecycle-Aware Components生命周期组件
  10. API 25 (Android(安卓)7.1.1 API) widget