AsyncTask解析(下)——实现自定义AsyncTask网络传输工具类封装

来源:互联网 发布:海奇软件 编辑:程序博客网 时间:2024/05/20 07:53

在上文: AsyncTask解析(上)——原理分析与超简单demo实现中已经对AsyncTask的实现原理以及源码流程进行了一定的分析,相信大家已经基本熟悉了AsyncTask内部实现网络传输的调用顺序以及过程细节,最后还写出了一个比较简单的Demo实践,十分简单易懂相信大家都能很快掌握。

然而那个Demo还是太粗制滥造了,功能太缺乏,很多需要传入的参数也没有写到构参里直接给写死了..

并且在真正的项目实践中,光使用这个简单的Demo是远远不够的,我们需要对它进行更好的封装,扩展它的功能,才能更好地为我们的项目服务。

所以,本文的核心重点是如何去封装出一个AsyncTask工具类,以及如何让AsyncTask变得简单易用。

整体框架的继承关系如下图所示:


理清一下思路,整体框架应用观察者模式,可以细分为以下几个步骤:

1、实现一个抽象类UrlAsyNet继承AsyncTask<String,Integer,T>(这里第三个参数设置为T是为了适配不同的传输类型)

这里为什么不用接口呢?因为接口的方法是不能有具体的实现的,但是在该方法中需要进行初始化的工作,所以这里使用了抽象类来实现。

/** *   Created by nangua on 2016/4/26. *   Params 启动任务执行的输入参数,这里是URL所以用String *   Progress 后台任务执行的百分比。 *   Result 后台执行任务最终返回的结果,比如String。 */public class UrlAsyNet<T> extends AsyncTask<String,Integer,T> {    /**     * 全部参数构造方法     * @param apikey     * @param httpArg     * @param httpUrl     * @param method     * @param onNetStateChangedListener     * @param type     */    public UrlAsyNet(String apikey, String httpArg, String httpUrl, NetMethod method, OnNetStateChangedListener<T> onNetStateChangedListener, ParamType type) {        this.apikey = apikey;        this.httpArg = httpArg;        this.httpUrl = httpUrl;        this.method = method;        this.onNetStateChangedListener = onNetStateChangedListener;        this.type = type;    }     /**     * 传入URL     * @param httpUrl     */    public UrlAsyNet(String httpUrl,String apikey,String httpArg) {        this.httpUrl = httpUrl;        this.apikey = apikey;        this.httpArg = httpArg;    }     //添加枚举类型    public enum NetMethod{        GET,POST    }     /**     * 参数类型。分为:JSONorXML文件。键值对,无参     */    public enum ParamType{        JSON_OR_XML_FILE        ,KEY_VALUE_PAIR,        NO_PARAM    }     /**     * 网络状态改变时候的监听器     * @param <T>     */    public interface OnNetStateChangedListener<T> {        /**         * 访问网络之前         */        public void beforeAccessNet();         /**         * 访问网络成功获取数据之后         *         * @param result         */        public void afterAccessNet(T result);         /**         * 出现了错误的时候         */        public void whenException();         /**         * 执行进度         * @param progress         */        public void onProgress(Integer progress);    }     //设置监听器回调     public OnNetStateChangedListener<T> getOnNetStateChangedListener() {        return onNetStateChangedListener;    }     //设置网络监听器    public void setOnNetStateChangedListener(OnNetStateChangedListener<T> onNetStateChangedListener) {        this.onNetStateChangedListener = onNetStateChangedListener;    }     //网络监听器实例    OnNetStateChangedListener<T> onNetStateChangedListener;     //在四个回调方法中调用网络监听器的方法以实现回调    @Override    protected void onCancelled() {        if (onNetStateChangedListener!=null){            onNetStateChangedListener.whenException();        }    }     @Override    protected void onPostExecute(T t) {        if (onNetStateChangedListener!=null){            onNetStateChangedListener.afterAccessNet(t);        }    }     @Override    protected void onPreExecute() {        if (onNetStateChangedListener!=null){            onNetStateChangedListener.beforeAccessNet();        }    }      @Override    protected void onProgressUpdate(Integer... values) {        if (onNetStateChangedListener!=null){            if (values.length>1) {                onNetStateChangedListener.onProgress(values[0]);            }        }    }     //使用HttpURLConnection需要用到的httpUrl    String httpUrl ;    //使用HttpURLConnection需要用到的httpArg    String httpArg ;    //连接百度API需要的APIKEY    String apikey;    //得到的参数类型    ParamType type;    //网络请求参数(GET或POST)    NetMethod method;    //数据    String jsonOrXmlFile;    //键值对    HashMap<String, Object> keyValuePair;      public String getHttpUrl() {        return httpUrl;    }     public void setHttpUrl(String httpUrl) {        this.httpUrl = httpUrl;    }     public String getApikey() {        return apikey;    }     public void setApikey(String apikey) {        this.apikey = apikey;    }     public String getHttpArg() {        return httpArg;    }     public void setHttpArg(String httpArg) {        this.httpArg = httpArg;    }     public ParamType getType() {        return type;    }     public void setType(ParamType type) {        this.type = type;    }      @Override    protected T doInBackground(String... params) {        return null;    }     /**     * 执行     */    public void execute(){        this.execute(new String[]{});    }}

2、在抽象类里编写一个网络监听器接口。然后在需要使用到的地方(比如在MainActivity里需要使用,就在MainActivity里写一个实现这个接口的内部类,从而在这个内部类里实现随着网络状态的改变改变对UI的操作)

那么问题来了:这里为什么不把组件当做参数传进去呢?比如在上文中的Demo是把TextViewProgressBar传进去的,那么如果你要传入的是一个CustView呢?这样就得重新修改写好的代码,拆轮子,违背了程序的可扩展性。所以更好的办法是提供一个可实现的网络监听接口,在接口里进行更新UI操作。

/**     * 网络状态改变时候的监听器     * @param <T>     */    public interface OnNetStateChangedListener<T> {        /**         * 访问网络之前         */        public void beforeAccessNet();        /**         * 访问网络成功获取数据之后         *         * @param result         */        public void afterAccessNet(T result);        /**         * 出现了错误的时候         */        public void whenException();        /**         * 执行进度         * @param progress         */        public void onProgress(Integer progress);    }
网络监听器的代码上文已经出现了,这里单独列出来一下。

3、编写具体的工具类UrlNormalAsyNet,实现对数据的接受(暂时没有写JSON和XML的解析):

/** * Created by nangua on 2016/4/26. */public class UrlNormalAsyNet extends UrlAsyNet<String>{    /**     * 请求方法POST和get     */    AsyNet.NetMethod method;    public UrlNormalAsyNet(String apikey, String httpArg, String httpUrl, NetMethod method, OnNetStateChangedListener<String> onNetStateChangedListener, ParamType type) {        super(apikey, httpArg, httpUrl, method, onNetStateChangedListener, type);    }    public UrlNormalAsyNet(String httpUrl, String apikey, String httpArg) {        super(httpUrl, apikey, httpArg);        this.httpUrl = httpUrl;        this.apikey = apikey;        this.httpArg = httpArg;    }    @Override    protected String doInBackground(String... params) {        BufferedReader reader = null;        String result = null;        StringBuffer sbf = new StringBuffer();        httpUrl = httpUrl + "?" + httpArg;        try {            URL url = new URL(httpUrl);            HttpURLConnection connection = (HttpURLConnection) url                    .openConnection();            connection.setRequestMethod("GET");            connection.setRequestProperty("apikey",  apikey);            connection.connect();            InputStream is = connection.getInputStream();            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));            String strRead = null;            while ((strRead = reader.readLine()) != null) {                sbf.append(strRead);                sbf.append("\r\n");            }            reader.close();            result = sbf.toString();            if (result != null) {                publishProgress(100);            }        } catch (Exception e) {            e.printStackTrace();        }        return result;    }}

运行截图:


本文暂时更新到这里,以后有时间再继续更新

目标要实现的工具类有三个:UrlFileAsyNet(处理文件网络传输信息),UrlImageAsyNet(处理图片传输信息),UrlNormalAsyNet(处理JSONXML,或String格式网络传输信息)

以下是大神同学Dikaros写的完整AsyncTask工具包下载地址:https://github.com/Dikaros/AsyNet 

QAQ(づ ̄ 3 ̄)づ求赞求关注!

 

 

2 0
原创粉丝点击