您的位置:首页 > 移动开发 > Android开发

【攻克Android(26)】Async Task 异步任务

2015-07-27 19:26 543 查看
[size=large]本文围绕以下两个部分展开: [/size]

[size=large]一、Async Task 异步任务[/size]
[size=large]案例一:通过Async Task进行线程间通信(非 UI进程更新 UI、处理耗时任务)[/size]


[size=large]一、Async Task 异步任务[/size]

[size=medium]1. Async Task 异步任务[/size]

[size=medium]AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类。AsyncTask的内部实现是一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+Handler的方式调用回调函数。[/size]

[size=medium]2. 使用方法[/size]

/**
* 自定义异步任务类 - 继承自 AsyncTask 类
*/

/*
三个模板参数:
(传入参数类型, 进度类型, 返回值类型)
Params:传递给后台任务的参数类型。
Progress:后台计算执行过程中,进步单位(progress units)的类型。
(就是后台程序已经执行了百分之几了。)
Result:后台执行返回的结果的类型。

AsyncTask并不总是需要使用上面的全部3种类型。
标识不使用的类型,只需要使用Void类型即可。
*/
private class XxxTask extends AsyncTask<Params, Progress, Result> {

/**
* 1. 准备运行(可选)
* <p/>
* 该回调函数在任务被执行之后立即由UI线程调用。
*
* 这个步骤通常用来建立任务,在用户接口(UI)上显示进度条。
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
}

/**
* 2. 正在后台运行(必须重写)
*
* 该回调函数由后台线程在onPreExecute()方法执行结束后立即调用。
* <p/>
* 通常在这里执行耗时的后台计算。
* 计算的结果必须由该函数返回,并被传递到 onPostExecute()中。
* <p/>
* 在该函数内也可以使用 publishProgress(Progress...)来发布一个或多个进度单位。
* 这些值将会在 onProgressUpdate(Progress...)中被发布到 UI线程
*
* @param params
* @return
*/
@Override
protected String doInBackground(String... params) {

return params[0];
}

/**
* 3. 完成后台任务(可选)
*
* 当后台计算结束后调用。
*
* 后台计算的结果会被作为参数传递给这一函数。
*
* @param s 后台计算的结果
*/
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}

/**
* 4. 进度更新 (可选)
* <p/>
* 该函数由 UI线程在 publishProgress(Progress...)方法调用完后被调用。
*
* 一般用于动态地显示一个进度条。
*
* @param values
*/
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}

/**
* 5. 取消任务(可选)
* <p/>
* 在调用AsyncTask的cancel()方法时调用
*/
@Override
protected void onCancelled() {
super.onCancelled();
}
}



[size=large]案例一:通过Async Task进行线程间通信(非 UI进程更新 UI、处理耗时任务)[/size]

[size=medium]效果如下:[/size]

[size=medium]进入主界面后,显示一个按钮:[/size]

[align=center][/align]

[size=medium]当点击该按钮的时候,跳到另一个界面:异步任务界面。[/size]

[align=center][/align]

[size=medium]要实现左上角“异步任务”左侧的回退按钮,只需要在功能清单文件中添加如下一句话:[/size]

android:parentActivityName=".MainActivity"


[size=medium]添加到该Activity中:[/size]

<activity
android:name=".AsyncTaskActivity"
android:label="@string/title_activity_async_task"
android:parentActivityName=".MainActivity" />


[size=medium]当点击START按钮的时候,条形进度条和文本进度,都会以0.2秒增加1的速度增长,一直到100。[/size]

[align=center][/align]

[align=center][/align]

[size=medium]当进度达到100的时候,会弹出Toast提示:“结果:Google”。[/size]

[align=center][/align]


[size=medium](1)strings.xml[/size]

<resources>
<string name="app_name">Async Task</string>

<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>

<string name="btn_start">Start</string>
<string name="btn_async_task">Async Task 异步任务</string>
<string name="title_activity_async_task">异步任务</string>

</resources>


[size=medium](2)activity_main.xml。主活动布局。[/size]

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<Button
android:id="@+id/btnAsyncTask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="@string/btn_async_task" />

</RelativeLayout>


[size=medium](3)新建一个Activity: AsyncTaskActivity。并在功能清单中设置回退按钮。[/size]

[size=medium](4)MainActivity。主活动。按钮的点击事件。[/size]

public void onClick(View view) {
startActivity(new Intent(this, AsyncTaskActivity.class));
}


[size=medium](5)activity_async_task.xml。异步任务活动布局。包括一个START按钮,一个条形进度条和一个文本(文本进度)。[/size]

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.android.handlerthread.AsyncTaskActivity">

<Button
android:id="@+id/btnStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="@string/btn_start" />

<ProgressBar
android:id="@+id/progressBar"
style="?android:progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/btnStart"
android:visibility="gone" />

<TextView
android:id="@+id/tvScale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progressBar"
android:visibility="gone" />

</RelativeLayout>

<!-- 设置 ProgressBar 和 TextView 不可见,
当点击 START 按钮的时候,才可见。-->


[size=medium](6)AsyncTaskActivity。通过Async Task进行线程间通信(非 UI进程更新 UI、处理耗时任务)[/size]

package com.android.handlerthread;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;


public class AsyncTaskActivity extends Activity {
// 1.1 要用到主界面中的 ProgressBar 和 TextView,因此要先声明并初始化。
// 声明两个控件(RatingBar 和 TextView)
private ProgressBar progressBar;
private TextView tvScale;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task);

// 1.2 初始化两个控件(ProgressBar 和 TextView)
progressBar = (ProgressBar) findViewById(R.id.progressBar);
tvScale = (TextView) findViewById(R.id.tvScale);
}

public void onClick(View view) {
// 2. 设置控件可见,并启动任务
progressBar.setVisibility(View.VISIBLE);
tvScale.setVisibility(View.VISIBLE);
UpdateTask task = new UpdateTask();
// 这里输入的参数会传输给 doInBackground()方法
task.execute("Google");
}

/**
* 3. 自定义异步任务类
*/
private class UpdateTask extends AsyncTask<String, Integer, String> {

/**
* 3.1 准备运行(可选)
*/
@Override
protected void onPreExecute() {
// 设置最大进度值:100
progressBar.setMax(100);
}

/**
* 3.2 正在后台运行(必须重写)
*
* @param params
* @return
*/
@Override
protected String doInBackground(String... params) {
for (int i = 0; i < 100; i++) {
// 5.2.1 设置进度值
// 发布一个或多个进度单位(units of progress)。
// 这些值将会在 onProgressUpdate(Progress...)中被发布到 UI线程
this.publishProgress(i + 1);
try {
// 5.2.2 模拟具体完成的耗时任务 --- 比如:访问网络。
// 200毫秒,进度增 1
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (isCancelled()) {
return "Cancelled";
}
}
return params[0];
}

/**
* 3.4 完成后台任务(可选)
*
* @param result 后台计算的结果
*/
@Override
protected void onPostExecute(String result) {
// 完成后台任务后,给一个 Toast 提示
20000 Toast.makeText(getApplicationContext(), "结果:" + result,
Toast.LENGTH_SHORT).show();
}

/**
* 3.3 进度更新 (可选)
*
* @param values
*/
@Override
protected void onProgressUpdate(Integer... values) {
// 因为只传入一个值:"Google",因此对应的进度更新的时候,也是 values[0]
progressBar.setProgress(values[0]);
tvScale.setText(String.format("%d / %d", values[0], 100));
}

/**
* 取消任务(可选)
*/
@Override
protected void onCancelled() {
super.onCancelled();
}
}

// -----------------------------------------------------------
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_async_task, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: