欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android带进度条的下载图片示例(AsyncTask异步任务)

程序员文章站 2023-01-21 10:08:13
为什么要用异步任务? 在android中只有在主线程才能对ui进行更新操作,而其它线程不能直接对ui进行操作 android本身是一个多线程的操作系统,我们不能把所有的...

为什么要用异步任务?

在android中只有在主线程才能对ui进行更新操作,而其它线程不能直接对ui进行操作

android本身是一个多线程的操作系统,我们不能把所有的操作都放在主线程中操作 ,比如一些耗时操作。如果放在主线程中 会造成阻塞 而当阻塞事件过长时 系统会抛出anr异常。所以我们要使用异步任务。android为我们提供了一个封装好的组件asynctask。

asynctask可以在子线程中更新ui,封装简化了异步操作。适用于简单的异步处理。如果多个后台任务时就要使用handler了 在这里就不再说明。

asynctask通常用于被继承。asynctask定义了三种泛型类型<params,progress,result>

  • params:启动任务时输入的参数类型
  • progress:后台任务执行的百分比
  • result:执行任务完成后返回结果的类型

继承asynctask后要重写的方法有:

doinbackgroud:必须重写,异步执行后台线程要完成的任务,耗时任务要写在这里,并且在这里不能操作ui。可以调用 publishprogress方法来更新实时的任务进度

onpreexecute:执行耗时操作前调用,可以完成一些初始化操作

onpostexecute:在doinbackground 执行完成后,主线程调用此方法,可以在此方法中操作ui

onprogressupdate:在doinbackgroud方法中调用publishprogress方法,更新任务的执行进度后 就会调用这个方法

下面通过一个实例来了解asynctask

首先附上运行结果

Android带进度条的下载图片示例(AsyncTask异步任务)

布局文件:

<linearlayout 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:orientation="vertical" > 

 <button 
  android:id="@+id/btn_download" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_gravity="center_horizontal" 
  android:text="点击下载" /> 

 <framelayout 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" > 

  <imageview 
   android:id="@+id/iv_image" 
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent" 
   android:scaletype="fitcenter" /> 

 </framelayout> 
</linearlayout> 

mainactivity

package com.example.asynctask; 
import java.io.bufferedinputstream; 
import java.io.bytearrayoutputstream; 
import java.io.ioexception; 
import java.io.inputstream; 
import java.net.malformedurlexception; 
import java.net.urlconnection; 
import android.os.asynctask; 
import android.os.bundle; 
import android.app.activity; 
import android.app.progressdialog; 
import android.graphics.bitmap; 
import android.graphics.bitmapfactory; 
import android.view.view; 
import android.view.view.onclicklistener; 
import android.widget.button; 
import android.widget.imageview; 
public class mainactivity extends activity implements onclicklistener{ 
 private imageview image; 
 private progressdialog progress; 
 private button btn_download; 
 private static string url="http://img4.imgtn.bdimg.com/it/u=1256159061,743487979&fm=21&gp=0.jpg"; 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
  super.oncreate(savedinstancestate); 
  setcontentview(r.layout.activity_main); 
  image=(imageview) findviewbyid(r.id.iv_image); 
  btn_download=(button) findviewbyid(r.id.btn_download); 
  progress=new progressdialog(this); 
  progress.seticon(r.drawable.ic_launcher); 
  progress.settitle("提示信息"); 
  progress.setmessage("正在下载,请稍候..."); 
  progress.setprogressstyle(progressdialog.style_horizontal); 
  btn_download.setonclicklistener(this); 
 } 
 @override 
 public void onclick(view v) { 
  // todo auto-generated method stub 
  new myasynctask().execute(url); 
 } 
 /* 
  * string*********对应我们的url类型 
  * integer********进度条的进度值 
  * bitmap*********异步任务完成后返回的类型 
  * */ 
 class myasynctask extends asynctask<string, integer, bitmap>{ 

  //执行异步任务(doinbackground)之前执行,并且在ui线程中执行 
  @override 
  protected void onpreexecute() { 
   // todo auto-generated method stub 
   super.onpreexecute(); 
   if(image!=null){ 
    image.setvisibility(view.gone); 
   } 
   //开始下载 对话框进度条显示 
   progress.show(); 
   progress.setprogress(0); 
  } 
  @override 
  protected bitmap doinbackground(string... params) { 
   // todo auto-generated method stub 
   //params是一个可变长的数组 在这里我们只传进来了一个url 
   string url=params[0]; 
   bitmap bitmap=null; 
   urlconnection connection; 
   inputstream is;//用于获取数据的输入流 
   bytearrayoutputstream bos;//可以捕获内存缓冲区的数据,转换成字节数组。 
   int len; 
   float count=0,total;//count为图片已经下载的大小 total为总大小 
   try { 
    //获取网络连接对象 
    connection=(urlconnection) new java.net.url(url).openconnection(); 
    //获取当前页面的总长度 
    total=(int)connection.getcontentlength(); 
    //获取输入流 
    is=connection.getinputstream(); 
    bos=new bytearrayoutputstream(); 
    byte []data=new byte[1024]; 
    while((len=is.read(data))!=-1){ 
     count+=len; 
     bos.write(data,0,len); 
     //调用publishprogress公布进度,最后onprogressupdate方法将被执行 
     publishprogress((int)(count/total*100)); 
     //为了显示出进度 人为休眠0.5秒 
     thread.sleep(500); 
    } 
    bitmap=bitmapfactory.decodebytearray(bos.tobytearray(), 0, bos.tobytearray().length); 
    is.close(); 
    bos.close(); 
   } catch (malformedurlexception e) { 
    // todo auto-generated catch block 
    e.printstacktrace(); 
   } catch (ioexception e) { 
    // todo auto-generated catch block 
    e.printstacktrace(); 
   } catch (interruptedexception e) { 
    // todo auto-generated catch block 
    e.printstacktrace(); 
   } 
   return bitmap; 
  } 
  //在ui线程中执行 可以操作ui 
  @override 
  protected void onpostexecute(bitmap bitmap) { 
   // todo auto-generated method stub 
   super.onpostexecute(bitmap); 
   //下载完成 对话框进度条隐藏 
   progress.cancel(); 
   image.setimagebitmap(bitmap); 
   image.setvisibility(view.visible); 
  } 
  /* 
   * 在doinbackground方法中已经调用publishprogress方法 更新任务的执行进度后 
   * 调用这个方法 实现进度条的更新 
   * */ 
  @override 
  protected void onprogressupdate(integer... values) { 
   // todo auto-generated method stub 
   super.onprogressupdate(values); 
   progress.setprogress(values[0]); 
  } 
 } 
} 

最后不要忘记在androidmanifest文件中配置网络访问权限

<uses-permission android:name="android.permission.internet"/> 

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!