安卓中的AsyncTask(异步任务) (下)

之前写了异步任务的上篇,简单介绍了一下异步任务的几个方法,今天写的是如何使用异步任务从网络上下载一张图片,并实时显示下载的进度。


1) 首先是XML文件,布局简单,一个按钮,一个用于显示图片的ImageView



    


2) 在.java文件中,使用到AsyncTask,在doInBackground 方法中,使用HttpURLConnection来实现下载图片的逻辑,这部分内容属于网络连接的内容,会在以后的文章来说明,所有代码几乎都写了注释。由于我们下载的是一张图片,三个泛型参数中第一个是下载的URL地址;由于要实时显示下载进度,第二个参数为Integer;下载完成返回的是一张图片,类型为Bitmap。

以下为.java的所有代码:

package com.zhixing.asynctaskprogress;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.zhixing.asynctaskprogress002.R;

public class MainActivity extends Activity {

	private Button btn_start;
	private ImageView image;
	private MyAsyncTask asyncTask;
	private ProgressDialog progressDialog; // ProgressDialog: 进度条对话框

	private String url = "http://www.benbenla.cn/images/20110731/benbenla-09c.jpg";

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

		image = (ImageView) findViewById(R.id.image);
		btn_start = (Button) findViewById(R.id.btn_start);
		progressDialog = new ProgressDialog(this);
		progressDialog.setTitle("提示");
		progressDialog.setMessage("正在下载,请稍后...");
		// 设置进度条对话框的样式,ProgressDialog.STYLE_HORIZONTAL: 设置进度条为水平
		progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

		btn_start.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				asyncTask = new MyAsyncTask();
				asyncTask.execute(url); // 通过execute()方法调用AsyncTask,参数传入网络图片的地址
			}
		});

	}

	class MyAsyncTask extends AsyncTask {

		@Override // 该方法是在后台任务执行之前被UI线程调用,做的是界面的初始化操作,比如显示一个进度条
		protected void onPreExecute() { 
			super.onPreExecute();
			
			progressDialog.show();
		}

		@Override // 所有的耗时任务都在该方法执行
		protected Bitmap doInBackground(String... params) { 
			Bitmap bitmap = null;
			URL url;
			HttpURLConnection connection = null;
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			try {
				// new一个URL对象,并传入需要的网络地址;
				url = new URL(params[0]); // params是一个可变长数组,可以接受传入的多个参数,params[0]代表的是我们要下载的图片的地址
				connection = (HttpURLConnection) url.openConnection(); // 获取网络连接的对象connection
				connection.setConnectTimeout(5 * 1000); // 设置连接超时的时间,单位毫秒
				connection.setReadTimeout(5 * 1000); // 设置读取超时的时间,单位毫秒
				connection.setRequestMethod("GET"); // 设置请求的方式,参数可以是GET,或者POST,但必须要大写

				InputStream in = connection.getInputStream(); // 通过 HttpURLConnection 对象的 getInputStream() 方法 获取到输入流
				// BufferedInputStream: 缓冲输入流, 通过BufferedInputStream对我们获取到的输入流进行包装,提高读取的效率
				BufferedInputStream bis = new BufferedInputStream(in);
				
				int length = connection.getContentLength(); // 下载文件的总长度
				int len = 0; // 读取的字节总数
				int count = 0; // 当前进度值
				byte[] buffer = new byte[128]; // []里面的数字代表每次读取的字节数,数值越小,下载速度越慢
				while((len = bis.read(buffer)) != -1){ // 不等于-1代表没有读完,bis.read(buffer): 将流读到 BufferedInputStream 中
					count += len;
					int num = (int) ((count/(float)length)*100); // num: 要显示的当前进度条数值
					publishProgress(num); // 调用publishProgress方法来更新进度条数值
					
					outputStream.write(buffer,0,len); // 将流写到ByteArrayOutputStream(字节数组流)中
				}
				
				byte[] result = outputStream.toByteArray(); // 获取内存缓冲区的数据,转换成字节数组
				bitmap = BitmapFactory.decodeByteArray(result, 0, result.length); // 将字节数组解析成Bitmap
					  
				in.close(); // 使用完,要记得关闭流
				bis.close();
				
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}  finally {
				if (connection != null) {
					connection.disconnect(); // 断开连接
				}
			}
			
			return bitmap; // 返回 Bitmap
		}

		@Override // 该方法在publishProgress方法被调用之后,被UI线程调用,用来在界面上显示任务的进展情况,比如通过一个进度条来显示进度
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			progressDialog.setProgress(values[0]);
		}

		@Override // 在doInBackground方法执行完之后,该方法江北UI线程调用,后台任务的结果将通过该方法传到UI线程,比如提示用户下载完成等等
		protected void onPostExecute(Bitmap result) {
			super.onPostExecute(result);
			
			progressDialog.dismiss(); // 让进度条对话框消失
			image.setImageBitmap(result); // 设置从网络下载的图片
			Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
		}

	}

}
下载过程中的截图:

安卓中的AsyncTask(异步任务) (下)_第1张图片

完成后的的截图:

安卓中的AsyncTask(异步任务) (下)_第2张图片

以上就是关于AsyncTask下载图片的所有内容,异步任务的功能非常强大,大家有兴趣可以去查找相关书籍来学习。



你可能感兴趣的:(Android)