## 安卓多任務(wù)實(shí)現(xiàn)的基本原理
### 一.基本概念
>? 操作一些耗時(shí)操作時(shí)候雳攘,如I/O讀寫大文件,數(shù)據(jù)庫操作以及網(wǎng)絡(luò)下載需要很長時(shí)間埋合,為了不阻塞用戶界面创淡,出現(xiàn)ANR(應(yīng)用程序無響應(yīng))的響應(yīng)提示窗口,這個(gè)時(shí)候我們考慮使用Thread線程來進(jìn)行解決.? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
### 二.Android中的進(jìn)程和線程
> 在Android系統(tǒng)中儒陨,如果有一個(gè)應(yīng)用程序組件時(shí)第一次被啟用花嘶,而且這時(shí)候,應(yīng)用程序也沒有其他的組件來運(yùn)行蹦漠,則Android系統(tǒng)會(huì)為應(yīng)用程序創(chuàng)建一個(gè)linux的**進(jìn)程**椭员,這個(gè)Linux進(jìn)程包含一個(gè)**線程**,稱為**主線程**或者**UI線程**.
> 當(dāng)一個(gè)組件在被啟動(dòng)時(shí),如果該process已經(jīng)存在了笛园,那么該組件就直接通過這個(gè)process被啟動(dòng)起來隘击,并且運(yùn)行在這個(gè)process的UI線程中.
#### 1.進(jìn)程
* 默認(rèn)情況下,同一個(gè)應(yīng)用程序內(nèi)的所有組件都是運(yùn)行在同一個(gè)進(jìn)程中的喘沿,大部分應(yīng)用程序都是按照這種方式運(yùn)行的闸度;
* 在具體應(yīng)用中,很多時(shí)候需要通過在manifest文件中進(jìn)行設(shè)置蚜印,通過修改四大組件在Manifest.xml的代碼塊中的android:proess屬性指定組件運(yùn)行的進(jìn)程,使其運(yùn)行在不同的process中留量。
* <application>中的元素也支持android:proess屬性窄赋,用于指定所有組件的默認(rèn)進(jìn)程。
#### 2.進(jìn)程的重要性層次結(jié)構(gòu)
**進(jìn)程有5中層次楼熄,按其重要程度遞減分為**
> 1.前臺(tái)進(jìn)程(用戶當(dāng)前操作所必須的進(jìn)程)
* 擁有一個(gè)正在與用戶交互的Activity
* 擁有一個(gè)Service忆绰,這個(gè)Service綁定了某一個(gè)正在與用戶交互的Activity
* 擁有一個(gè)前臺(tái)Service
* 擁有一個(gè)Service且它正在執(zhí)行聲明周期回調(diào)方法
* 擁有一個(gè)BroadcastReceiver且這個(gè)BroadcastReceiver正在執(zhí)行onRece方法
> 2.可見進(jìn)程
* 沒有任何前臺(tái)組件,但是仍然會(huì)影響用戶在屏幕上所見內(nèi)容的進(jìn)程
* 擁有一個(gè)可見但是不可與用戶交互的Activity
* 擁有一個(gè)Service可岂,這個(gè)Service綁定了一個(gè)可見但是不可與用戶進(jìn)行交互的Activity
> 3.服務(wù)進(jìn)程
* 由startService()方法啟動(dòng)的Service進(jìn)程错敢,雖然不直接和所見內(nèi)容關(guān)聯(lián),但是會(huì)執(zhí)行一些用戶關(guān)心的操作,例如后臺(tái)播放音樂或者下載數(shù)據(jù)等等
* 若系統(tǒng)不足以維持前臺(tái)進(jìn)程和可見進(jìn)程稚茅,才會(huì)犧牲服務(wù)進(jìn)程的空間
> 4.后臺(tái)進(jìn)程
* 包含用戶不可見的Activity的進(jìn)程,這些進(jìn)程對用戶體驗(yàn)沒有直接影響纸淮,可以隨時(shí)在任意時(shí)間終止它們,以回收內(nèi)存資源.
* 系統(tǒng)通過LRU(最近最少使用)列表進(jìn)行多個(gè)后臺(tái)進(jìn)程的管理亚享,確保最近使用的Activity最后被終止
> 5.空進(jìn)程
* 進(jìn)程不含有任何應(yīng)用組件咽块,該進(jìn)程主要作用是緩存,以改善在此進(jìn)程中運(yùn)行組件的啟動(dòng)時(shí)間欺税。
* 系統(tǒng)會(huì)經(jīng)常終正此類進(jìn)程
#### 3.線程
> Android是單線程模型侈沪,我們創(chuàng)建的Service、Activity以及Broadcast均是在一個(gè)主線程處理晚凿,這里我們可以理解為uI線程亭罪。(應(yīng)用程序是一個(gè)默認(rèn)的**單線程單任務(wù)程序**)
> Ul Thread中運(yùn)行著許多重要的邏輯,如系統(tǒng)事件處理歼秽,用戶輸入事件處理应役,ul繪制,Service,Alarm等
> 我們編寫的代碼穿插在主線程的邏輯中哲银,比如對用戶觸摸事件的檢測和響應(yīng)扛吞,對用戶輸入的處理,自定義View的繪制等荆责。如果我們插入的代碼比價(jià)耗時(shí)滥比,如網(wǎng)絡(luò)請求或數(shù)據(jù)庫讀取,就會(huì)阻塞uI線程其他邏輯的執(zhí)行做院,從而導(dǎo)致界面卡頓盲泛。
> 如果卡頓時(shí)間超過5秒,系統(tǒng)就會(huì)報(bào)ANR錯(cuò)誤键耕。所以寺滚,執(zhí)行耗時(shí)的操作,我們需要另起線程執(zhí)行屈雄。
> 在新線程執(zhí)行完耗時(shí)的邏輯后村视,往往需要將結(jié)果反饋給界面,進(jìn)行uI更新酒奶。Android的ul toolkit不是線程安全的蚁孔,不能在非uI線程進(jìn)行uI的更新
> **所有對界面的更新必須在uI線程進(jìn)行**
> 安卓的單線程模式遵從兩個(gè)原則
>
> * 1.不要阻塞UI進(jìn)程
> * 2.不要在UI線程之外訪問UI組件
> 創(chuàng)建線程:? 基礎(chǔ)操作都在UI線程中運(yùn)行,耗時(shí)操作可以創(chuàng)建新的線程去完成
* 繼承Thread類
* 實(shí)現(xiàn)Runnable接口
> **安卓提供的四種常用的操作多線程的方式惋嚎,分別是:**
* Handle + Thread
* AsyncTask
* ThreadPoolExecutor
* IntentService
————————————————————————————————————————————————————————————————————
### 三杠氢、實(shí)現(xiàn)多任務(wù)
#### 1.多任務(wù)的實(shí)現(xiàn)原理
* **在Android中,我們把除uI線程外的另伍,其他所有的線程都叫做工作線程鼻百,也就是說Android只會(huì)存在兩種線程:UI主線程(ul thread)和工作線程(work thread)**
* 我們把耗時(shí)的操作放在工作線程中去做。操作完成后,再通知UI主線程做出相應(yīng)的響應(yīng)温艇。
* 這就需要掌握線程間通信的方式因悲。在Android中提供了兩種線程間的通信方式:
? * AsyncTask機(jī)制
? * Handler機(jī)制
##### (1)使用AsyncTask
* AsyncTask是Android框架提供的**異步處理**的輔助類,它可以實(shí)現(xiàn)耗時(shí)操作仕具他線程執(zhí)行中贝,而處理結(jié)果在Main線程執(zhí)行
* 它屏蔽掉了多線程和Handler的概念囤捻,進(jìn)行了較高程度的封裝。
* 使用AsyncTask的代碼很容易被理解邻寿,因?yàn)樗麄兌加幸恍┚哂刑囟氊?zé)的方法蝎土,如:預(yù)處理的方法onPreExecute,后臺(tái)執(zhí)行任務(wù)的方法dolnBackground绣否,更新進(jìn)度的方法publishProgress誊涯,返回結(jié)果的方法onPostExecute等等
##### (2)Handle機(jī)制
* Handler機(jī)制是通過消息隊(duì)列進(jìn)行通信的機(jī)制,通過使用Handler,LooperMessageQueue蒜撮,和Message這幾個(gè)類協(xié)調(diào)來完成
? * Handler:在android里負(fù)責(zé)發(fā)送和處理消息暴构,通過它可以實(shí)現(xiàn)其他線程與Main線程之間的消息通訊
? * Looper:負(fù)責(zé)管理線程的消息隊(duì)列和消息循環(huán)
? * MessageQueue:消息隊(duì)列,先進(jìn)先出段磨,它的作用是保存有待線程處理的消息
#####? ? (3)Handler類
* UI主線程在創(chuàng)建時(shí)會(huì)被自動(dòng)創(chuàng)建一個(gè)消息隊(duì)列和消息循環(huán)取逾,主線程的Looper通過創(chuàng)建一個(gè)Handler對象,對外界提供了訪問消息隊(duì)列的渠道
? * 主線程通過Handler.handleMessage()讀取消息隊(duì)列中的消息
? * 工作線程通過方法發(fā)送消息到主線程的消息隊(duì)列**Handler.sendMessage()? ? Handler.post()**
————————————————————————————————————————————————————————————————
### 四苹支、.Android實(shí)現(xiàn)多線程的兩種操作模式
#### 1Android有兩種方式實(shí)現(xiàn)多線程操作UI:
* 第一種是創(chuàng)建新線程Thread砾隅,用handler負(fù)責(zé)線程間的通信和消息。
* 第二種方式AsyncTask異步執(zhí)行任務(wù)
#### 2.使用Handler實(shí)現(xiàn)多任務(wù)
在新的線程中調(diào)用主線程中的Handler的postXX和sendmessage方法來實(shí)現(xiàn)與主線程進(jìn)行通信
**使用post方法實(shí)現(xiàn)多任務(wù)的主要步驟**:
* 創(chuàng)建一個(gè)Handler對象债蜜;
* 將要執(zhí)行的操作卸載線程對象的run方法中晴埂;
* 使用post方法運(yùn)行線程對象
* 如果需要循環(huán)執(zhí)行,需要在線程對象的run方法中再次調(diào)用post方法
#### 3.Handler機(jī)制實(shí)現(xiàn)異步任務(wù)demo
* xml文件中添加一個(gè)TextView
? ```xml
? <?xml version="1.0" encoding="utf-8"?>
? <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
? ? ? xmlns:app="http://schemas.android.com/apk/res-auto"
? ? ? xmlns:tools="http://schemas.android.com/tools"
? ? ? android:layout_width="match_parent"
? ? ? android:layout_height="match_parent"
? ? ? tools:context=".AsynchronousTask.HandlerAsyTaskActivity">
? ? ? <TextView
? ? ? ? ? android:id="@+id/textview"
? ? ? ? ? android:layout_width="match_parent"
? ? ? ? ? android:layout_height="wrap_content"
? ? ? ? ? android:text="hello"
? ? ? ? ? android:textAllCaps="false"
? ? ? ? ? tools:ignore="MissingConstraints" />
? </androidx.constraintlayout.widget.ConstraintLayout>
? ```
* java文件 編輯代碼
? ```java
? package com.example.handleractivity.AsynchronousTask;
? import androidx.annotation.NonNull;
? import androidx.appcompat.app.AppCompatActivity;
? import android.os.Bundle;
? import android.os.Handler;
? import android.os.Message;
? import android.widget.TextView;
? import com.example.handleractivity.R;
? public class HandlerAsyTaskActivity extends AppCompatActivity {
? ? ? private final static int TEST = 1;
? ? ? private TextView textView;
? ? ? //這是自己創(chuàng)建的Handler寻定,實(shí)現(xiàn)異步任務(wù)儒洛,這里用來更改UI
? ? ? private Handler mHandler = new Handler(){
? ? ? ? ? @Override
? ? ? ? ? public void handleMessage(@NonNull Message msg) {
? ? ? ? ? ? ? textView.setText("這是工作線程文本");
? ? ? ? ? }
? ? ? };
? ? ? @Override
? ? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? ? setContentView(R.layout.activity_handler_asy_task);
? ? ? ? ? textView = findViewById(R.id.textview);
? //? ? ? ? textView.setText("這是一段文本");
? ? ? ? ? new ActivityThread().start();
? ? ? }
? ? ? /*
? ? ? 這是一個(gè)線程不安全的行為
? ? ? */
? ? ? class ActivityThread extends Thread{
? ? ? ? ? @Override
? ? ? ? ? public void run() {
? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? Thread.sleep(3000);
? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? }
? //? ? ? ? ? ? textView.setText("這是工作線程文本");
? ? ? ? ? ? ? //使用handler發(fā)送消息至消息隊(duì)列
? ? ? ? ? ? ? Message message = new Message();
? ? ? ? ? ? ? message.what = TEST;
? ? ? ? ? ? ? mHandler.sendMessage(message);
? ? ? ? ? }
? ? ? }
? }
? ```
> 我們設(shè)置一個(gè)線程,讓其休眠3秒鐘狼速,然后執(zhí)行 textView.setText("這是工作線程文本")操作琅锻,三秒之后程序會(huì)崩潰。
>
> 原因是: 不能在除了UI線程之外的線程里邊進(jìn)行更改UI的操作向胡。
那怎么才能實(shí)現(xiàn)呢浅浮?
> 使用Handler實(shí)現(xiàn)異步任務(wù),自己新建一個(gè)Handler捷枯,然后在工作線程中使用handler來傳遞信息。handler里面進(jìn)行更改UI的操作专执,就可了
### 五淮捆、Handler機(jī)制方法調(diào)用
#### 1.使用Runnable和Handler實(shí)現(xiàn)五秒鐘之后出現(xiàn)彈窗
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
? ? xmlns:app="http://schemas.android.com/apk/res-auto"
? ? xmlns:tools="http://schemas.android.com/tools"
? ? android:layout_width="match_parent"
? ? android:layout_height="match_parent"
? ? tools:context=".HandlerPost.HandlerPostActivity">
? ? <Button
? ? ? ? android:id="@+id/btnShowToast"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="開啟Toast"/>
? ? <TextView
? ? ? ? android:text="你好"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"/>
</LinearLayout>
```
```java
public class HandlerPostActivity extends AppCompatActivity implements View.OnClickListener{
? ? //寫一個(gè)Handler
? ? Handler countHandler = new Handler();
? ? /*線程1:啟動(dòng)一個(gè)Toast顯示線程*/
? ? Runnable mRunToast = new Runnable() {
? ? ? ? @Override
? ? ? ? public void run() {
? ? ? ? ? ? Toast.makeText(HandlerPostActivity.this,"hello Toast",Toast.LENGTH_SHORT).show();
? ? ? ? }
? ? };
? ? private Button mbtnShowToast;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_handler_post);
? ? ? ? mbtnShowToast = findViewById(R.id.btnShowToast);
? ? ? ? mbtnShowToast.setOnClickListener(this);
? ? }
? ? //添加事件監(jiān)聽
? ? @Override
? ? public void onClick(View v) {
? ? ? ? switch (v.getId()) {
? ? ? ? ? ? case R.id.btnShowToast:
? ? ? ? ? ? ? ? /**
? ? ? ? ? ? ? ? * SystemClock.uptimeMillis()表示開機(jī)到當(dāng)前的一個(gè)累計(jì)時(shí)間
? ? ? ? ? ? ? ? */
? ? ? ? ? ? ? ? countHandler.postAtTime(mRunToast, SystemClock.uptimeMillis()+5*1000);
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }
}
```
#### 2.開辟一個(gè)工作線程配合Handler實(shí)現(xiàn)計(jì)數(shù)器的功能
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
? ? xmlns:app="http://schemas.android.com/apk/res-auto"
? ? xmlns:tools="http://schemas.android.com/tools"
? ? android:layout_width="match_parent"
? ? android:layout_height="match_parent"
? ? tools:context=".HandlerPost.HandlerPostActivity"
? ? android:orientation="vertical">
? ? <Button
? ? ? ? android:id="@+id/btnStart"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="啟動(dòng)"/>
? ? <Button
? ? ? ? android:id="@+id/btnStop"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="關(guān)閉"/>
? ? <Button
? ? ? ? android:id="@+id/btnShowToast"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="開啟Toast"/>
? ? <TextView
? ? ? ? android:id="@+id/tvCount"
? ? ? ? android:text="你好"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"/>
</LinearLayout>
```
```java
public class HandlerPostActivity extends AppCompatActivity implements View.OnClickListener {
? ? Handler countHandler = new Handler();
? ? int count = 0;
? ? /*線程1:啟動(dòng)一個(gè)Toast顯示線程*/
? ? Runnable mRunToast = new Runnable() {
? ? ? ? @Override
? ? ? ? public void run() {
? ? ? ? ? ? Toast.makeText(HandlerPostActivity.this, "hello Toast", Toast.LENGTH_SHORT).show();
? ? ? ? }
? ? };
? ? /*線程2:文本區(qū)計(jì)數(shù)器線程*/
? ? Runnable mRunCount = new Runnable() {
? ? ? ? @Override
? ? ? ? public void run() {
? ? ? ? ? ? textCount.setText("count: " + String.valueOf(count++));
? ? ? ? ? ? //再調(diào)用一次,以此形成一個(gè)類似于循環(huán)的操作,一秒加一次
? ? ? ? ? ? countHandler.postDelayed(mRunCount, 1000);
? ? ? ? }
? ? };
? ? private Button mbtnShowToast;
? ? private TextView textCount;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_handler_post);
? ? ? ? mbtnShowToast = findViewById(R.id.btnShowToast);
? ? ? ? mbtnShowToast.setOnClickListener(this);
? ? ? ? findViewById(R.id.btnStart).setOnClickListener(this);
? ? ? ? findViewById(R.id.btnStop).setOnClickListener(this);
? ? ? ? textCount = findViewById(R.id.tvCount);
? ? }
? ? //添加事件監(jiān)聽
? ? @Override
? ? public void onClick(View v) {
? ? ? ? switch (v.getId()) {
? ? ? ? ? ? case R.id.btnShowToast:
? ? ? ? ? ? ? ? /**
? ? ? ? ? ? ? ? * SystemClock.uptimeMillis()表示開機(jī)到當(dāng)前的一個(gè)累計(jì)時(shí)間
? ? ? ? ? ? ? ? */
? ? ? ? ? ? ? ? countHandler.postAtTime(mRunToast, SystemClock.uptimeMillis() + 5 * 1000);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case R.id.btnStart:
? ? ? ? ? ? ? ? //表示推遲一秒執(zhí)行
? ? ? ? ? ? ? ? countHandler.postDelayed(mRunCount, 1000);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case R.id.btnStop:
? ? ? ? ? ? ? ? //移除回調(diào)的過程
? ? ? ? ? ? ? ? countHandler.removeCallbacks(mRunCount);
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }
}
```
運(yùn)行效果;

### 六、AsyncTask實(shí)現(xiàn)多任務(wù)
* 使用Handler類來在子線程中更新UI線程總會(huì)啟動(dòng)一些匿名的子線程攀痊,太多的子線程給系統(tǒng)帶來了巨大的負(fù)擔(dān)
* Andoroid提供了一個(gè)工具類AdyncTask桐腌,來實(shí)現(xiàn)異步執(zhí)行任務(wù)
* AsyncTask是抽象類,具有三種泛型:Params苟径、Progress案站、Result
? * **Params: **表示啟動(dòng)任務(wù)執(zhí)行的參數(shù),比如HTTP請求的URL
? * **Progress:** 表示后臺(tái)任務(wù)執(zhí)行的百分比
? * **Result: **表示后臺(tái)執(zhí)行任務(wù)最終返回的結(jié)果棘街,比如String,Integer等
* 通過繼承一個(gè)AsyncTask類定義一個(gè)異步任務(wù)類
* Android提供一個(gè)讓程序員編寫后臺(tái)操作更為容易和透明AsyncTask,使得后臺(tái)線程能夠在UI主線程外進(jìn)行處理
* 使用AsyncTask蟆盐,不需要自己來寫后臺(tái)線程,無需終結(jié)后臺(tái)線程遭殉,只需要?jiǎng)?chuàng)建AsyncTask類石挂,并實(shí)現(xiàn)其中的抽象方法以及重寫某些方法
> 下面是一個(gè)實(shí)例,點(diǎn)擊按鈕险污,啟動(dòng)進(jìn)度條痹愚。進(jìn)度條加載完畢,把“執(zhí)行完畢”顯示在文本上
#### 1.xml文件
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
? ? xmlns:app="http://schemas.android.com/apk/res-auto"
? ? xmlns:tools="http://schemas.android.com/tools"
? ? android:layout_width="match_parent"
? ? android:layout_height="match_parent"
? ? android:orientation="vertical"
? ? tools:context=".AsynchronousTask.AsyncTaskDemo">
? ? <Button
? ? ? ? android:id="@+id/btn"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="Press it"
? ? ? ? android:textAllCaps="false" />
? ? <TextView
? ? ? ? android:id="@+id/txt"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:layout_gravity="center"
? ? ? ? android:textSize="30sp"
? ? ? ? android:text="hello world" />
? ? <ProgressBar
? ? ? ? android:id="@+id/progressbar"
? ? ? ? style="@style/Widget.AppCompat.ProgressBar.Horizontal"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:visibility="invisible"
? ? ? ? android:layout_marginTop="50dp" />
</LinearLayout>
```
#### 2.java文件
```java
public class AsyncTaskDemo extends AppCompatActivity implements View.OnClickListener {
? ? private final static String TAG = "AsyncTaskDemo";
? ? private Button mBtn;
? ? private ProgressBar progressBar;
? ? private TextView mTxt;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_async_task_demo);
? ? ? ? mBtn = findViewById(R.id.btn);
? ? ? ? mBtn.setOnClickListener(this);
? ? ? ? progressBar = findViewById(R.id.progressbar);
? ? ? ? mTxt = findViewById(R.id.txt);
? ? }
? ? @Override
? ? public void onClick(View v) {
? ? ? ? TimeTickLoad timeTickLoad = new TimeTickLoad();
? ? ? ? timeTickLoad.execute(1000);
? ? }
? ? class TimeTickLoad extends AsyncTask<Integer,Integer,String>{
? ? ? ? @Override
? ? ? ? protected void onPreExecute() {
? ? ? ? ? ? Log.i(TAG, "onPreExecute");
? ? ? ? ? ? progressBar.setVisibility(ProgressBar.VISIBLE);
? ? ? ? ? ? super.onPreExecute();
? ? ? ? }
? ? ? ? @Override
? ? ? ? protected void onPostExecute(String s) {
? ? ? ? ? ? Log.i(TAG, "onPostExecute");
? ? ? ? ? ? super.onPostExecute(s);
? ? ? ? ? ? mTxt.setText(s);
? ? ? ? }
? ? ? ? @Override
? ? ? ? protected void onProgressUpdate(Integer... values) {
? ? ? ? ? ? mTxt.setText("onProgressUpdate");
? ? ? ? ? ? Log.i(TAG, "onProgressUpdate");
? ? ? ? ? ? //更新進(jìn)度條
? ? ? ? ? ? progressBar.setProgress(values[0]);
? ? ? ? ? ? super.onProgressUpdate(values);
? ? ? ? }
? ? ? ? /**
? ? ? ? 這個(gè)方法是使用AsyncTask必須進(jìn)行覆寫的一個(gè)方法蛔糯,耗時(shí)的操作在此方法內(nèi)執(zhí)行
? ? ? ? */
? ? ? ? @Override
? ? ? ? protected String doInBackground(Integer... integers) {
? ? ? ? ? ? //這里不能撰寫UI相關(guān)操作
? ? ? ? ? ? Log.i(TAG, "hello");
//? ? ? ? ? ? mTxt.setText("doInBackground");
? ? ? ? ? ? for (int i = 0; i < 10; i++) {
? ? ? ? ? ? ? ? //執(zhí)行此操作會(huì)自動(dòng)調(diào)用onProgressUpdate()
? ? ? ? ? ? ? ? publishProgress(i*10);
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Thread.sleep(integers[0]);
? ? ? ? ? ? ? ? }catch (Exception e){
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return "執(zhí)行完畢";
? ? ? ? }
? ? }
}
```
> AsyncTask的周期:

**從打印的日志可以看出拯腮,首先運(yùn)行的是onPreExecute()方法,然后運(yùn)行的是doInBackground(),最后運(yùn)行的是onPostExecute**
> 運(yùn)行效果:

#### 3.實(shí)現(xiàn)步驟
* 使用execute方法出發(fā)異步任務(wù)的執(zhí)行
* 使用onPreExecute()表示執(zhí)行預(yù)處理 : 在本例中實(shí)現(xiàn)繪制一個(gè)進(jìn)度條控件
* 使用doInBackground()用于執(zhí)行較為費(fèi)時(shí)的操作:在本例中就是計(jì)算進(jìn)度
? **這個(gè)方法是AsyncTask的關(guān)鍵蚁飒,必須進(jìn)行覆寫**
* 使用onProgressUpdate()對進(jìn)度條控件根據(jù)進(jìn)度值做出具體的響應(yīng)
* 使用onPostExecute()可以對后臺(tái)任務(wù)的結(jié)果做出處理