第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

Android 入門教程

菜單類控件
菜單:Menu
并發(fā)編程
多線程

AsyncTask:異步任務(wù)

在前面的章節(jié)有提到過,Android 系統(tǒng)默認會在主線程(UI 線程)執(zhí)行任務(wù),但是如果有耗時程序就會阻塞 UI 線程,導(dǎo)致頁面卡頓。這時候我們通常會將耗時任務(wù)放在獨立的線程,然后通過 Handler 等線程間通信機制完成 UI 的刷新。很多時候我們也許只是想執(zhí)行一個簡單的任務(wù),為此寫一套 Handler 線程通信就會顯得比較復(fù)雜,不用擔(dān)心,Android 系統(tǒng)為我們提供了一個專門用于執(zhí)行異步任務(wù)的工具——Async Task,它可以讓我們執(zhí)行后臺任務(wù)并輕松的與 UI 線程進行狀態(tài)同步,今天就一起來學(xué)習(xí)一下 AyncTask 的用法。

1. AsyncTask 簡介

AsyncTask 類通常用來在執(zhí)行后臺任務(wù)的同時刷新 UI,通過調(diào)用execute()方法觸發(fā)后臺任務(wù)的執(zhí)行,首先會回調(diào) AsyncTask 的onPreExecute(),接著回調(diào)doInBackground()來執(zhí)行自定義的后臺任務(wù),最后回調(diào)onPostExecute()方法用來刷新 UI,整體流程示意圖如下:

圖片描述

2. AsyncTask 的基本用法

2.1 聲明 AsyncTask

我們不能直接創(chuàng)建 AsyncTask,正確的方法是繼承自 AsyncTask 實現(xiàn)一個它的子類,如下:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
        protected Long doInBackground(URL... urls) {
             // 執(zhí)行后臺耗時任務(wù)
            return;
        }

        protected void onProgressUpdate(Integer... progress) {
            // 任務(wù)執(zhí)行進度更新
        }

        protected void onPostExecute(Long result) {
            // 執(zhí)行完畢,更新UI
        }
    }

以上是 AsyncTask 的核心回調(diào)方法,每個方法的含義會在后面具體講到。

2.2 指定參數(shù)

AsyncTask 可以幫助你在子線程和主線程之間同步參數(shù),根據(jù)不同的業(yè)務(wù)場景,參數(shù)類型和個數(shù)也會不一樣。剛剛在 2.1 小節(jié)聲明 AyncTask 子類的時候,需要傳入 3 個泛型參數(shù):

  • TypeOfVarArgParams:
    在任務(wù)啟動之后,傳入給后臺任務(wù)的參數(shù)類型

  • ProgressValue:
    啟動之后到任務(wù)結(jié)束之間,系統(tǒng)會不斷回調(diào)此方法,用來更新任務(wù)的進度

  • ** ResultValue:**
    后臺任務(wù)的執(zhí)行結(jié)果

2.3 啟動后臺任務(wù)

在聲明完后臺任務(wù)之后,就可以直接啟動了。啟動方式比較簡單,直接通過調(diào)用execute()方法啟動后臺任務(wù):

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

3 AsyncTask 關(guān)鍵回調(diào)方法

AsyncTask 是由 4 個回調(diào)方法配合組成,這 4 個回調(diào)方法按照一定的順序依次被調(diào)用,所以我們需要 focus 的是在正確的回調(diào)方法中實現(xiàn)我們想要的邏輯,下面詳細看看如何使用。

  • onPreExecute():
    在執(zhí)行execute()方法之后該方法立即被調(diào)用,標志著 AyncTask 正式開啟。通常用來做一些需要在后臺任務(wù)開啟之前完成的初始化工作,比如展示一個進度條、或者彈出一個對話框等等。該方法在 UI 線程執(zhí)行。
  • doInBackground(Params):
    在執(zhí)行完onPreExecute()方法之后立即被調(diào)用,用來執(zhí)行需要放在后臺執(zhí)行的耗時任務(wù)。在創(chuàng)建 AsyncTask 的時候傳入的參數(shù)就是提供給doInBackground使用的。在后臺任務(wù)執(zhí)行完畢后,還需要將執(zhí)行結(jié)果返回到onPostExecutes ()中,同時我們也可以通過publishProgress(Progress…)方法來手動發(fā)布任務(wù)進度,進度將從子線程發(fā)送到 UI 線程。毋庸置疑,該方法在子線程中執(zhí)行。
  • onProgressUpdate(Progress…):
    當(dāng)我們通過publishProgress(Params)發(fā)布進度之后,系統(tǒng)會回調(diào)該方法,用來獲取任務(wù)執(zhí)行進度并更新 UI。這一步就完成了子線程到主線程的通信,該方法在 UI 線程執(zhí)行
  • onPostExecute(Result):
    當(dāng)后臺任務(wù)執(zhí)行完畢,該方法被回調(diào),同時標志著整個 AyncTask 結(jié)束。與onPreExecute相反,通常會在onPostExecute中做一些回收工作,比如提示“下載完成”、“加載失敗”、隱藏進度條等等。

4 AsyncTask 示例

本節(jié)的功能和第 38 節(jié) Handler 的功能類似,我們還是完成一個后臺執(zhí)行耗時任務(wù),并同步更新進度條的功能,可以直接在 Handler 的例子上修改。

4.1 布局文件

布局文件基本一樣,只是默認將進度條和進度顯示隱藏起來,等到onPreExecute()方法的時候在做初始化展示,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ProgressBar
        android:visibility="gone"
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />

    <Button
        android:id="@+id/start_progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/progressBar"
        android:layout_alignParentStart="true"
        android:layout_marginStart="24dp"
        android:layout_marginTop="62dp"
        android:text="開始任務(wù)" />

    <TextView
        android:visibility="gone"
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/start_progress"
        android:layout_alignBottom="@+id/start_progress"
        android:layout_alignParentEnd="true"
        android:layout_marginEnd="85dp"
        android:gravity="center"
        android:text="當(dāng)前進度:0%"
        android:textSize="16sp" />

</RelativeLayout>

4.2 異步任務(wù)控制

異步任務(wù)的代碼基本上和 Handler 一致,我們通過Thread.sleep(1000)來模擬一秒鐘的耗時操作,然后在onPreExecute()中展示進度條,在后臺任務(wù)執(zhí)行完后通過publishProgress(int)來將任務(wù)進度發(fā)送到主線程,由onProgressUpdate(int)方法在 UI 線程接收進度,并更新進度條。最后在結(jié)束的時候返回“已完成”提示,在onPostExecute(String)方法中進行收尾工作,隱藏進度條并展示“已完成”。代碼如下:

package com.emercy.myapplication;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends Activity {

    private static final int MAX = 100;

    private ProgressBar progressBar;
    private Button startProgress;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progressBar = findViewById(R.id.progressBar);
        startProgress = findViewById(R.id.start_progress);
        textView = findViewById(R.id.textView);
        progressBar.setMax(MAX);

        startProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new DownloadTask().execute();
            }
        });
    }

    // 1、創(chuàng)建Async Task子類
    private class DownloadTask extends AsyncTask<Integer, Integer, String> {

        // 2、初始化階段,展示進度條
        @Override
        protected void onPreExecute() {
            progressBar.setVisibility(View.VISIBLE);
            textView.setVisibility(View.VISIBLE);
        }

        // 3、執(zhí)行后臺任務(wù)
        @Override
        protected String doInBackground(Integer... integers) {
            int i;
            for (i = 0; i < 100; i++) {
                try {
                    // 一秒鐘的耗時操作
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 4、發(fā)布進度
                publishProgress(i);
            }
            return "異步任務(wù)已完成";
        }

        // 5、接收后臺任務(wù)數(shù)據(jù)并更新進度條
        @Override
        protected void onProgressUpdate(Integer... values) {
            textView.setText("當(dāng)前進度:" + values[0] + "%");
            progressBar.setProgress(values[0]);
        }

        // 6、任務(wù)結(jié)束
        @Override
        protected void onPostExecute(String s) {
            progressBar.setVisibility(View.GONE);
            textView.setText(s);
        }
    }
}

編譯之后,效果如下:

圖片描述

可以看到大體的效果和 Handler 是一樣的,但是整個異步任務(wù)的處理流程更加清晰了,而且可以很方便的做任務(wù)前的初始化任務(wù)后的回收工作,整個線程的切換也不再需要我們?nèi)タ刂?,全部交給 AsyncTask 操作就行,一切就是這么簡單!

5 小結(jié)

本節(jié)介紹了一個專門用于執(zhí)行異步任務(wù)的工具類,首先需要創(chuàng)建一個子類繼承自 AsyncTask,然后確定好需要傳入和返回的參數(shù)類型,接著覆寫 4 個關(guān)鍵的方法,剩下的線程切換及數(shù)據(jù)傳輸就交給系統(tǒng)完成了。
相比 Handler,AsyncTask使用更簡單,我們只需要關(guān)注我們的后臺邏輯,而 Handler 需要我們自行管理的東西比較多。所以在執(zhí)行后臺任務(wù)刷新 UI 的場景,強烈推薦使用 AsyncTask,可以讓我們的開發(fā)更加順暢。