异步任务之AsyncTask实现<一>

转发请注明出处:http://blog.csdn.net/qq_28055429/article/details/51934966

前言:因为handler+message来实现异步操作相对复杂,故而如果只需简单异步操作的话,可用异步任务AsyncTask来实现

一,基本知识:

(1)原型:

android.os.AsyncTask<Params,Progress,Result> :

三个参数

Params --------启动任务执行的输入参数,比如HTTP请求的URL。

Progress -----后台任务执行的百分比,。

Result --------后台执行任务最终返回的结果,比如Drawable。



(2)基本步骤:

4个步骤:

onPreExecute():  执行后台操作前回调的函数,常用来设置任务,例如:在用户界面中显示一个进度条。

doInBackground(Void... params) :后台执行耗时的操作,常用于接受参数返回结果,结果返回到onPostExecute()中

不能直接操作UI,在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。

onProgressUpdate(Progress...) : 在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。

onPostExecute (String result):执行后台操作完毕后自动回调此函数,后台操作结束后的结果会返回到这里,来使用

(3)基本方法:

boolean   cancel(boolean mayInterruptIfRunning)  :尝试取消,如任务下载时,突然想停止,可设置XX.cancel(true);

execute(Params... params)       :根据参数来开始执行

get():如果有必要,就等待计算完成,然后取它的结果

get(long timeout, TimeUnit unit)  :如果有必要,等待规定时间的计算,然后取它的结果

boolean isCancelled()    :判断操作是否已经取消了

AsyncTask.Status  getStatus()  :获取当前任务的状态,

(4)4个原则:

1.异步任务的实例必须在UI线程中创建。

2.execute(Params... params)方法必须在UI线程中调用。

3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。

4.一个任务实例只能执行一次,如果执行第二次将会抛出异常。

(5)用法:一般都是一个类去继承AsyncTask,重写里面的方法,一般重写的方法有:doInBackground和onPostExecute

这是官方的例子:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }
在MainActivity中执行代码:

 new DownloadFilesTask().execute(url1, url2, url3);

二,例子:

例子(1):加载网络图片:

布局:activity_third:放置一个imageView用于显示图片

<?xml version="1.0" encoding="utf-8"?>
<!--定义基本布局:LinearLayout-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <!--定义一个imageView来显示图片-->
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:src="@drawable/load"/>

</LinearLayout>

异步类:ImageAsyncTask:继承自AsyncTask<Void , Void, Drawable>,实现其中的方法:

package testsdcard.com.maiyu.s04_79.domain;

import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.ImageView;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import testsdcard.com.maiyu.s04_79.R;

/**自定义ImageAsynTask类,继承自异步任务类
 * Created by maiyu on 2016/7/17.
 */
public class ImageAsynTask extends AsyncTask<Void ,Void ,Drawable> {
    private ImageView m ;       //用来显示图片
    private String imageUrl ;   //记录网络图片地址

    //根据imageView对象和网络图片网址的,构造函数
    public ImageAsynTask(ImageView i , String t){
        m  = i ;
        imageUrl = t ;
    }
    //后台执行耗时的操作
    @Override
    protected Drawable doInBackground(Void... voids) {
        return loadImages(imageUrl);    //自定义加载图片的方法
    }

    //执行后台操作完毕后自动回调此方法
    @Override
    protected void onPostExecute(Drawable drawable) {
        super.onPostExecute(drawable);
        if(drawable != null){       //判断图片加载是否成功
            m.setImageDrawable(drawable);
        }else {
            m.setImageResource(R.drawable.failed);
        }
    }
    //执行后台操作前的回调函数
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    //根据网址加载图片
    private Drawable loadImages(String url) {
        try{
            //生成URL对象
            URL mUrl = new URL(url);
            //得到inputStream
            InputStream inputStream = (InputStream)mUrl.openStream();
            return Drawable.createFromStream(inputStream , "test"); //生成并返回图片

        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }
}

测试类:ThridActivity:在里面主要新建异步任务来测试加载图片:

new ImageAsynTask(mImage , "http://p4.so.qhimg.com/t01aade72dccf26cffe.jpg").execute();

代码如下:

package testsdcard.com.maiyu.s04_79.activity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;

import testsdcard.com.maiyu.s04_79.R;
import testsdcard.com.maiyu.s04_79.domain.ImageAsynTask;

/**
 * Created by maiyu on 2016/7/17.
 */
public class ThirdActivity extends Activity {
    private ImageView mImage ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
        mImage = (ImageView)findViewById(R.id.imageView);
        //新建一个异步任务,开始加载网络图片
        new ImageAsynTask(mImage , "http://p4.so.qhimg.com/t01aade72dccf26cffe.jpg").execute();
    }
}

记得加网络权限:

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

结果:略,,,

例子2:根据网址下载网络Html内容,可中断下载,即测试类cancel(boolean)方法:

布局:activity_four:放置一个editText,两个按钮,即下载和停止,一个ScrollView(里面放置一个TextView)用于显示内容:

<?xml version="1.0" encoding="utf-8"?>
<!--定义当前的基本布局;LinearLayout-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <!--定义获得用户需要加载的网址的输入框-->
    <EditText
        android:id="@+id/Et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/four_edt1"/>
    <!--定义用户单击开始加载按钮控件-->
    <Button
        android:id="@+id/BtnStart"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/four_btn1"/>
    <!--定义用户单击终止加载按钮控件-->
    <Button
        android:id="@+id/BtnStop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/four_btn2"/>
    <!--用于显示内容-->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/Tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </ScrollView>

</LinearLayout>

异步类:HtmlAsyncTask继承自AsyncTask<Void , Void, String>,再去实现里面方法,

代码如下:

package testsdcard.com.maiyu.s04_79.domain;

import java.io.IOException;

import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;

//自定义ImageAsynTask类,继承自异步任务类
public class HtmlAsyncTask extends AsyncTask<Void, Void, String> {
    //用来存储加载网址内容成功后展示网络源代码的TextView对象
    private TextView m;
    //记录需要加载的网络地址
    private String url;

    //构造函数,传入TextView对象和网络地址
    public HtmlAsyncTask(TextView i, String t) {
        m = i;
        url = t;
    }

    //后台执行耗时的操作
    @Override
    protected String doInBackground(Void... params) {
        return requestByHttpGet(url);
    }

    //执行后台操作完毕后自动回调此函数
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.e("isCancelled()", isCancelled() + "");
        //如果用户取消此异步任务
        if (isCancelled()) {
            m.setText("取消加载");
        }
        //如果加载的得到的网络地址的源代码不为空的话,设置textview对象的值
        else if (null != result) {
            m.setText(result);
        }
        //如果加载的内容为空的话,显示加载失败
        else {
            m.setText("加载失败");
        }
    }

    //执行后台操作前回调的函数
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    //通过加载url的网络内容
    public String requestByHttpGet(String url) {
        //新建HttpGet对象
        HttpGet httpGet = new HttpGet(url);
        //定义HttpClient对象
        HttpClient httpClient = new DefaultHttpClient();
        //定义HttpResponse实例
        HttpResponse httpResp;
        try {
            httpResp = httpClient.execute(httpGet);
            // 判断是够请求成功
            if (httpResp.getStatusLine().getStatusCode() == 200) {
                // 获取返回的数据
                String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");
                Log.e("TAG", "HttpGet方式请求成功,返回数据如下:");
                return result;
            } else {
                Log.e("TAG", "HttpGet方式请求失败");
            }
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

测试类:同理:代码如下:

package testsdcard.com.maiyu.s04_79.activity;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import testsdcard.com.maiyu.s04_79.R;
import testsdcard.com.maiyu.s04_79.domain.HtmlAsyncTask;

//定义了本实例的主要Activity
public class FourActivity extends Activity {
    //定义布局中的TextView控件
    private TextView tv;
    //定义布局中的EditText控件
    private EditText et;
    //定义布局中的开始加载Button控件
    private Button btnstart;
    //定义布局中的终止加载Button控件
    private Button btnstop;
    //定义异步请求html代码的异步任务
    protected HtmlAsyncTask hat;

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

    private void setListener() {
        //设置btn的点击监听器
        btnstart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //初始textview的内容
                tv.setText("Html加载中.........");
                //获取EditText的用户输入值
                String str = et.getText().toString();
                //启动异步任务加载用户输入的url中的网络html
                hat = new HtmlAsyncTask(tv, str);
                hat.execute();
            }
        });
        btnstop.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //终止异步任务
                hat.cancel(true);
            }
        });
    }

    private void findView() {
        //得到布局中的TextView的对象
        tv = (TextView) findViewById(R.id.Tv);
        //得到布局中的EditText的对象
        et = (EditText) findViewById(R.id.Et);
        //得到布局中的开始加载的Button的对象
        btnstart = (Button) findViewById(R.id.BtnStart);
        //得到布局中的开始加载的Button的对象
        btnstop = (Button) findViewById(R.id.BtnStop);
    }
}

同样要加网络权限:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
结果:略,,

三,总结:

AsyncTask使用的一般步骤:

(1)创建一个类,继承AsyncTask<参数1,参数2,参数3>,参数一般为<Void,Void,你想要返回的类型>,

如:ImageAsyncTask extends AsyncTask<Void ,Void ,Drawable>  {}//获取图片

StringAsyncTask extends AsyncTask<Void ,Void ,String>{}//获取字符串数据

(2)然后去重写其中的方法,一般重写的有doInBackground和onPostExecute

如:略,,,

(3)在测试类中去调用,并执行execute()方法。

上一个例子中:

new HtmlAsyncTask(tv, str).execute();

时间: 2024-11-03 21:35:41

异步任务之AsyncTask实现<一>的相关文章

[转]Android:异步处理之AsyncTask的应用(二)

2014-11-07     既然UI老人家都这么忙了,我们这些开发者肯定不能不识趣的去添乱阻塞UI线程什么的,否则UI界面万一停止响应了呢——这不是招骂的节奏么?!所以我们知道用Handler+Thread的方法,在子线程中处理耗时的任务,任务完成后通过Handler通知UI主线程更新UI界面,皆大欢喜有木有. 可是这样,还是有某些人觉得用Handler+Thread的代码会比较繁琐,当然这个某些人里面包括我们伟大的谷歌.所以AsyncTask(异步任务)在Android 1.5中横空出世:相

Android:异步处理之AsyncTask的应用(二)

前言 在上一篇文章中<Android:异步处理之Handler+Thread的应用(一)>,我们知道Android的UI主线程主要负责处理用户的按键事件.用户的触屏事件以及屏幕绘图事件等:既然UI老人家都这么忙了,我们这些开发者肯定不能不识趣的去添乱阻塞UI线程什么的,否则UI界面万一停止响应了呢——这不是招骂的节奏么?!所以我们知道用Handler+Thread的方法,在子线程中处理耗时的任务,任务完成后通过Handler通知UI主线程更新UI界面,皆大欢喜有木有. 可是这样,还是有某些人觉

异步任务(AsyncTask)

为了解决新线程不能更新UI组件的问题,Android提供了如下几种解决方案: 使用Handler实现线程之间的通信 Activity.runOnUiThread(Runable). View.post(Runable). View.postDelayed(Runable,long). 前面我们已经知道了如何使用Handler,后三种方式可能导致编程略显繁琐,而异步任务则可简化这种操作. AsyncTask<Params, Progress, Result>是抽象类,定义了下面三种泛型类型: P

Android异步处理框架AsyncTask源码解析

一.概述 在Android开发中,我们进行异步处理一般会采用两种方式: 1.Thread +Handler 通常我们在Thread里面发送消息,然后在Handler的handleMessage方法里面去处理对应的任务,因为Android是不允许UI线程去更新UI的,这个时候我们可以采取这种方式 2.AsyncTask AsyncTask是Android为我们封装的一个轻量级的异步处理框架,其实底层也是用了类似Thread+Handler的方式.对外提供了一些方法,我们实现这些方法就可以很方便的进

Android异步任务处理框架AsyncTask源码分析

[转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] 引言 在平时项目开发中难免会遇到异步耗时的任务(比如最常见的网络请求).遇到这种问题,我们可以自己通过Handler+Message+Thread/ThreadPool来构造一个异步耗时任务框架.当你下次项目中又遇到一个网络请求,你又不得不重写异步耗时任务处理框架.出于避免开发者重复搬砖工作,Google工程师给开发者搭建了一个通用的异步耗时任务处理框架--AsyncTask. Asyn

断其一指------异步任务(AsyncTask)

这个东西我学了好几遍,总觉得格式很别扭-- AsyncTask 异步处理 解决的问题:在子线程中,有的时候也需要多次动态更新UI,此时,除了使用Handler之外,用AsyncTask也是一种相对比较简洁的方式: AsyncTask<Params,Progress,Result> 是一个抽象类,用来被继承的. 1.三个参数 Params 启动任务执行输入参数的类型 Progress 后台任务完成进度的类型 Result 执行任务完成后返回的结果 2.如何使用AsyncTask (1)创建一个类

Android开发之异步消息处理机制AsyncTask

转自:Android AsyncTask完全解析,带你从源码的角度彻底理解 另外一篇比较详细的博文:http://blog.csdn.net/liuhe688/article/details/6532519 AsyncTask的基本用法 首先来看一下AsyncTask的基本用法,由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它.在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下: 1. Params 在执行AsyncTask时需要传

第十六章:异步处理之AsyncTask的应用

前言 我们知道Android的UI主线程主要负责处理用户的按键事件.用户的触屏事件以及屏幕绘图事件等:既然UI老人家都这么忙了,我们这些开发者肯定不能不识趣的去添乱阻塞UI线程什么的,否则UI界面万一停止响应了呢——这不是招骂的节奏么?!所以我们知道用Handler+Thread的方法,在子线程中处理耗时的任务,任务完成后通过Handler通知UI主线程更新UI界面,皆大欢喜有木有. 可是这样,还是有某些人觉得用Handler+Thread的代码会比较繁琐,当然这个某些人里面包括我们伟大的谷歌.

异步加载AsyncTask

private void huodeshuju() {        new AsyncTask<String, Void, String>() { @Override            protected String doInBackground(String... params) {                try {                    URL url=new URL(params[0]);                    HttpURLConnect