手写volley网络请求框架

    网络请求框架其实google已经提供了不少的开源框架,但为什么还需要手写呢?看到这篇文章的博友不知道有没有在一二线的企业工作过,像BAT这些企业,他们开发出的项目,很少会有用到谷歌或者android提供的原生api,这也是高级Android开发工程师所必备的技术,就是自己手写出开源框架的项目。接下来我就给大家演示一下volley的框架的手写实现,这个不同于volley本身的框架,在手写的过程中,我会将不是本项目需要的代码给剔除掉,并创新出自己的设计思想。

    开发一个网络访问框架需要考虑的问题:

    1.扩展性:不能只处理json或者xml或者image等等的某一种;

    2.易用性:解决一个小问题时候,只需要修改一两行代码;

    3.稳定性:自己写的框架比开源的框架要更稳定,要明白只要是人开发出来的东西,我也能自己写出来;

    4.和其他框架能否集成。

    自己要写的网络框架的需求:

    1.不关心数据解析,获取数据为对象;

    2.网络访问是在子线程,实现线程切换,操作可以发生在主线程;

    3.高并发;

    4.缓存策略。

设计的框架图形为:


第一步:写一个网络消息处理中心的管理类:ThreadPoolManager,这个类有三个作用:1、将应用层去过来的任务添加到请求队列中;2、把队列中的任务放入线程池中;3、让线程池工作起来;该类的截图如下:

public class ThreadPoolManager {

    //1、把任务添加到请求队列中
    private LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
    //添加任务,把调用层取过来到任务放入请求队列中
    public void execute(Runnable runnable) {
        if (runnable != null) {
            try {
                queue.put(runnable);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //2、把队列中到任务放入到线程池
    private ThreadPoolExecutor threadPoolExecutor;

    private ThreadPoolManager() {
        threadPoolExecutor = new ThreadPoolExecutor(4, 20, 15, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(4), rejectedExecutionHandler);
        threadPoolExecutor.execute(runnable);
    }

    //线程池拒绝策略,防止15s内没处理完,线程池会丢弃线程
    private RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            //参数r就是超时线程
            try {
                queue.put(r);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    //3、让线程池工作起来
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while (true) {
                Runnable runnable1 = null;
                //从队列中取出请求
                try {
                    runnable1 = queue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (runnable1 != null) {
                    threadPoolExecutor.execute(runnable1);
                }
            }
        }
    };

    private static ThreadPoolManager ourInstance = new ThreadPoolManager();

    public static ThreadPoolManager getOurInstance() {
        return ourInstance;
    }
}

第二步:


策略设计模式:设计请求和响应的顶层接口。

请求的接口:IHttpService

/**
 * 封装请求
 *
 * Created by chengkai on 2018/4/6.
 */

public interface IHttpService {

    //1.设置URL
    void setUrl(String url);

    //2.设置请求参数
    void setRequestData(byte[] requestData);

    //3.执行请求
    void execute();

    //需要设置两个接口之间的关系
    void setHttpCallBack(IHttpListener httpListener);
}

响应的接口:IHttpListener

/**
 * 封装响应
 *
 * Created by chengkai on 2018/4/6.
 */

public interface IHttpListener {

    //接收上一个接口的结果
    void onSuccess(InputStream inputStream);
    void onFailure();
}

应用层发起一起网络请求的实体类:HttpTask

/**
 * 一次http的任务类
 *
 * Created by wangsujuan on 2018/4/6.
 */

public class HttpTask<T> implements Runnable{

    private IHttpListener httpListener;
    private IHttpService httpService;

    /**
     * HttpTask:应用层发起一次网络请求的实体类
     * @param requestInfo 应用层发起请求的参数
     * @param url 应用层发起请求的url
     * @param httpService
     * @param httpListener
     * @param <T>
     */
    public<T> HttpTask(T requestInfo, String url, IHttpService httpService, IHttpListener httpListener) {
        this.httpService = httpService;
        this.httpListener = httpListener;

        httpService.setUrl(url);
        httpService.setHttpCallBack(httpListener);

        if (requestInfo != null) {
            String requestContent = JSON.toJSONString(requestInfo);
            try {
                httpService.setRequestData(requestContent.getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void run() {
        httpService.execute();
    }
}

IHttpService接口的实现类:JsonHttpService代码如下

public class JsonHttpService implements IHttpService{

    private String url;
    private byte[] requestData;

    private IHttpListener httpListener;

    @Override
    public void setUrl(String url) {
        this.url = url;
    }

    @Override
    public void setRequestData(byte[] requestData) {
        this.requestData = requestData;
    }

    /**
     * 真实的网络操作在这里实现
     */
    @Override
    public void execute() {
        httpUrlconnPost();
    }

    public void httpUrlconnPost(){

        URL url = null;
        try {
            url = new URL(this.url);
            urlConnection = (HttpURLConnection) url.openConnection();//打开http连接
            urlConnection.setConnectTimeout(6000);//连接的超时时间
            urlConnection.setUseCaches(false);//不使用缓存
            urlConnection.setInstanceFollowRedirects(true);//是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
            urlConnection.setReadTimeout(3000);//响应的超时时间
            urlConnection.setDoInput(true);//设置这个连接是否可以写入数据
            urlConnection.setDoOutput(true);//设置这个连接是否可以输出数据
            urlConnection.setRequestMethod("POST");//设置请求的方式
            urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");//设置消息的类型
            urlConnection.connect();// 连接,从上述至此的配置必须要在connect之前完成,实际上它只是建立了一个与服务器的TCP连接
            //-------------使用字节流发送数据--------------
            OutputStream out = urlConnection.getOutputStream();
            BufferedOutputStream bos = new BufferedOutputStream(out);//缓冲字节流包装字节流
            if (requestData != null) {
                bos.write(requestData);
            }
            //把这个字节数组的数据写入缓冲区中
            bos.flush();//刷新缓冲区,发送数据
            out.close();
            bos.close();
            //------------字符流写入数据------------
            if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK) {//得到服务端的返回码是否连接成功
                InputStream in = urlConnection.getInputStream();
                httpListener.onSuccess(in);
            }
        } catch (Exception e) {
            e.printStackTrace();
            httpListener.onFailure();
        }finally{
            urlConnection.disconnect();//使用完关闭TCP连接,释放资源
        }
    }

    HttpURLConnection urlConnection = null;

    @Override
    public void setHttpCallBack(IHttpListener httpListener) {
        this.httpListener = httpListener;
    }
}

IHttpListener接口的实现类JsonHttpListener代码如下:

public class JsonHttpListener<M> implements IHttpListener {

    private Class<M> responseClass;
    private IDataListener<M> dataListener;
    //用于线程到切换
    private Handler handler = new Handler(Looper.getMainLooper());

    public JsonHttpListener(IDataListener<M> dataListener, Class<M> responseClass) {
        this.dataListener = dataListener;
        this.responseClass = responseClass;
    }

    @Override
    public void onSuccess(InputStream inputStream) {
        //获取响应结果,把byte数据转换成String数据
        String content = getContent(inputStream);
        //处理json字符串,转换为对象
        final M response = JSON.parseObject(content, responseClass);
        //把结果传送到调用层
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (dataListener != null) {
                    dataListener.onSuccess(response);
                }
            }
        });

    }

    @Override
    public void onFailure() {
        //把结果传送到调用层
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (dataListener != null) {
                    dataListener.onFailure();
                }
            }
        });

    }

    private String getContent(InputStream inputStream) {
        String content = null;
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
            } catch (IOException e) {
                System.out.println("Error=" + e.toString());
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    System.out.println("Error=" + e.toString());
                }
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }
}

回调给应用层的接口:IDataListener代码如下:

/**
 * 回调给应用层到接口
 *
 * Created by chengkai on 2018/4/6.
 */

public interface IDataListener<M> {

    void onSuccess(M m);
    void onFailure();
}

第三步:框架层提供给应用层调用的接口:

public class Volley {

    public static<T,M> void sendJsonRequest(T requestInfo, String url, Class<M> response, IDataListener<M> dataListener)
    {
        IHttpService httpService = new JsonHttpService();
        IHttpListener httpListener = new JsonHttpListener<>(dataListener,response);
        HttpTask<T> httpTask = new HttpTask<T>(requestInfo,url,httpService,httpListener);
        ThreadPoolManager.getOurInstance().execute(httpTask);
    }
}

在button按钮点击的效果:

ublic void click(View view) {
    Volley.sendJsonRequest(null, url, ResponceData.class, new IDataListener<ResponceData>() {
        @Override
        public void onSuccess(ResponceData responceData) {
            Log.i("chengkai","城市:" + responceData.result.today.city);
        }

        @Override
        public void onFailure() {
            Log.i("chengkai", "访问失败");
        }
    });
}

最终调试的效果为:


到此说明测试成功!项目代码github下载地址为:https://github.com/cWX411904/VolleyDesignByMySelf

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值