在上一个例子中,我们是在LoadImage的onPostExecute中修改的UI,不是说只允许在主线程中修改UI吗?我们看一下源代码是如何操作的。

MainActicity.java

package cn.lixyz.asynctest;import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;public class MainActivity extends Activity{private Button button;private ImageView imageView;private ProgressBar progressBar;private String URL="http://ww3.sinaimg.cn/bmiddle/612c96afjw1ewwftl3uqkj20u00koq48.jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//获取组件button = (Button) findViewById(R.id.button);imageView = (ImageView) findViewById(R.id.imageView);progressBar = (ProgressBar) findViewById(R.id.progressBar);//给button设置点击事件,点击按钮,启动异步任务button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {new LoadImage().execute(URL);}});}class LoadImage extends AsyncTask<String,Void,Bitmap>{//开始执行耗时操作,连接网络获取图片,并且将Bitmap返回
        @Overrideprotected Bitmap doInBackground(String... params) {String url = params[0];Bitmap bitmap = null;URLConnection connection;InputStream is;try {connection = new URL(url).openConnection();Thread.sleep(5000);is = connection.getInputStream();BufferedInputStream bis = new BufferedInputStream(is);bitmap  = BitmapFactory.decodeStream(bis);is.close();bis.close();} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}return bitmap;}//onPreExcute方法是在doInBackGround方法前执行,用于做一些初始化操作,这里将progressBar显示出来
        @Overrideprotected void onPreExecute() {super.onPreExecute();progressBar.setVisibility(View.VISIBLE);}//doInBackGround方法执行后,会自动执行该方法,获取到doInBackGround返回的对象,然后更改UI
        @Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);progressBar.setVisibility(View.GONE);imageView.setImageBitmap(bitmap);}}
}

View Code

acticity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="4"><ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"/><ProgressBarandroid:id="@+id/progressBar"android:visibility="gone"android:layout_centerInParent="true"style="@style/Widget.AppCompat.ProgressBar"android:layout_width="wrap_content"android:layout_height="wrap_content" /></RelativeLayout><Buttonandroid:id="@+id/button"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:text="点击载入" />
</LinearLayout>

View Code

先找到AsyncTask的构造函数:

    public AsyncTask() {mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection uncheckedResult result = doInBackground(mParams);Binder.flushPendingCommands();return postResult(result);}};mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {postResultIfNotInvoked(get());} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException("An error occurred while executing doInBackground()",e.getCause());} catch (CancellationException e) {postResultIfNotInvoked(null);}}};}

可以看到在AsyncTask的构造函数中,仅仅初始化了两个变量 mWorker 和 mFuture

接着启动AsyncTask,我们找到 execute 方法:

    @MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}

可以看到,在 execute() 方法中,只执行了一个 executeOnExecutor() ,我们继续看executeOnExecutor方法:

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

可以看到,在 executeOnExecutor() 方法中,先判断了AsyncTask的状态,如果是 RUNNING 或者是 FINISHED 的话,则会抛出 IllegalStateException 异常,如果不是,则将AsyncTask的状态设置为 RUNNING  ,然后执行 onPreExecute() 方法,我们再看这个方法:

    @MainThreadprotected void onPreExecute() {}

这个方法又没有做任何操作,之前我们讲过, onPreExecute() 方法是在执行 doInBackGround() 之前执行,用来做一些初始化操作的,所以如果我们有需要的话,就需要自己重写 onPreExecute() 方法了。

  接着看 executeOnExecutor() 方法,在执行完 onPreExecute() 方法之后,继续往下,将 params 赋值给 mWorker.mParams 之后,又执行了 exec.execute(mFuture) , mFuture 是在前面的构造方法中初始化的,我们看代码:

    public AsyncTask() {mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection uncheckedResult result = doInBackground(mParams);Binder.flushPendingCommands();return postResult(result);}};mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {postResultIfNotInvoked(get());} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException("An error occurred while executing doInBackground()",e.getCause());} catch (CancellationException e) {postResultIfNotInvoked(null);}}};}

  可以看到在这里调用了 doInBackground() 方法,并最后返回了 postResult(result) ,再继续看,找到 postResult(result)

    private Result postResult(Result result) {@SuppressWarnings("unchecked")Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;}

  可以看到,在这部分代码中,显示获取到了一个Handler,然后调用这个Handler对象的obtainMessage()方法得到一个Message对象,我们看一下获取到的这个Handler对象:

    private static Handler getHandler() {synchronized (AsyncTask.class) {if (sHandler == null) {sHandler = new InternalHandler();}return sHandler;}}

  发现是一个 InternalHandler 对象,继续找这个 InternalHandler 对象

    private static class InternalHandler extends Handler {public InternalHandler() {super(Looper.getMainLooper());}@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}

  这里就清楚了,获取到的是一个 MainLooper ,也就是说获取的是在主线程中的Handler,也就是说,上面的操作最后将Message发送到了主线程中,然后根据发送过来的消息是  MESSAGE_POST_RESULT  还是 MESSAGE_POST_PROGRESS 来判断该执行什么方法

  如果是 MESSAGE_POST_RESULT  ,我们查看finish方法:

    private void finish(Result result) {if (isCancelled()) {onCancelled(result);} else {onPostExecute(result);}mStatus = Status.FINISHED;}

  到这里,就一目了然了,调用了onPostResult方法更新UI。

  整个流程走完,会发现其实AsyncTask还是Handler机制,只不过是对线程做了优化和封装而已

更多内容:

  Android应用AsyncTask处理机制详解及源码分析

  Android异步类AsyncTask详解

转载于:https://www.cnblogs.com/xs104/p/4869669.html

Android笔记(三十六) AsyncTask是如何执行的?相关推荐

  1. 【Visual C++】游戏开发笔记三十六 浅墨DirectX提高班之四 顶点缓存的逆袭

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8276363 作者:毛星云(浅墨 ...

  2. 【Unity 3D】学习笔记三十六:物理引擎——刚体

    物理引擎就是游戏中模拟真是的物理效果.如两个物体发生碰撞,物体自由落体等.在unity中使用的是NVIDIA的physX,它渲染的游戏画面很逼真. 刚体 刚体是一个很很中要的组件. 默认情况下,新创的 ...

  3. Jenkins +maven+tomcat自动构建部署(学习笔记三十六)

    https://my.oschina.net/denglz/blog/524154 摘要: jenkins + maven + svn + tomcat 自动部署 jenkins  是做什么用的,如果 ...

  4. opencv学习笔记三十六:AKAZE特征点检测与匹配

    KAZE是日语音译过来的 , KAZE与SIFT.SURF最大的区别在于构造尺度空间,KAZE是利用非线性方式构造,得到的关键点也就更准确(尺度不变性 ): Hessian矩阵特征点检测 ,方向指定, ...

  5. OpenCV学习笔记(三十六)——Kalman滤波做运动目标跟踪 OpenCV学习笔记(三十七)——实用函数、系统函数、宏core OpenCV学习笔记(三十八)——显示当前FPS OpenC

    OpenCV学习笔记(三十六)--Kalman滤波做运动目标跟踪 kalman滤波大家都很熟悉,其基本思想就是先不考虑输入信号和观测噪声的影响,得到状态变量和输出信号的估计值,再用输出信号的估计误差加 ...

  6. VTK学习笔记(三十六)VTK图像填充

    VTK学习笔记(三十六)VTK图像填充 1.官方示例 2.其他例子 总结 1.官方示例 来自官方示例代码,自己只是添加了理解. 代码: #include <vtkCamera.h> #in ...

  7. Slicer学习笔记(三十六)slicer坐标系

    Slicer学习笔记(三十六)slicer坐标系 1.坐标系统 1.1.世界坐标系 1.2.解剖坐标系 1.3.图像坐标系 1.4.图像变换 1.5.二维示例或计算IJtoLS矩阵 1.6.与其他软件 ...

  8. android仿秒拍源码,你所不知道的程序员 程序员其实真的很…【Bus Weekly】三十六期...

    原标题:你所不知道的程序员 程序员其实真的很-[Bus Weekly]三十六期 快,点击蓝色"字体"关注这个公众号,一起涨姿势- 现如今,程序员在中国的科技 圈可以说已经达到了举足 ...

  9. 推荐系统三十六式——学习笔记(三)

    由于工作需要,开始学习推荐算法,参考[极客时间]->[刑无刀大牛]的[推荐系统三十六式],学习并整理. 3 原理篇之紧邻推荐 3.1 协同过滤 要说提到推荐系统中,什么算法最名满天下,我想一定是 ...

  10. Mr.J-- jQuery学习笔记(三十二)--jQuery属性操作源码封装

    扫码看专栏 jQuery的优点 jquery是JavaScript库,能够极大地简化JavaScript编程,能够更方便的处理DOM操作和进行Ajax交互 1.轻量级 JQuery非常轻巧 2.强大的 ...

最新文章

  1. querywrapper or and嵌套_两个经常用的逻辑函数AND函数,OR函数
  2. 天气预报都哪儿去了?
  3. 联想笔记本进入pe_联想笔记本bios怎么设置U盘启动|legacy和uefi双引导模式启动
  4. php 6.0新特性,新版特性 | 序言 | Laravel 6 中文文档
  5. [云炬创业基础笔记]第二章创业者测试4
  6. @ResponseBody,@RequestBody,@PathVariable
  7. sql查询成绩最高分_sql查询各科成绩前三名----详述过程,思路清晰不烧脑!
  8. Kafka科普系列 | 原来Kafka中的选举有这么多?
  9. curl 增加header_libcurl增加HTTP header 和 POST之后获取返回数据
  10. 唤起那些年你对IDL的记忆(二)
  11. php element 插件_为phpstorm安装vue插件
  12. shell开启飞行模式_手机飞行模式,太神奇了,今天总算明白了,不用真是太浪费了...
  13. python opencv保存图片到指定路径_OpenCV-将图像保存到所选的特定文件夹
  14. 驱动,包括很多软件,并不是最新的就是最好的
  15. PostgreSQL数据保留窗口功能的使用
  16. 在C#中列出进程,杀掉进程。
  17. 分享股票量化交易程序化模型的设计思路
  18. 中国天气预报网接口及城市代码
  19. 黑客红客骇客红客蓝客飞客是什么?有什么区别?(学习资料)
  20. 内存测试软件 ddr4,RAMCHECK LX DDR4 PRO/DDR3 内存测试仪

热门文章

  1. 【疑难杂症】vmware虚拟机提示“该虚拟机似乎正在使用中”,并且无法获取所有权解决办法(三步解决虚拟机vmware提示正在使用中的问题)
  2. tomcat命令无法启动 the catalina_home environment variable is not defined correctly this environment variab
  3. python内建函数是什么意思_Python3内建函数简介,Python3内建函数详解
  4. Oracle如何手工执行job,求助高手,JOB执行和手工执行执行结果不同,JOB执行不出来,手工却没问题...
  5. 为什么C和C++难以被取代?
  6. HDLBits答案(1)_Verilog语法基础
  7. 基于ZYNQ实时目标检测系统
  8. 阿加莎•克里斯蒂作品04东方快车谋杀案
  9. java 复制文件_Java中复制文件的4种方法
  10. oracle ebs mom,OracleEBS-OAF开发笔记