异步任务之AsyncTask实现<一>

来源:互联网 发布:怎么在淘宝上买种子 编辑:程序博客网 时间:2024/05/17 03:27

转发请注明出处: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;//定义了本实例的主要Activitypublic 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();




1 0