`
贾礼威
  • 浏览: 798 次
社区版块
存档分类
最新评论

AsyncTask

阅读更多
<!DOCTYPE html><html><head><title>AsyncTask</title><meta charset='utf-8'><link href='https://dn-maxiang.qbox.me/res-min/themes/marxico.css' rel='stylesheet'></head><body><div id='preview-contents' class='note-content'>
                        <div id="wmd-preview" class="preview-content"></div>
                    <div id="wmd-preview-section-1" class="wmd-preview-section preview-content">

</div><div id="wmd-preview-section-2" class="wmd-preview-section preview-content">

<h1 id="asynctask">AsyncTask</h1>

<p></p>

<p>异步的短时间任务,最多到几秒的操作</p>

<ul><li>三个类型 <br>
1.Params 传递给任务的参数 <br>
2.Progress 执行中返回的阶段类型 <br>
3.Result 最终结果的返回类型</li>
<li>4个步骤 <br>
1.onPreExecute 在UI线程中执行一般是用来配置任务 <br>
2.doInBackground 在后台执行,返回类型必须是Result类型,可以调用publishProgress来向UI线程报告进度 <br>
3.onProgressUpdate 在UI线程中执行,可以用来在UI上显示进度条等 <br>
4.onPostExecute 在UI线程中执行,Result被传入作为参数</li>
<li>取消任务 <br>
1.调用cancel可以使接下来调用的isCancel方法返回true <br>
2.取消任务后在doInBackground 结束后会调用onCancelled 而不是onPostExecute  <br>
3.cancel只可以设置标志位,并不能立即中断任务,需要在doInBackground 在执行的过程中周期性的去检查isCancel</li>
<li>线程相关 <br>
1.AsyncTask类必须在UI线程中加载(系统自动加载) <br>
2.AsyncTask实例必须在UI线程中进行构造 <br>
3.不要手动调用doInBackground 等方法 <br>
4.AsyncTask只能执行一次,再次执行会抛出异常 <br>
5.AsyncTask保证所有的回调都是同步的,所以在4个步骤中不必考虑并发问题</li>
</ul>

</div><div id="wmd-preview-section-3" class="wmd-preview-section preview-content">

<pre class="prettyprint hljs-dark"><code class="language-java hljs">    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AsyncTask</span><span class="hljs-params">()</span> </span>{<br>        <span class="hljs-comment">//Callable 的包装,将给executor执行</span><br>        mWorker = <span class="hljs-keyword">new</span> WorkerRunnable&lt;Params, Result&gt;() {<br>            <span class="hljs-function"><span class="hljs-keyword">public</span> Result <span class="hljs-title">call</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{<br>                mTaskInvoked.set(<span class="hljs-keyword">true</span>);<br><br>                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);<br>                <span class="hljs-comment">//noinspection unchecked</span><br>                <span class="hljs-keyword">return</span> postResult(doInBackground(mParams));<br>            }<br>        };<br>        <span class="hljs-comment">//控制mWorker执行的future,用来在必要的时候取消执行</span><br>        mFuture = <span class="hljs-keyword">new</span> FutureTask&lt;Result&gt;(mWorker) {<br>            <span class="hljs-annotation">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">done</span><span class="hljs-params">()</span> </span>{<br>                <span class="hljs-keyword">try</span> {<br>                    postResultIfNotInvoked(get());<br>                } <span class="hljs-keyword">catch</span> (InterruptedException e) {<br>                    android.util.Log.w(LOG_TAG, e);<br>                } <span class="hljs-keyword">catch</span> (ExecutionException e) {<br>                    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"An error occured while executing doInBackground()"</span>,<br>                            e.getCause());<br>                } <span class="hljs-keyword">catch</span> (CancellationException e) {<br>                    postResultIfNotInvoked(<span class="hljs-keyword">null</span>);<br>                }<br>            }<br>        };<br>    }<br></code></pre>

<p>调用execute后实际会转到executeOnExecutor上,代码如下:</p>

</div><div id="wmd-preview-section-244" class="wmd-preview-section preview-content">

<pre class="prettyprint hljs-dark"><code class="language-java hljs"><br><span class="hljs-comment">/* 这里的exec是可以制定的,默认的是AsyncTask的sDefaultExecutor,这是个SerialExecutor即所有任务需要顺序执行<br>也可以传入自定义的Executor来实现任务的并发执行<br>*/</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> AsyncTask&lt;Params, Progress, Result&gt; executeOnExecutor(Executor exec,<br>            Params... params) {<br>            <span class="hljs-comment">//状态判断,也是为什么只能执行一次</span><br>        <span class="hljs-keyword">if</span> (mStatus != Status.PENDING) {<br>            <span class="hljs-keyword">switch</span> (mStatus) {<br>                <span class="hljs-keyword">case</span> RUNNING:<br>                    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Cannot execute task:"</span><br>                            + <span class="hljs-string">" the task is already running."</span>);<br>                <span class="hljs-keyword">case</span> FINISHED:<br>                    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Cannot execute task:"</span><br>                            + <span class="hljs-string">" the task has already been executed "</span><br>                            + <span class="hljs-string">"(a task can be executed only once)"</span>);<br>            }<br>        }<br><br>        mStatus = Status.RUNNING;<br><span class="hljs-comment">// 此方法还没有进入到exec中所以onPreExecute还是在UI线程中操作</span><br>        onPreExecute();<br><span class="hljs-comment">// 将params传入到mWoeker中,并将包涵mWorker的future送给exec去执行</span><br>        mWorker.mParams = params;<br>        exec.execute(mFuture);<br><br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;<br>    }<br></code></pre>

<p>默认的执行是在SerialExecutor中执行的,它可以保证所有的AsyncTask的doInBackground是同步执行的</p>

</div><div id="wmd-preview-section-1115" class="wmd-preview-section preview-content">

<pre class="prettyprint hljs-dark"><code class="language-java hljs">    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SerialExecutor</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Executor</span> </span>{<br>        <span class="hljs-keyword">final</span> ArrayDeque&lt;Runnable&gt; mTasks = <span class="hljs-keyword">new</span> ArrayDeque&lt;Runnable&gt;();<br>        Runnable mActive;<br><span class="hljs-comment">// 这个方法可以保证传进的r都是顺序执行的,即一个结束后另一个才开始</span><br>        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Runnable r)</span> </span>{<br>            mTasks.offer(<span class="hljs-keyword">new</span> Runnable() {<br>                <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{<br>                    <span class="hljs-keyword">try</span> {<br>                        r.run();<br>                    } <span class="hljs-keyword">finally</span> {<br>                        scheduleNext();<br>                    }<br>                }<br>            });<br>            <span class="hljs-comment">//当第一个任务时候会触发,或者当某个任务结束时候下一个task还没有到达的时候也会触发</span><br>            <span class="hljs-comment">//当任务在前一个任务还没有结束就到达了,那么会在上面的scheduleNext直接触发执行</span><br>            <span class="hljs-keyword">if</span> (mActive == <span class="hljs-keyword">null</span>) {<br>                scheduleNext();<br>            }<br>        }<br><span class="hljs-comment">//将任务送给THREAD_POOL_EXECUTOR 执行</span><br>        <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">scheduleNext</span><span class="hljs-params">()</span> </span>{<br>            <span class="hljs-keyword">if</span> ((mActive = mTasks.poll()) != <span class="hljs-keyword">null</span>) {<br>                THREAD_POOL_EXECUTOR.execute(mActive);<br>            }<br>        }<br>    }<br></code></pre>

<p>上面可以看到onPreExecute是在主线程中执行的,然后是doInBackGround在独立的线程中,那么它是又如何回到UI线程中的呢? <br>
这是因为AsyncTask构造了一个基于主线程的Handler ,代码如下:</p>

</div><div id="wmd-preview-section-1326" class="wmd-preview-section preview-content">

<pre class="prettyprint hljs-dark"><code class="language-java hljs">    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InternalHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Handler</span> </span>{<br>        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InternalHandler</span><span class="hljs-params">()</span> </span>{<br>        <span class="hljs-comment">// 确保可以在主线程中执行</span><br>            <span class="hljs-keyword">super</span>(Looper.getMainLooper());<br>        }<br><br>        <span class="hljs-annotation">@SuppressWarnings</span>({<span class="hljs-string">"unchecked"</span>, <span class="hljs-string">"RawUseOfParameterizedType"</span>})<br>        <span class="hljs-annotation">@Override</span><br>        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleMessage</span><span class="hljs-params">(Message msg)</span> </span>{<br>            AsyncTaskResult&lt;?&gt; result = (AsyncTaskResult&lt;?&gt;) msg.obj;<br>            <span class="hljs-keyword">switch</span> (msg.what) {<br>                <span class="hljs-keyword">case</span> MESSAGE_POST_RESULT:<br>                    <span class="hljs-comment">// There is only one result,会调用onProgressUpdate</span><br>                    result.mTask.finish(result.mData[<span class="hljs-number">0</span>]);<br>                    <span class="hljs-keyword">break</span>;<br>                <span class="hljs-keyword">case</span> MESSAGE_POST_PROGRESS:<br>                    result.mTask.onProgressUpdate(result.mData);<br>                    <span class="hljs-keyword">break</span>;<br>            }<br>        }<br>    }<br></code></pre>

<p>onProgressUpdate  和 onPostExecute 都是在handler中执行的所以自然是在主线程,而将消息传递给handler的是publishProgress 和 postResult</p>

<p>publishProgress 比较简单就是从Handler 获取小心然后发送,这个在AsyncTask内部没有调用,主要用来给用户自定义的子类在doInBackground中使用</p>

<p>postResult 是在mWorker中定义会在结束后发消息给handler</p></div><div id="wmd-preview-section-footnotes" class="preview-content"></div></div></body></html>
分享到:
评论

相关推荐

    Android AsyncTask异步处理下载网页

    Android提供了一种便捷的机制,名为`AsyncTask`,用于在后台线程执行这些任务,同时允许在主线程更新UI。`AsyncTask`是一个轻量级的框架,设计用来简化在Android应用程序中进行后台操作的过程。 `AsyncTask`包含三...

    AsyncTask类实例详解

    AsyncTask是Android中用于在后台线程执行耗时操作并更新UI的一种机制。它通过封装了线程管理和与主线程的交互,简化了在UI线程中处理异步任务的流程。下面我们将深入探讨AsyncTask的使用、原理以及如何更新UI。 ...

    AsyncTask结合HttpUrlConnection的例子

    在Android开发中,异步处理是非常重要的一环,特别是在与服务器进行数据交互时,为了保持UI线程的流畅性,避免出现"应用无响应"(ANR)的情况,开发者通常会使用`AsyncTask`。本例子是关于如何将`AsyncTask`与`...

    android中AsyncTask的用法

    在Android应用开发中,AsyncTask是一个用于在后台线程执行耗时操作并更新UI的工具类,它是Android 1.5版本引入的。AsyncTask的设计初衷是为了简化异步编程,避免直接操作线程和Handler带来的复杂性。下面我们将详细...

    AsyncTask加载网络图片,实现进度条的更新

    `AsyncTask`是Android提供的一种轻量级的并发工具,用于在后台线程执行任务,并在主线程更新UI。在本示例中,我们将深入探讨如何使用`AsyncTask`来加载网络图片并实时更新进度条。 首先,我们需要理解`AsyncTask`的...

    AsyncTask下载网络图片 进度条提示

    `AsyncTask`是Android提供的一种轻量级的异步处理机制,它可以帮助我们在主线程中轻松地执行后台任务,同时更新UI。本篇文章将详细探讨如何使用`AsyncTask`来实现网络图片的下载,并且展示进度条提示。 `AsyncTask`...

    Android AsyncTask 源码解析

    **Android AsyncTask 源码解析** AsyncTask 是 Android 平台上一个非常重要的工具类,用于在后台线程执行耗时操作,然后在 UI 线程更新结果,从而避免了因长时间运行任务而导致的 ANR(Application Not Responding...

    Handler与AsyncTask使用示例

    在Android开发中,`Handler`、`AsyncTask`和`Looper`是三个非常重要的概念,它们主要用于处理应用程序的异步操作和线程通信。本文将深入探讨这些知识点,并通过实例来展示它们如何协同工作。 首先,`Handler`是...

    Android AsyncTask用法和异步加载图片.rar

    Android提供了一种轻量级的机制来在后台执行这些任务,即`AsyncTask`。本资料包主要讲解了如何使用`AsyncTask`进行异步加载图片,这对于在UI线程中保持流畅用户体验至关重要。 `AsyncTask`是Android SDK中的一个类...

    android任务后台处理 asyncTask封装

    `AsyncTask`是Android提供的一种轻量级的异步处理机制,它能让我们在后台线程执行耗时操作,并在完成后更新主线程中的UI。下面我们将深入探讨`AsyncTask`的工作原理及其封装方法。 `AsyncTask`的核心在于三个泛型...

    01_AsyncTask_演示线程阻塞

    `AsyncTask`是Android提供的一种轻量级的异步任务处理框架,它允许开发者在后台线程执行耗时操作,然后在UI线程更新结果,避免了阻塞主线程导致的ANR(Application Not Responding)问题。这篇我们将深入探讨`...

    Android中异步类AsyncTask用法总结

    AsyncTask 是 Android 平台上一种轻量级的异步处理机制,主要用于在后台执行耗时操作,同时确保结果能够在主线程中安全地更新 UI。它简化了多线程编程,尤其是与用户界面交互的需求。 首先,AsyncTask 包含三个泛型...

    一个AsyncTask的Demo

    AsyncTask是Android平台中用于在后台执行耗时操作并更新UI的一种工具类。它主要设计用来简化异步处理,特别是那些需要与用户界面交互的任务。在这个"AsyncTask的Demo"中,我们将深入探讨AsyncTask的工作原理及其核心...

    Android 线程AsyncTask逐步在list中加入条目

    在这个"Android 线程AsyncTask逐步在list中加入条目"的例子中,我们首先会创建一个`AsyncTask`子类,如`LoadDataTask`,继承自`AsyncTask`。`doInBackground()`方法将用于生成数据(可能是从网络请求或本地数据库...

    AsyncTask的示例代码

    AsyncTask是Android开发中用于在后台执行任务并更新UI的重要工具。它允许开发者在主线程之外执行耗时操作,如网络请求、数据库操作等,同时能够方便地在工作完成时更新UI,避免了直接在主线程中进行这些操作导致的...

    面向对象思想实现AsyncTask类的复用

    在Android开发中,AsyncTask是一种轻量级的异步处理工具,用于在后台线程执行耗时操作,然后在UI线程更新结果。本篇文章将深入探讨如何利用面向对象的思想来实现AsyncTask类的复用,提高代码的可维护性和灵活性。 ...

    AndEngine_分析之三-----AsyncTask_BaseActivity备忘

    ### AndEngine分析之三——AsyncTask与BaseActivity深入解析 #### 一、AsyncTask概述 在AndEngine项目中,为了实现界面更新等操作时避免主线程阻塞的问题,使用了`AsyncTask`来处理后台任务。`AsyncTask`提供了一...

    AsyncTask加载网络图片

    在Android开发中,异步任务(AsyncTask)是一种常见的用于执行后台操作并更新UI线程的工具,尤其在处理耗时任务,如加载网络图片时非常有用。AsyncTask提供了简单的接口,使得开发者可以在后台线程中执行计算,然后...

    Android异步请求之AsyncTask

    `AsyncTask`是Android SDK提供的一种轻量级的异步处理机制,它使得开发者能够在后台线程执行任务,并在UI线程更新结果,避免了主线程被阻塞的风险。下面将详细解释`AsyncTask`的原理、使用方法以及注意事项。 ### ...

    AsyncTask的cancel的有效用法

    在Android开发中,AsyncTask是一种常用的轻量级异步任务处理框架,用于在后台线程执行耗时操作,然后在UI线程更新结果。当我们需要取消一个正在运行的AsyncTask时,就需要理解并正确使用`cancel`方法。本文将深入...

Global site tag (gtag.js) - Google Analytics