<commit_before>---
layout: post
title: 调用AsyncTask的excute方法不能立即执行程序的原因分析及改善方案
category: Android
tags: Android
keywords: Android,AsyncTask,excute,AsyncTask not run
description: 调用AsyncTask的excute方法不能立即执行程序的原因分析及改善方案
---

&emsp;&emsp;最近在项目中遇到一个关于调用AsyncTask的excute方法不能立即执行程序的问题，项目的targetSdkVersion是15，最后分析发现是AsyncTask的运行机制导致，特地总结出来以免后面再犯同样的错误。

## 通过源码分析AsyncTask的工作原理

### AsyncTask官方文档解读

#### AsyncTask介绍

&emsp;&emsp;AsyncTask是一个Android SDK中轻量级的异步任务类，它在线程池中执行后台任务，把执行进度和执行结果返回给主线程，并在主线程更新UI，AsyncTask实质上是对Thread和Handler的封装，通过AsyncTask能够更方便地在执行后台任务的过程中和结束后实现更新UI操作。

#### AsyncTask的用法

&emsp;&emsp;AsyncTask是一个抽象类，它需要被实现后才能正常使用，子类必须要复写doInBackground方法，如果需要在执行完后台任务后更新UI，则需要实现onPostExecute方法，下面是一个AsyncTask使用实例：

	class DownloadFilesTask extends AsyncTask<URL, Integer, Long>{
		@Override
		protected Void doInBackground(Integer... params) {
			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));
         	}

          	return totalSize;
		}
		
		protected void onProgressUpdate(Integer... progress) {
          	setProgressPercent(progress[0]);
      	}
 
      	protected void onPostExecute(Long result) {
          	showDialog("Downloaded " + result + " bytes");
      	}
	}

	// 调用方式如下
	new DownloadFilesTask().excute(url1, url2, url3);

####　参数说明

&emsp;&emsp;AsyncTask的三个参数<Params, Progress, Result>说明：

- **Params**：执行AsyncTask时传递的参数类型；

- **Progress**:执行后台任务时更新进度的进度值类型；

- **Result**:后台任务执行完成后的返回值类型。

**注意：**并不是所有的参数都需要指明类型，如果某一个参数你没有用到，改成Void类型即可。

#### 执行流程

&emsp;&emsp;在AsyncTask执行的过程中，会经历如下四个步骤：

- **onPreExecute**：UI线程中调用，在调用excute方法后会立即被调用，这个方法适用于初始化task，比如显示后台任务进度条；

- **doInBackground**：非UI线程中调用，在onPreExecute执行后调用，这个方法适用于执行耗时的操作，excute方法中的Params参数就是通过这个方法传递的，该方法的返回值就是Task执行的结果，在doInBackground方法执行过程中，可以通过publishProgress方法来更新后台任务的执行进度；

- **onProgressUpdate**：UI线程中调用，在publishProgress方法后被调用，这个方法用于在后台任务执行过程中显示任务的进度UI，比如它可以用于显示进度条动画或者显示进度文本；

- **onPostExecute**：UI线程中调用，后台任务执行完成后被调用，Task返回的结果以参数的形式传递到该方法中。

#### 取消Task<commit_msg>改善博客格式<commit_after>---
layout: post
title: 调用AsyncTask的excute方法不能立即执行程序的原因分析及改善方案
category: Android
tags: Android
keywords: Android,AsyncTask,excute,AsyncTask not run
description: 调用AsyncTask的excute方法不能立即执行程序的原因分析及改善方案
---

&emsp;&emsp;最近在项目中遇到一个关于调用AsyncTask的excute方法不能立即执行程序的问题，项目的targetSdkVersion是15，最后分析发现是AsyncTask的运行机制导致，特地总结出来以免后面再犯同样的错误。

## 通过源码分析AsyncTask的工作原理

### AsyncTask官方文档解读

#### AsyncTask介绍

&emsp;&emsp;AsyncTask是一个Android SDK中轻量级的异步任务类，它在线程池中执行后台任务，把执行进度和执行结果返回给主线程，并在主线程更新UI，AsyncTask实质上是对Thread和Handler的封装，通过AsyncTask能够更方便地在执行后台任务的过程中和结束后实现更新UI操作。

#### AsyncTask的用法

&emsp;&emsp;AsyncTask是一个抽象类，它需要被实现后才能正常使用，子类必须要复写doInBackground方法，如果需要在执行完后台任务后更新UI，则需要实现onPostExecute方法，下面是一个AsyncTask使用实例：

	class DownloadFilesTask extends AsyncTask<URL, Integer, Long>{
		@Override
		protected Void doInBackground(Integer... params) {
			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));
         	}

          	return totalSize;
		}
		
		protected void onProgressUpdate(Integer... progress) {
          	setProgressPercent(progress[0]);
      	}
 
      	protected void onPostExecute(Long result) {
          	showDialog("Downloaded " + result + " bytes");
      	}
	}

	// 调用方式如下
	new DownloadFilesTask().excute(url1, url2, url3);


#### 参数说明

&emsp;&emsp;AsyncTask的三个参数<Params, Progress, Result>说明：

- **Params**：执行AsyncTask时传递的参数类型；

- **Progress**:执行后台任务时更新进度的进度值类型；

- **Result**:后台任务执行完成后的返回值类型。

**注意：**并不是所有的参数都需要指明类型，如果某一个参数你没有用到，改成Void类型即可。

#### 执行流程

&emsp;&emsp;在AsyncTask执行的过程中，会经历如下四个步骤：

- **onPreExecute**：UI线程中调用，在调用excute方法后会立即被调用，这个方法适用于初始化task，比如显示后台任务进度条；

- **doInBackground**：非UI线程中调用，在onPreExecute执行后调用，这个方法适用于执行耗时的操作，excute方法中的Params参数就是通过这个方法传递的，该方法的返回值就是Task执行的结果，在doInBackground方法执行过程中，可以通过publishProgress方法来更新后台任务的执行进度；

- **onProgressUpdate**：UI线程中调用，在publishProgress方法后被调用，这个方法用于在后台任务执行过程中显示任务的进度UI，比如它可以用于显示进度条动画或者显示进度文本；

- **onPostExecute**：UI线程中调用，后台任务执行完成后被调用，Task返回的结果以参数的形式传递到该方法中。

#### 取消Task
{'fraction_non_alphanumeric': 0.11419172932330827, 'fraction_numerical': 0.005169172932330827, 'mean_word_length': 5.9332247557003255, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1214539', 'n_tokens_mistral': 2283, 'n_tokens_neox': 2442, 'n_words': 175}