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

版权声明:本文为博主原创文章,转载请附上原文链接! https://blog.csdn.net/qq_22770457/article/details/51252858

在上文: 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 ̄)づ求赞求关注!

 

 

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页