- 浏览: 314791 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
u011076522:
写的确实不错,总结的很好,内容大都属实
C/C++内存分配方式 -
水晶魔方:
...
联合编译工具推荐IncrediBuild -
caiwb1990:
又看了一遍~ 越看越清晰~
C/C++内存分配方式 -
caiwb1990:
每次准备面试的时候来瞅瞅。timer_yin 写道好文,正好补 ...
TCP/IP、Http、Socket的区别【转】 -
caiwb1990:
互相学习~kongxuan 写道这个不错,用简单的话将事情讲明 ...
TCP/IP、Http、Socket的区别【转】
AsyncTask的本质是一个线程池,所有提交的异步任务都会在这个线程池(想想C3P0)中的工作线程内执行,当工作线程需要跟UI线程交互时,工作线程会通过向在UI线程创建的Handler传递消息的方式,调用相关的回调函数,从而实现UI界面的更新。
还是以昨天的例子为例~来说明AsyncTask的实现原理
分析:
在分析实现流程之前,我们先了解一下AsyncTask有哪些成员变量。
回到例子中,点击按钮之后会新建一个GetIteyeLogoTask对象:
此时会调用父类AsyncTask的构造函数:
AsyncTask.java
WorkerRunnable类实现了callable接口的call()方法,该函数会调用我们在AsyncTask子类中实现的doInBackground(mParams)方法,由此可见,WorkerRunnable封装了我们要执行的异步任务。FutureTask中的protected void done() {}方法实现了异步任务状态改变后的操作。当异步任务被取消,会向UI线程传递MESSAGE_POST_CANCEL消息,当任务成功执行,会向UI线程传递MESSAGE_POST_RESULT消息,并把执行结果传递到UI线程。
由此可知,AsyncTask在构造的时候已经定义好要异步执行的方法doInBackground(mParams)和任务状态变化后的操作(包括失败和成功)。
当创建完GetIteyeLogoTask对象后,执行
此时会调用AsyncTask的execute(Params...params)方法
当任务正在执行或者已经完成,会抛出IllegalStateException,由此可知我们不能够重复调用execute(Params...params)方法。在提交任务到线程池之前,调用了onPreExecute()方法。然后才执行sExecutor.execute(mFuture)是任务提交到线程池。
前面我们说到,当任务的状态发生改变时(1、执行成功2、取消执行3、进度更新),工作线程会向UI线程的Handler传递消息。我们知道Handler要处理其他线程传递过来的消息。在AsyncTask中,InternalHandler是在UI线程上创建的,它接收来自工作线程的消息,实现代码如下:
当接收到消息之后,AsyncTask会调用自身相应的回调方法。
总结:
1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。
2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务
3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数
还是以昨天的例子为例~来说明AsyncTask的实现原理
package cn.caiwb.aysnc; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; 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.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast; public class AsyncTaskActivity extends Activity { private ImageView mImageView; private Button mButton; private ProgressBar mProgressBar; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mImageView= (ImageView) findViewById(R.id.imageView); mButton = (Button) findViewById(R.id.button); mProgressBar = (ProgressBar) findViewById(R.id.progressBar); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { GetIteyeLogoTask task = new GetIteyeLogoTask(); task.execute("http://www.iteye.com/images/logo.gif"); } }); } class GetIteyeLogoTask extends AsyncTask<String,Integer,Bitmap> {//继承AsyncTask @Override protected Bitmap doInBackground(String... params) {//处理后台执行的任务,在后台线程执行 publishProgress(0);//将会调用onProgressUpdate(Integer... progress)方法 HttpClient hc = new DefaultHttpClient(); publishProgress(30); HttpGet hg = new HttpGet(params[0]);//获取csdn的logo final Bitmap bm; try { HttpResponse hr = hc.execute(hg); bm = BitmapFactory.decodeStream(hr.getEntity().getContent()); } catch (Exception e) { return null; } publishProgress(100); //mImageView.setImageBitmap(result); 不能在后台线程操作ui return bm; } protected void onProgressUpdate(Integer... progress) {//在调用publishProgress之后被调用,在ui线程执行 mProgressBar.setProgress(progress[0]);//更新进度条的进度 } protected void onPostExecute(Bitmap result) {//后台任务执行完之后被调用,在ui线程执行 if(result != null) { Toast.makeText(AsyncTaskActivity.this, "成功获取图片", Toast.LENGTH_LONG).show(); mImageView.setImageBitmap(result); }else { Toast.makeText(AsyncTaskActivity.this, "获取图片失败", Toast.LENGTH_LONG).show(); } } protected void onPreExecute () {//在 doInBackground(Params...)之前被调用,在ui线程执行 mImageView.setImageBitmap(null); mProgressBar.setProgress(0);//进度条复位 } protected void onCancelled () {//在ui线程执行 mProgressBar.setProgress(0);//进度条复位 } } }
分析:
在分析实现流程之前,我们先了解一下AsyncTask有哪些成员变量。
private static final int CORE_POOL_SIZE =5;//5个核心工作线程 private static final int MAXIMUM_POOL_SIZE = 128;//最多128个工作线程 private static final int KEEP_ALIVE = 1;//空闲线程的超时时间为1秒 private static final BlockingQueue<Runnable> sWorkQueue = new LinkedBlockingQueue<Runnable>(10);//等待队列 private static final ThreadPoolExecutorsExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue,sThreadFactory);//线程池是静态变量,所有的异步任务都会放到这个线程池的工作线程内执行。
回到例子中,点击按钮之后会新建一个GetIteyeLogoTask对象:
GetIteyeLogoTask task = new GetIteyeLogoTask();
此时会调用父类AsyncTask的构造函数:
AsyncTask.java
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return doInBackground(mParams); } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { Message message; Result result = null; try { result = 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) { message = sHandler.obtainMessage(MESSAGE_POST_CANCEL, new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null)); message.sendToTarget();//取消任务,发送MESSAGE_POST_CANCEL消息 return; } catch (Throwable t) { throw new RuntimeException("An error occured while executing " + "doInBackground()", t); } message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(AsyncTask.this, result));//完成任务,发送MESSAGE_POST_RESULT消息并传递result对象 message.sendToTarget(); } }; }
WorkerRunnable类实现了callable接口的call()方法,该函数会调用我们在AsyncTask子类中实现的doInBackground(mParams)方法,由此可见,WorkerRunnable封装了我们要执行的异步任务。FutureTask中的protected void done() {}方法实现了异步任务状态改变后的操作。当异步任务被取消,会向UI线程传递MESSAGE_POST_CANCEL消息,当任务成功执行,会向UI线程传递MESSAGE_POST_RESULT消息,并把执行结果传递到UI线程。
由此可知,AsyncTask在构造的时候已经定义好要异步执行的方法doInBackground(mParams)和任务状态变化后的操作(包括失败和成功)。
当创建完GetIteyeLogoTask对象后,执行
task.execute("http://www.iteye.com/images/logo.gif");
此时会调用AsyncTask的execute(Params...params)方法
public final AsyncTask<Params,Progress, Result> execute(Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw newIllegalStateException("Cannot execute task:" + " the taskis already running."); case FINISHED: throw newIllegalStateException("Cannot execute task:" + " the taskhas already been executed " + "(a task canbe executed only once)"); } } mStatus = Status.RUNNING; onPreExecute();//运行在ui线程,在提交任务到线程池之前执行 mWorker.mParams = params; sExecutor.execute(mFuture);//提交任务到线程池 return this; }
当任务正在执行或者已经完成,会抛出IllegalStateException,由此可知我们不能够重复调用execute(Params...params)方法。在提交任务到线程池之前,调用了onPreExecute()方法。然后才执行sExecutor.execute(mFuture)是任务提交到线程池。
前面我们说到,当任务的状态发生改变时(1、执行成功2、取消执行3、进度更新),工作线程会向UI线程的Handler传递消息。我们知道Handler要处理其他线程传递过来的消息。在AsyncTask中,InternalHandler是在UI线程上创建的,它接收来自工作线程的消息,实现代码如下:
private static class InternalHandler extends Handler { @SuppressWarnings({"unchecked","RawUseOfParameterizedType"}) @Override public voidhandleMessage(Message msg) { AsyncTaskResult result =(AsyncTaskResult) msg.obj; switch (msg.what) { caseMESSAGE_POST_RESULT: // There is onlyone result result.mTask.finish(result.mData[0]);//执行任务成功 break; caseMESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData);//进度更新 break; caseMESSAGE_POST_CANCEL: result.mTask.onCancelled();//取消任务 break; } } }
当接收到消息之后,AsyncTask会调用自身相应的回调方法。
总结:
1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。
2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务
3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数
发表评论
-
Android多线程:预读实现
2012-04-08 00:22 3019上一篇博文我们可以知道,使用AsyncTask有导致应用FC的 ... -
Android多线程:AsyncTask的分析
2012-04-05 13:34 4627开发Android应用的过程中,我们需要时刻注意保障应用的稳定 ... -
Android异步3:AsyncTask更新UI
2012-02-29 10:13 1389前天写了Thread+Handler的 ... -
Android异步2:深入详解 Handler+Looper+MessageQueue
2012-02-28 10:15 1721Android使用消息机制实现 ... -
Android异步1:Thread+Handler更新UI
2012-02-27 14:01 2274每个Android应用程序都运行在一个dalvik虚拟机进程中 ... -
WebView及js
2012-02-20 09:37 1319在Android中通过WebView控 ... -
Android用线程应注意
2012-02-17 09:36 1406我们都知道Hanlder是线程与Activity通信的桥梁,我 ... -
Android用线程应注意
2012-02-17 09:35 1我们都知道Hanlder是线程 ... -
Android Google Api 获取地址
2012-02-16 09:38 3376我们获取Location的目的之一肯定是有获取这个位置的详细地 ... -
Android获取经纬度
2012-02-16 09:34 4448Location 在Android 开发中还是经常用到的,比如 ... -
Android启动已安装应用
2012-02-15 22:45 1192如何在一个应用中 通过某个事件,而去启动另外一个已安装的应用。 ... -
Android 获取Ip
2012-02-15 22:41 1140我们开发中,有判断手机是否联网,或者想获得当前手机的Ip地址, ... -
布局定义菜单--MenuInflater的使用
2012-02-14 10:42 2226传统意义上的定义菜单感觉比较繁琐,当我们使用MenuInfla ... -
LayoutInflater的使用
2012-02-13 11:58 1369在实际开发种LayoutInflater这个类还是非常有用的, ... -
自定义属性
2012-02-13 11:54 1159在xml 文件里定义控件的属性,我们已经习惯了android: ... -
自定义View
2012-02-13 11:37 1014对于初学着来说,他们习惯了Android 传统的页面布局方式, ... -
Intent传递对象的两种方法(Serializable,Parcelable)
2012-02-13 10:23 30103今天讲一下Android中Intent中如何传递对象,就我目前 ... -
Android Service 服务详细讲解
2012-01-16 09:38 1028Android 的Service 和 Handler一样很重, ... -
自定义窗口标题
2011-11-06 14:10 1718我们看到过很多应用,他们的窗口标题行都不是系统默认的 要么有按 ...
相关推荐
本篇文章将深入探讨如何在Android中使用`AsyncTask`来异步加载网络图片。 首先,我们了解`AsyncTask`的基本结构。`AsyncTask`有三个泛型参数:`Params`, `Progress`, 和 `Result`。在本例中,`Params`通常是网络...
让我们深入了解一下`AsyncTask`及其工作原理。 ### 1. AsyncTask简介 `AsyncTask`是Android提供的一个轻量级组件,用于在后台线程执行任务,然后在UI线程更新结果。它包含三个泛型参数:`Params`、`Progress`和`...
本文将深入探讨`AsyncTask`的工作原理、使用方法以及注意事项。 ### 1. `AsyncTask`概述 `AsyncTask`是Android SDK中的一个抽象类,它允许开发者在后台线程中执行任务,并在UI线程中更新结果。它的设计目标是简化...
通过以上对 AsyncTask 的源码解析和使用方法的介绍,你应该对如何在 Android 应用中高效地使用异步任务有了更深入的理解。在实际开发中,正确理解和使用 AsyncTask 可以帮助我们编写出更加流畅、响应快速的应用程序...
在深入探讨AsyncTask的“黑暗面”之前,我们先来回顾一下AsyncTask的基本用法和工作原理。 AsyncTask主要由四个关键部分组成:onPreExecute()、doInBackground()、onProgressUpdate()和onPostExecute()。其中,...
在Android应用开发中,异步任务(AsyncTask)是一个常用工具,用于在后台线程执行耗时操作,然后在UI线程更新结果,避免阻塞用户界面。AsyncTask的使用和内部机制对于任何Android开发者来说都至关重要。让我们深入...
下面将详细解释Android异步任务的概念、工作原理以及如何在实际项目中应用。 一、Android异步任务概述 Android系统为了解决在主线程(UI线程)中执行耗时操作导致的应用程序无响应(ANR)问题,引入了异步任务。...
本文将深入探讨“android异步任务框架源码”,讲解其核心概念、工作原理以及如何实现。 Android中的异步任务通常通过AsyncTask类来实现。AsyncTask是一个轻量级的组件,设计用于在UI线程和后台线程之间进行通信。它...
对于深入理解Android的多线程编程,`AsyncTask`是一个重要的起点,但随着Android版本的更新,建议开发者了解并掌握更现代的异步处理技术,如`Coroutines`和`ViewModel`配合`LiveData`,以获得更好的性能和可维护性。...
下面我们将深入探讨`AsyncTask`的工作原理及其封装方法。 `AsyncTask`的核心在于三个泛型参数:`Params`、`Progress`和`Result`,它们分别代表了后台任务的输入参数类型、后台执行过程中的进度类型和任务执行结果的...
本篇文章将深入探讨Android AsyncTask的工作原理、使用方法以及一些常见应用场景。 **一、Android AsyncTask概述** AsyncTask是Android提供的一个类,它允许开发者在后台线程执行任务,然后在UI线程更新结果,以...
本文将深入探讨Android的AsyncTask及其与Handler的对比。 **AsyncTask详解** AsyncTask是Android SDK提供的一种轻量级的异步处理机制,特别适合于执行短时间的、与UI相关的后台任务。它的主要优点在于简化了UI更新...
本篇文章将深入探讨`AsyncTask`的工作原理和如何在实际应用中使用。 首先,`AsyncTask`是自Android 1.5版本起引入的,主要为了解决在Android平台上进行异步操作的问题。它通过提供一个简单的接口,允许开发者在后台...
这篇博文将深入探讨`AsyncTask`的工作原理及其在实际开发中的应用。 `AsyncTask`类提供了三个泛型参数:`Params`、`Progress`和`Result`。`Params`代表执行任务所需的输入参数类型,`Progress`表示后台任务执行过程...
在这个“一个AsyncTask异步任务的操作实例”中,我们将深入探讨AsyncTask的工作原理、使用方法以及如何在实际项目中应用。 1. **AsyncTask基本结构**: AsyncTask由三个泛型参数定义:`Params`, `Progress`, 和 `...
本文将深入探讨Android的异步加载解决方案,尤其是通过`AsyncTask`类实现的方式。 `AsyncTask`是Android SDK提供的一种轻量级的异步处理工具,适用于快速执行少量的后台任务。它具有三个泛型参数:`Params`(输入...
在本文中,我们将深入探讨AsyncTask的原理、使用方法以及其限制。 AsyncTask的定义: 正如官方文档所述,AsyncTask是为了方便在UI线程和后台线程之间进行交互而设计的。它允许开发者在后台执行操作,并在完成后更新...
下面,我们将深入探讨Android系统中的这些功能及其与AsyncTask的结合使用。 1. **拍照上传**: 在Android中,拍照通常通过调用`Intent`来启动系统相机应用完成。一旦用户拍摄照片,应用可以通过`onActivityResult...
本教程将深入讲解AsyncTask的工作原理、如何创建和使用,以及如何实现对异步任务状态的监控,特别是关注任务的结束状态。 AsyncTask的核心理念是“后台计算,前台显示”,它提供了三个泛型参数:Params, Progress, ...