详解Android 中AsyncTask 的使用

详解Android 中AsyncTask 的使用

1、首先我们来看看AsyncTask 的介绍:  

Handler 和 AsyncTask 都是android 中用来实现异步任务处理的方式;其中:

Handler 实例向 UI 线程发送消息,完成界面更新,

优点:对整个过程控制的比较精细;
        缺点:代码相对臃肿,多个任务同时执行时,不易对线程进行精确的控制;

AsyncTask :比Handler 更轻量级一些,适用于简单的异步处理;

优点:简单 | 快捷 | 过程可控;
        缺点:使用多个异步操作时就变得复杂起来;

2、AsyncTask 的定义:(AsyncTask 定义了三种泛型类型) 

  public abstract class AsyncTask<Params,Progress,Result>{...} 

说明:

Params :启动任务执行的输入参数,例如:HTTP 请求的URL;
        Progress: 后台任务执行的百分比;
        Result:后台执行任务最终返回的结果,比如String;

3、AsyncTask 异步任务的执行步骤:(以下方法除execute(Params... params),在AsyncTask中重写),下列是相关方法的介绍:

A、execute(Params... params) :

执行一个异步任务,需要我们在UI线程中调用,触发任务

B、OnPreExecute():

execute(Params... params)调用后立即执行,一般用于在执行后台任务前对UI做一些标记; 例如,可以在此处显示进度对话框;

C、doInBackground(Params.. params):

onPreExecute() 完成后执行,后台执行,处理比较耗时的操作;此处不能操作UI,执行的过程中调用publishProgress(Progress... values)来更新进度信息;

D、onProgressUpdate(Progress... values):

在调用publicshProgress(Progress... values)方法执行,直接将进度信息更新到UI组建上;此方法在主线程上执行,用于显示任务执行的进度;

E、onPostExecute(Result result):

此方法在主线程中执行,当后台的操作结束时,此方法会被调用,计算结果作为参数传递到此方法中,直接将结果显示到UI组建上。

F、cancel(); :

取消一个正在执行的任务,在UI线程中完成,用AsyncTask的对象进行调用,参数为true/false;

4、使用AsyncTask 时注意事项: 

A、异步任务实例必须在UI线程中创建;
    B、execute(Params... params) 方法必须在UI线程中调用;
    C、不要手动的调onPreExecute().doInBackground().onProgressUpdate().onPostExecute()这几个方法;
    D、不能在doInBackground(Params... params) 中更改组件信息;
    E、一个任务实例只能执行一次,如果执行第二次会抛出异常;

5、案例:使用AsyncTask 实现图片的下载:

Activity类,主程序的入口:

  public class MainActivity extends Activity { 

  // 程序入口
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    MyAsyncTask my = new MyAsyncTask();
    my.execute("http://photocdn.sohu.com/20110927/Img320705637.jpg");
  } 

}

   AsyncTask 派生类,实现异步任务:

  package com.sun.asynctask; 

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; 

import org.apache.http.HttpConnection;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; 

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log; 

/**
 * 异步任务,实现网页内容的获取
 *
 *
 * 生成该类的对象,并调用execute方法之后
 *
 * 首先执行的是onProExecute() 方法,
 *
 * 其次执行的doInBackground()方法
 */
public class MyAsyncTask extends AsyncTask<String, Integer, Bitmap> { 

  /**
   * 在execute() 方法执行后立即执行,运行在UI线程中,
   * 在后台任务开始前执行,用于标识UI界面
   */
  protected void onPreExecute() {
    super.onPreExecute();
    Log.i("msg","onPreExecute()...");
  } 

  /**
   * 后台执行耗时的任务;
   *
   * 方法中的 String 参数对应 AsyncTask的第一个参数;
   * 返回的 Bitmap 对应的是AsyncTask 的第三个参数;
   *
   * 该方法并不运行在UI线程中,主要用于异步操作,可以调用publishProgress()方法触发
   * onProgressUpdate对UI进行操作;
   *
   */
  protected Bitmap doInBackground(String... params) {
    Log.i("msg","doInBackground(String... params)..."); 

    try { 

      /* 网络访问方式 二 */
      /*
      URL url = new URL(params[0]);
      HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
      connection.connect(); // 开始连接
      int zong = connection.getContentLength();
      InputStream is2 = connection.getInputStream();
      */ 

      /* 开始网络访问数据 */
      HttpGet hg = new HttpGet(params[0]); // 此处注意参数的用法
      HttpClient hc = new DefaultHttpClient();
      HttpResponse hr = hc.execute(hg); // 发送请求,得到响应 

      // 判断请求是否成功
      if(hr.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
        Log.i("msg", "access success...");
        HttpEntity he = hr.getEntity();
        InputStream is = he.getContent(); // 获取输入流对象,好比搭桥
        long total = he.getContentLength(); // 文件的总字节数 

        ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 输出流,临时容器,用于装从is中流出的数据 

        byte[] buffer = new byte[1024]; // 缓存容器,每次装载1024 个字节数据
        int len = 0; // 每次读的字节数
        int curLen = 0 ; // 已读多少数据 

        while((len=is.read(buffer))!=-1){ // 当len !=-1 时,也就是还有数据可读
          Log.i("msg","begin read data..."+len+",total:"+total);
          baos.write(buffer, 0, len); // 向临时容器中装数据
          curLen=curLen+len; // 更新已读的数据 

          /* 在UI显示当前读取的进度 , 调用次方法触发onProgressUpdate() 方法执行 */
          publishProgress((int)(((float)curLen/total)*100));
        } 

        Bitmap bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, (int)total);
        is.close();
        return bitmap;
      }
    } catch (Exception e) {
      e.printStackTrace();
    } 

    return null;
  } 

  /**
   * 括号中的参数:String 对应的是AsyncTask 的第三个参数,也就是
   * 接收了 从doInBackground() 返回的结果;
   * 此方法在 doInBackground() 方法执行结束后执行,运行在UI线程中,
   * 可以对UI进行更新
   */
  protected void onPostExecute(Bitmap result) {
    super.onPostExecute(result);
    Log.i("msg","onPostExecute(String result)..."+result.getHeight());
  } 

  /**
   * 方法括号中的Integer 对应AsyncTask 中的第二个参数;
   * 在doInBackground() 中每次调用publishProgress() 时被执行;
   * 该方法是在UI线程中的,所以可以用于对UI进行更新
   */
  protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values); 

    Log.i("msg","onProgressUpdate(Integer... values)..."+values[0]);
  } 

  /**
   * 图片的下载
   */
  public HttpURLConnection downPic(String urltemp){ 

    try {
      URL url = new URL(urltemp); // 确定连接地址
      // 打开一个连接
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.connect(); // 开始连接
      return connection;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  } 

}

以上就是Android AsyncTask的应用实例,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Android开发之全屏与非全屏的切换设置方法小结

    本文实例讲述了Android开发之全屏与非全屏的切换设置方法.分享给大家供大家参考,具体如下: 静态方法 1. 代码方式 在Activity类OnCreate方法中设置,代码如下 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().se

  • Android使用GridView实现日历的方法

    在开发中可能会遇到某些情况下需要用到日历的功能,并且还要在日历上加标签什么的,最重要的就是android自带的日历由于各个系统版本不同导致日历的样式也不同,这样就会导致使用起来比较麻烦..而且在日历中加标签也不好实现...所以很多时候日历都是自己去实现的...由于自定义日历会比较麻烦...这里就教大家使用GridView来实现,主要是我们比较熟悉这个控件...到时候也可以根据自己的情况进行封装为自定义View 下面就先看看效果图.由于是从项目中抽取出来的,某些地方定制性比较强, 可以根据需求自行

  • Android 中WallpaperManager用法实例

    Android 中WallpaperManager用法实例 注意:壁纸的设置得加入权限: <uses-permission android:name="android.permission.SET_WALLPAPER"/> 1.WallpaperManager  对象的获得: wallpaperManager =WallpaperManager.getInstance(this); 2.设置壁纸的方法: 方法一:wallpaperManager.setBitmap(); /

  • Android Spinner 组件的应用实例

    Android Spinner 组件 Spinner: 下拉组件 使用事项:布局在XML 中实现,具体的数据在JAVA 代码中实现: 所用知识点: 数组适配器:ArrayAdapter  用于关系M 层和 C 层: 事件:OnItemSelectedListener; 案列:查看十二星座效果图: xml:代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tool

  • Android开发实现各种图形绘制功能示例

    本文实例讲述了Android开发实现各种图形绘制功能.分享给大家供大家参考,具体如下: 这里结合本人的开发事例,简单介绍一下如何在Android平台下实现各种图形的绘制. 首先自定义一个View类,这个view类里面需要一个Paint对象来控制图形的属性,需要一个Path对象来记录图形绘制的路径,需要一个Canvas类来执行绘图操作,还需要一个Bitmap类来盛放绘画的结果. Paint mPaint = new Paint(); mPaint.setAntiAlias(true); mPain

  • 浅谈Android 的线程和线程池的使用

    Android 的线程和线程池 从用途上分,线程分为主线程和子线程:主线程主要处理和界面相关的事情,子线程则往往用于耗时操作. 主线程和子线程 主线程是指进程所拥有的线程.Android 中主线程交 UI 线程,主要作用是运行四大组件以及处理它们和用户的交互:子线程的作业则是执行耗时任务. Android 中的线程形态 1.AsyncTask AsyncTask 是一种轻量级的异步任务类,可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新 UI, AsyncTas

  • Android编程实现播放视频时切换全屏并隐藏状态栏的方法

    本文实例讲述了Android编程实现播放视频时切换全屏并隐藏状态栏的方法.分享给大家供大家参考,具体如下: 1. Demo示例: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (this.getResources().getConfiguration().ori

  • 详解Android 中AsyncTask 的使用

    详解Android 中AsyncTask 的使用 1.首先我们来看看AsyncTask 的介绍:   Handler 和 AsyncTask 都是android 中用来实现异步任务处理的方式:其中: Handler 实例向 UI 线程发送消息,完成界面更新, 优点:对整个过程控制的比较精细:         缺点:代码相对臃肿,多个任务同时执行时,不易对线程进行精确的控制: AsyncTask :比Handler 更轻量级一些,适用于简单的异步处理: 优点:简单 | 快捷 | 过程可控:    

  • 详解Android中AsyncTask的使用方法

    在Android中实现异步任务机制有两种方式,Handler和AsyncTask. Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制. 为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务

  • 详解Android中AsyncTask机制

    在Android当中,提供了两种方式来解决线程直接的通信问题,一种是通过Handler的机制,还有一种就是今天要详细讲解的 AsyncTask 机制. AsyncTask       AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程. 怎么来理解AsyncTask呢?通俗一点来说,AsyncTask就相当于Android给我们提供了一个多线

  • 详解Android中图片的三级缓存及实例

    详解Android中图片的三级缓存及实例 为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响 特别是,当我们想要重复浏览一些图片时,如果每一次浏览都需要通过网络获取,流量的浪费可想而知 所以提出三级缓存策略,通过网络.本地.内存三级缓存图片,来减少不必要的网络交互,避免浪费流量

  • 详解Android中Intent对象与Intent Filter过滤匹配过程

    如果对Intent不是特别了解,可以参见博文<详解Android中Intent的使用方法>,该文对本文要使用的action.category以及data都进行了详细介绍.如果想了解在开发中常见Intent的使用,可以参见<Android中Intent习惯用法>. 本文内容有点长,希望大家可以耐心读完. 本文在描述组件在manifest中注册的Intent Filter过滤器时,统一用intent-filter表示. 一.概述 我们知道,Intent是分两种的:显式Intent和隐式

  • 详解 Android中Libgdx使用ShapeRenderer自定义Actor解决无法接收到Touch事件的问题

    详解 Android中Libgdx使用ShapeRenderer自定义Actor解决无法接收到Touch事件的问题 今天在项目中实现了一个效果,主要是画一个圆.为了后续使用方便,将这个圆封装在一个自定义Actor(CircleActot)中,后续想显示一个圆的时候,只要创建一个CircleActor中即可. 部分代码如下所示: package com.ef.smallstar.unitmap.widget; import android.content.res.Resources; import

  • 详解Android中的Service

    Service简介: Service是被设计用来在后台执行一些需要长时间运行的操作. Android由于允许Service在后台运行,甚至在结束Activity后,因此相对来说,Service相比Activity拥有更高的优先级. 创建Service: 要创建一个最基本的Service,需要完成以下工作:1)创建一个Java类,并让其继承Service 2)重写onCreate()和onBind()方法 其中,onCreate()方法是当该Service被创建时执行的方法,onBind()是该S

  • 详解Android中Handler的内部实现原理

    本文主要是对Handler和消息循环的实现原理进行源码分析,如果不熟悉Handler可以参见博文<详解Android中Handler的使用方法>,里面对Android为何以引入Handler机制以及如何使用Handler做了讲解. 概括来说,Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制.我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功

  • 详解Android中获取软键盘状态和软键盘高度

    详解Android中获取软键盘状态和软键盘高度 应用场景 在Android应用中有时会需要获取软键盘的状态(即软键盘是显示还是隐藏)和软键盘的高度.这里列举了一些可能的应用场景. 场景一 当软键盘显示时,按下返回键应当是收起软键盘,而不是回退到上一个界面,但部分机型在返回键处理上有bug,按下返回键后,虽然软键盘会自动收起,但不会消费返回事件,导致Activity还会收到这次返回事件,执行回退操作,这时就需要判断,如果软键盘刚刚由显示变为隐藏状态,就不执行回退操作. 场景二 当软键盘弹出后,会将

  • 详解Android中fragment和viewpager的那点事儿

    在之前的博文<Android 中使用 ViewPager实现屏幕页面切换和页面轮播效果>和<详解Android中Fragment的两种创建方式>以及<Android中fragment与activity之间的交互(两种实现方式)>中我们介绍了ViewPager以及Fragment各自的使用场景以及不同的实现方式. 那如果将他们两结合起来,会不会擦出点火花呢,答案是肯定的.之前在介绍ViewPager时,我们实现了多个ImageView的切换,并配合更新导航原点的状态.那我

随机推荐