点击按钮下载图片
MainActivity.java中的代码:
public class MainActivity extends ActionBarActivity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv=(ImageView) findViewById(R.id.iv);
// 点击按钮下载图片
public void click(View view) {
new MyAysncTask().execute(params);
}
// 使用异步任务下载图片,这里使用内部类形式
//Params 表示当前的AsyncTask操作时需要的参数类型 这里是URL为String类型
//Progress 表示当前AsyncTask耗时操作时进度类型 不显示进度就填Void 显示进度指定是整形
//Result 表示当前AsyncTask耗时操作结果的数据类型
class MyAysncTask extends AsyncTask<String, Integer,byte[]>{
//(1)先构建一个显示进度的对象ProgressDialog
private ProgressDialog pd;
//该方法表示在AsyncTask执行之前运行在UI线程中的准备方法 初始化工作
@Override
protected void onPreExecute() {
//(2)初始化ProgressDialog,设置标题/样式等等
pd=new ProgressDialog(MainActivity.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//表示在进度条对话框中显示进度条
//点击进度条对话框中的取消按钮取消异步任务
pd.setButton(ProgressDialog.BUTTON_NEGATIVE,"取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
cancel(true);//cancel(boolean b)如果设置为true表示取消当前的异步任务,当执行该方法后会立即执行onCancelled()方法
}
});
//(3)展示进度条
pd.show();
super.onPreExecute();
}
protected void onCancelled(){
//表示U线程中调用cancel()方法取消异步任务成功时回调的方法
//该方法正常 情况下是 doInBackground()方法执行后才执行的。如果先执行cancel()方法,就会立即执行该方法
//注意:如果onCancelled()被执行,这时将不再执行onPostExecute()方法
pd.dismiss();
}
//表示在onPreExecute()方法执行 后立即执行
//该方法运行在工作线程中,主要执行耗时工作
//该方法的参数类型与类中第一个参数一致
//返回值与类中的第三个参数一致
@Override
protected byte[] doInBackground(String... params) {
byte[] images=null;
ByteArrayOutputStream output=new ByteArrayOutputStream();
//第一步:得到URL对象,并把图片地址传进来
try {
URL url=new URL(params[0]);
//第二步:通过openConnection()方法获得HttpURLConnection对象
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//第三步:设置属性。如请求方式、连接的超时时间、设置是否可以向服务器去读写操作等
conn.setDoInput(true);//表示可以向服务器去读操作
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//第四步:与网络建立连接
conn.connect();
//第五步:获得响应代码(为了判断是否连接成功,当值为200时表示连接成)并进行判断
//当连接成功,首先获得流对象,为输入流对象(表示从网络读取资源)
//读取资源要准备的工作:首先建立一个缓冲区,将读取的资源放入缓冲区
//因为读和写是同时进行,所以在这里也要获得输出流对象进行写出操作,可以利用while语句进行循环判读,当缓冲区的资源不等于-1,我们就进行输出操作
int responseCode=conn.getResponseCode();
if(responseCode==200){
InputStream input=conn.getInputStream();
//(4)获得当前下载图片数据文件的总长度
long totallLength=conn.getContentLength();
int currentLength=0;//表示当前下载图片文件的长度
byte[] data=new byte[1024];
int temp=0;
//isCancelled()表示异步任务是否被取消 当文件没有读取完毕并且异步任务没有取消的情况下继续读取
while(((temp=input.read(data)))!=-1&&isCancelled()){
currentLength+=temp;//表示每次循环读取的内容添加到当前的长度变量currentLength中
//表示根据文件的总长度与当前下载的长度计算 获得图片下载进度
int progress=(int) ((currentLength/(float)totallLength)*100);
publishProgress(progress);//表示将进度发布到主线程中
output.write(data, 0, temp);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//第六步:现在图片是存在内存流当中,所以现在要内存流的数据转换成字节数组,然后进行返回就可以了。
images=output.toByteArray();
return images;
}
//该方法表示当doInBackground()方法执行完后把得到的结果传递到该方法,立即执行该方法,该方法的作用是负责将数据结果展示到UI界面
@Override
protected void onPostExecute(byte[] result) {
//第七步:将图片的字节数组转换成图片对象,并将图片展示到UI界面
if(result!=null&&result.length!=0){
Bitmap bm=BitmapFactory.decodeByteArray(result, 0, result.length);
iv.setImageBitmap(bm);
}else
{
Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
}
pd.dismiss();//当下载完成将进度框关闭
super.onPostExecute(result);
}
//该方法表示运行在主线程中用来更新进度的回调方法
//该方法的作用是:如果doInBackground()方法中调用了 publishProgress()方法向主线程发布进度 由该方法获得进度后更新UI界面进度
@Override
protected void onProgressUpdate(Integer... values) {
pd.setProgress(values[0]);//设置更新进度
}
}
}