Android基础知识-AsyncTask相关

线程是操作系统调度的最小单元
线程是一种受限的系统资源,不可能无限制的产生,线程创建和销毁都会有相应开销。

线程池缓存一定数量的线程,避免频繁创建和销毁线程带来的系统开销。

Android中线程池,是通过 Executor 派生特定类型的线程池。

一、AsyncTask的使用和注意事项

public abstract class AsyncTask<Params, Progress, Result> {
}
1、参数

AsyncTask 是轻量级的异步任务类,在线程池中执行后台任务
把执行的 进度、结果 传递给主线程。
内部封装了 线程池 、 MainHandler

参数一:Params 参数的类型

参数二:Progress 后台任务的执行进度的类型

参数三:Result 后台任务的返回结果类型

如果AsyncTask 不需要传递具体参数,者三个泛型参数可以用Void代替

2、限制

1)AsyncTask 的 类要在主线程中加载(android 4.1 以上版本中系统自动完成)
2)AsyncTask 对象必须在 主线程 创建
3)execute 方法必须在 主线程 调用
4)不要在程序中直接调用 onPreExecute()、onPostExecute()、doInBackgound()、onProgressUpdate
AsyncTask 内部调用的
5)一个AsyncTask 对象 只能执行一次,只能 调一次execute 方法,否则会报运行时异常
6) android 1.6 之后 AsyncTask 采用线程池处理并行任务。

二、AsyncTask几个重要的方法

doInBackgound、onProgressUpdate、onPostExecute

1、onPreExecute()

任务执行之前,在 主线程 回调,用于做一些准备工作。

2、doInBackgound(Params… params)

线程池中执行,params 表示入参

在此方法中,通过 publishProgress 方法更新任务进度,
publishProgress 方法,会调用 onProgressUpdate 方法,
doInBackgound 方法,返回计算结果给 onPostExecute 方法

3、onProgressUpdate(Progress… values)

执行进度改变时,在主线程回调

4、onPostExecute(Result result)

任务执行完成,在主线程中回调,result 参数是后台任务返回值。

5、onCanceled()

任务被取消时,在主线程回调,此时 onPostExecute 不会被调用。

6、 使用
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
	
	@Override
	protected Long doInBackgound(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));
			
			if(isCancelled()) {
				break;
			}
		}
		return totalSize;
	}
	
	@Override
	protected void onProgressUpdate(Integer... progress) {
		//更新UI
		setProgressPercent(progress[0]);
	}
	
	@Override
	protected void onPostExecute(Long result) {
		//结果处理
		showDialog("Downloaded " + result + " bytes")
	}
}

new DownloadFilesTask().execute(url1, url2, url3);

三、AsyncTask的工作原理

任务队列容量为 128
AsyncTask 先将任务塞入队列,再用线程池执行任务,
执行时通过publishProgress 更新进度到主线程
执行完成后结果回调主线程返回结果
AsyncTask 有 mStatus字段记录状态,每个 AsyncTask 只能执行一次 execute 方法

public abstract class AsyncTask<Params, Progress, Result> {	
	private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
	private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
	private static final int KEEP_ALIVE_SECONDS = 30;

	//任务队列容量为 128
	private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);
	
	//用于执行任务的线程池
	public static final Executor THREAD_POOL_EXECUTOR;
	
	static {
		ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
				CORE_POOL_SIZE,     //核心线程数:CPU核心数-1 并且最少为2,最大为4
				MAXIMUM_POOL_SIZE,  //最大线程数:CPU核心数*2+1
				KEEP_ALIVE_SECONDS, //闲置时间30秒
				TimeUnit.SECONDS,
				sPoolWorkQueue, sThreadFactory);
		threadPoolExecutor.allowCoreThreadTimeOut(true);
		THREAD_POOL_EXECUTOR = threadPoolExecutor;
	}
	
	//用于排队任务
	public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
	private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
	
	//用于将执行环境从线程池切换到主线程
	private final Handler mHandler;
	
	//一个串行的线程池,添加的任务会放到一个队列中,按顺序执行。
	SerialExecutor implements Executor {
		final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
		Runnable mActive;

		public synchronized void execute(final Runnable r) {
			//把要执行的任务,塞到 mTasks 队列中
			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);
			}
		}
	}

	public AsyncTask(@Nullable Looper callbackLooper) {
		// 绑定主线程的 Handler
		mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
			? getMainHandler()
			: new Handler(callbackLooper);
		...
		mWorker = new WorkerRunnable<Params, Result>() {
			public Result call() throws Exception {
				...
				try {
					//线程池中执行 doInBackgound()
					//noinspection unchecked
					result = doInBackground(mParams);
				} catch (Throwable tr) {
					mCancelled.set(true);
					throw tr;
				} finally {
					//执行完后,发消息,通知主线程,执行 AsyncTask.finish()方法
					postResult(result);
				}
				...
				return result;
			}
		};

		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 occurred while executing doInBackground()",
							e.getCause());
				} catch (CancellationException e) {
					postResultIfNotInvoked(null);
				}
			}
		};
	}
	
	private Result postResult(Result result) {
		@SuppressWarnings("unchecked")
		//Handler 在主线程收到消息后,会执行 finish() 方法
		Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
				new AsyncTaskResult<Result>(this, result));
		message.sendToTarget();
		return result;
	}

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

	@MainThread
	public final AsyncTask<Params, Progress, Result> execute(Params... params) {
		/* sDefaultExecutor 是一个串行的线程池,
		 * 一个进程中所有的AsyncTask,都在这个串行的线程池中排队执行
		 */
		return executeOnExecutor(sDefaultExecutor, params);
	}
	
	@MainThread //主线程中执行
	public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
		if (mStatus != Status.PENDING) {//一个 AsyncTask对象,只能执行一次
			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;
	}
}	

推荐阅读:

《Android开发艺术探索》第十一章 Android的线程和线程池
《Java并发编程的艺术》第九章 Java中的线程池,第十章 Executor框架

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值