概述

android 提供了一个异步任务类AsyncTask,使创建异步任务、更新UI变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。本例子将演示并实现,使用AsyncTask来下载视频。

详细

一、准备工作

开发环境:

jdk1.8

Eclipse Luna Service Release 1 (4.4.1)

运行环境:

华为荣耀6(Android4.4)、华为p9(Android7.0)

实现功能:

使用AsyncTask实现异步下载视频

二、简介

在Android中,我们需要将一些耗时的操作放到子线程中,如果放在UI线程会造成主线程阻塞,出现ANR。在子线程中处理耗时操作,需要进行更新UI,一般的做法是通过Handler发送消息到UI线程进行处理,相对来说使用Handler的代码比较臃肿。对于Handler的知识可以看这两篇文章: Android Handler的基本使用、深入理解Handler、Looper、Messagequeue。 
android 提供了一个异步任务类AsyncTask,使创建异步任务、更新UI变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。

三、AsyncTask说明

AsyncTask 允许在UI线程上执行后台操作和发布结果,而不必操作Thread和Handler。

AsyncTask 允许在UI线程上执行后台操作和发布结果,而不必操作Thread和Handler。 
它是围绕Thread和Handler设计的一个辅助类,主要应用于短操作(最多几秒)。如果想要运行长时间的任务,强烈建议使用Executor、ThreadPoolExecutor和FuterTask。

AsyncTask:一个在后台线程上运行,而结果在UI线程上发布的任务。异步任务必须被继承使用,子类至少覆盖一个方法(doInBackground)。异步任务用到了3个泛型类型:

  • Params:执行任务时发送给任务的参数类型。

  • Progress:后台任务执行期间,发布的进度、百分比。

  • Result:后台计算的结果类型。

异步任务中,并不是所有的泛型类型都要被使用,如果某个类型不需要使用,只需要使用Void类型就可以。如:

private  class MyTask extends AsyncTask<Void, Void, Void>{....}。

1 任务执行步骤

执行一个异步任务需要经历4个步骤:

  • onPreExecute():在UI线程上调用execute方法后,执行onPreExecute(运行在UI线程上)。此步骤通常用于设置任务,例如在用户界面显示进度条。

  • doInBackground(Params…):执行完onPreExecute后,立即在后台线程运行,此步骤可能需要长时间的后台计算。execute()参数也被传到这步。计算结果必须由这步骤返回,并返回到最后一步。这一步骤也可以使用publishprogress发布任务的进度,进度会被发送到onProgressUpdata。

  • onProgressUpdate(Progress…):调用publishprogress后,执行该步骤(运行在UI线程),执行时间是不确定的。这个方法用于在后台计算仍在执行时在用户界面显示进度。例如:用一个进度条显示下载视频的百分比。

  • onPostExecute(Result):后台计算(doInBackground)完成时,在UI线程运行该方法。后台计算结果作为一个参数传递到这步。

2 取消任务

一个任务可以随时取消,通过调用cancel(boolean),调用此方法将导致随后使用iscancelled()返回ture。调用此方法后,在doInBackground执行完后不再调用onPostExecute(Result),而是调用oncancelled(Result)。

3 线程规则

要想使AsyncTask类能正常工作,必须遵循一些线程规则:

  • AsyncTask类必须在UI线程中加载。

  • 任务实例必须在UI线程中创建。

  • execute(Params…)必须在UI线程中调用。

  • 不要手动调用onPreExecute()、doInBackground(Params…)、onProgressUpdate(Progress…)、onPostExecute(Result)。

  • 一个任务实例只能执行一次,(多次执行会抛出异常)。

4 执行顺序

在1.6之前,AsyncTask是串行执行任务的; 
1.6的时候AsyncTask开始采用线程池里处理并行任务; 
但是从3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务。

四、程序实现

1、项目代码结构

顺便附上V7的代码包截图:

2、实现思路

如下是通过使用AsyncTask下载一个段视频的列子,下载成功或失败后设置按钮内容,并在下载过程中更新下载进度。 
先看下效果图。

关键实现类MainActivity:

package cn.vn.asynctaskdemo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar; public class MainActivity extends Activity implements OnClickListener {
private final static String TAG = "MainActivity";
public static final String VIDEO_DOWNLOAD_FOLDER = Environment
.getExternalStorageDirectory().toString();
private Button mExecuteBtn;
private ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mExecuteBtn = (Button) findViewById(R.id.btn_execute);
mExecuteBtn.setOnClickListener(this);
mProgressBar = (ProgressBar) findViewById(R.id.progress);
} @Override
public void onClick(View view) {
mProgressBar.setProgress(0);
//下载视频
new DownloadTask().execute("http://120.25.226.186:32812/resources/videos/minion_05.mp4");
} public class DownloadTask extends AsyncTask<String, Double, Boolean>{ @Override
protected void onPreExecute() {
Log.i(TAG,"onPreExecute ");
}
@Override
protected Boolean doInBackground(String... params) {
Log.i(TAG,"doInBackground params[0]="+params[0]);
HttpURLConnection conn = null;
try{
URL url = new URL(params[0]);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Connection", "Keep-Alive");
}catch(Exception e){
e.printStackTrace();
return false;
} //获取文件长度
long videoTotalLength = conn.getContentLength();
File file = new File(VIDEO_DOWNLOAD_FOLDER, "test.mp4");
try { //创建File对象,文件路径为/sdcard/test.mp4
InputStream in = conn.getInputStream();
if (in == null)
return false;
//如果文件已经存在,并且第二个参数为true,则向原先的文件追加数据,否则重新写。
FileOutputStream os = new FileOutputStream(file, false);
byte[] buffer = new byte[4096];
int len = 0;
int current = 0;
while ((len = in.read(buffer)) != -1) {
current += len;
//更新进度
publishProgress((double) current,
(double) videoTotalLength);
os.write(buffer, 0, len);
}
os.close();
in.close();
} catch (Exception e) {
if (file.exists())
file.delete();
e.printStackTrace();
return false;
}
return true;
} @Override
protected void onProgressUpdate(Double... values) {
//设置ProgressBar进度
mProgressBar.setProgress((int) (values[0]/values[1]*100));
} @Override
protected void onPostExecute(Boolean result) {
if(result){
Log.i(TAG,"下载文件成功");
mExecuteBtn.setText("下载成功");
}else{
Log.i(TAG,"下载文件失败");
mExecuteBtn.setText("下载失败");
}
}
}
}

该demo比较简单,只有一个Activity——>MainActivity。该界面有一个Button和一个ProgressBar。点击Button开始执行异步任务,下载网上视频,并保存到本地文件中。打印信息如下:

06-23 11:14:50.890 I/MainActivity(28417): onPreExecute
06-23 11:14:50.890 I/MainActivity(28417): doInBackground params[0]=http://120.25.226.186:32812/resources/videos/minion_01.mp4
06-23 11:15:33.562 I/MainActivity(28417): 下载文件成功

第37行:创建DownloadTask实例,调用其execute方法,开始执行任务。 
开始执行任务,先走onPreExecute方法,然后进入doInBackground,这里面用来进行耗时操作,这里未在主线程运行,调用publishProgress来更新下载进度,会调用onProgressUpdate。 
任务下载完成(失败或成功),走onPostExecute方法。之后在分析下AsyncTask的源码。

五、运行效果

1、运行,右键项目:Run as -》Android Application

2、运行时的截图

六、其他补充

下载后的压缩包里面有

其中代码包为

另外一个则为依赖包,关于android-support-v7包的说明,这里有些参考资料:http://blog.csdn.net/hh2000/article/details/39718623

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

AsyncTask 异步任务基本使用-下载视频的更多相关文章

  1. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  2. android AsyncTask异步下载并更新进度条

    AsyncTask异步下载并更新进度条    //如果不是很明白请看上篇文章的异步下载 AsyncTask<String, Integer, String> 第一个参数:String 传入 ...

  3. Android线程管理之AsyncTask异步任务

    前言: 前面几篇文章主要学习了线程以及线程池的创建与使用,今天来学习一下AsyncTask异步任务,学习下AsyncTask到底解决了什么问题?然而它有什么弊端?正所谓知己知彼百战百胜嘛! 线程管理相 ...

  4. 使用AsyncTask异步更新UI界面及原理分析

    概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线 ...

  5. Android 多线程----AsyncTask异步任务详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  6. Android中使用Thread线程与AsyncTask异步任务的区别

    最近和几个朋友交流Android开发中的网络下载问题时,谈到了用Thread开启下载线程时会产生的Bug,其实直接用子线程开启下载任务的确是很Low的做法,那么原因究竟如何,而比较高大上的做法是怎样? ...

  7. Android异步处理系列文章四篇之二 使用AsyncTask异步更新UI界面

    Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ...

  8. Android异步处理二:使用AsyncTask异步更新UI界面

    在<Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面>中,我们使用Thread+Handler的方式实现了异步更新UI界面,这一篇中,我们介绍一种更为简 ...

  9. Python+Requests+异步线程池爬取视频到本地

    1.本次项目为获取梨视频中的视频,再使用异步线程池下载视频到本地 2.获取视频时,其地址中的Url是会动态变化,不播放时src值为图片的地址,播放时src值为mp4格式 3.查看视频链接是否存在aja ...

随机推荐

  1. leetcode第一刷_Gray Code

    说到格雷码,应该没人不知道,详细它有什么用,我还真不是非常清楚,我室友应该是专家.生成的规律不是非常明显,之前看到帖子讲的,这会儿找找不到了.. 思想是这种,假设有n位,在第2^(n-1)个编码以下画 ...

  2. Java7语法新特性

    Java7语法新特性: 1. switch中增加对String类型的支持. public String generate(String name, String gender) { String ti ...

  3. springmvc最简单的搭建,初学者必看

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=" ...

  4. Sublimetext3将空格转换为Tab

    最近在学习Python,从网上粘贴的代码很多缩进都是空格,这样就会导致代码执行的时候报错,因为Python是依靠缩进来判断代码层次的.我的编辑器是Sublime Text 3看了一下,原来转换成Tab ...

  5. 0, \0, NULL

    字符串.字符数组输入.输出与'\0'的问题 原创首发,欢迎转载! 作者按 字符串.字符数组以"%s"格式输入时,以遇到'空格'为这个字符串输入结束. 字符串.字符数组以" ...

  6. 机器学习简史brief history of machine learning

    BRIEF HISTORY OF MACHINE LEARNING My subjective ML timeline (click for larger) Since the initial sta ...

  7. 服务信息块协议 SMB(Server Message Block protocol)

    SMB(Server Message Block)是协议名,它能被用于Web连接和客户端与服务器之间的信息沟通. SMB协议 SMB最初是IBM的贝瑞·费根鲍姆(Barry Feigenbaum)研制 ...

  8. 学习笔记:AC自动机

    话说AC自动机有什么用......我想要自动AC机 AC自动机简介:  首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配 ...

  9. 【BZOJ】【1014】【JLOI2008】火星人prefix

    Splay/二分/Hash 看了网上的题目关键字(都不用点进去看……我也是醉了)了解到做法= =那就上呗,前面做了好几道Splay的题就是为了练手搞这个的. Hash判断字符串是否相同应该很好理解吧? ...

  10. 解析KML文件并提取coordinates中的经纬度坐标信息

    从googleEarh导出的kml文件 <?xml version="1.0" encoding="UTF-8"?><kml xmlns=&q ...