实现Android网络框架:(一)整体设计

    xiaoxiao2021-12-13  27

      动手做一个是我最喜欢的学习模式之一,最近自己在做一个Android使用的简单的网络框架,参考了Volley和csdn大牛的一些文章,虽然做出来的东西都差不多,但自己实现一遍真的对Http协议、网络执行、设计模式等等有了很深刻的认识,也能够发掘模块化、框架化的优势所在,和大家分享一下。

    1、为什么Android应用需要网络框架?

      在Android开发的过程中,网络是必不可少的,我们的应用使用了大量网络数据,这其中使用的网络协议就是Http,相信大家也不会陌生,可是网络如何执行是一个大问题,原因有很多,Android不能再主线程执行网络请求,Android本身又没有提供任何完善的网络执行框架,那么为什么需要网络框架呢?我们来看看不用框架如何实现网络执行:

    addButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) {  ...//代码省略 new Thread(new Runnable() { @Override public void run() { try { List<String> fileList = new ArrayList<String>(); fileList.add("/storage/emulated/0/face.jpg"); Log.d("test", fileList.toString()); //执行网络请求 userService.sendAndRecogniseFace(fileList); mHandler.sendEmptyMessage(1); } catch (ServiceRulesException e) { e.printStackTrace(); Message msg = new Message(); Bundle data = new Bundle(); data.putString("Error_Message", e.getMessage()); msg.setData(data); mHandler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); Message msg = new Message(); Bundle data = new Bundle(); data.putString("Error_Message", "程序出错-未知错误"); msg.setData(data); mHandler.sendMessage(msg); } } }).start(); } } });

      当你没有网络框架的时候,你的网络请求(无论你使用HttpClient还是HttpURLConnection),你都必须使用新的线程来执行(不能在主线程中执行),而新开线程意味着什么?如果你需要执行100次,你就需要新开100个线程…这对本来资源就有限的手机来说,是何等的痛苦啊;另外一个巨大的问题,还是与UI线程有关,一般执行完网络请求都需要更新UI,可你的网络请求已经在新开的线程中执行了,如何返回主线程?当然是Handler了,你还需要在Handler中写所有的返回更新操作,又增加了工作量…所以,一个完善有效的网络框架不仅可以节省资源,提高程序质量,还可以减少工作量,何乐而不为呢?当然我写的肯定不能算完善,毕竟本人水平有限,不过你可以通过写这个简单的网络框架学习到更多的知识,当你再去看那些著名网络框架的时候往往就觉得很容易理解了。

    2、网络框架基本结构

      我们的HttpFramework主要分为四个部分,首先是Request,就是我们的发起的一次网络请求的实体;之后是一个经典的生产者消费者模式需要的RequestQueue,用于存放Request;还需要HttpExecutor,它的作用就是从队列中取出Request来进行执行;最后需要一个ResponseDispatcher,把结果分发到UI线程去执行,也就解决了我们之前使用Handler的问题。   主题架构图如下图所示:      整个网络框架的结构其实不是分层的,而是由四个相互独立的模块构建而成:

    1、Request

      Request就是网络框架的基础对象,表示了一个Http网络请求,比如一个上传请求,一个登陆请求等等,而它的具体实现则是与返回类型有关,因为我们知道Http返回的请求报文在Java中可以被抽象为Entity,但是Entity所包含的数据有可能是Json,有可能是String等等,这些是不固定的,为了做到“抽象”的目的,我们把返回类型抽象出来,在返回时统一为字节数据,再由使用的开发者自行去转换,就实现了抽象的目的,所以具体实现为xxxRequest,xxx就表示了不同的返回类型。这个具体我们后面也会说到。

    2、RequestQueue

      RequestQueue就是存放Request的消息队列,这也是生产者消费者模型必不可少的一部分,Request被存放在队列中,待Executor取出去真正执行,当然它的实现需要保证原子性,这样才能被多个Executor并发访问。

    3、HttpExecutor

      Http请求的执行者,它负责执行Http请求。需要注意的是HttpExecutor继承自Thread,这是因为我的网络框架采用了线程模型来进行,而不是用线程池,线程模型就是使用固定数量的线程来进行处理,循环从RequestQueue来取Request进行处理,如果没有可取的Request,Executor将处于阻塞状态。为什么不使用线程池呢,因为线程池更重量,并且启动速度更慢,使用线程模型正好符合了网络框架的需求,并且投递是与Executor耦合的,使用线程池的话更麻烦。

    4、ResponseDispatcher

      ReponseDispatcher的作用就是进行Reponse的分发,把它分发到主线程中去执行Request完成之后的操作,直接减少了我们的工作量,不需要使用Handler去进行线程切换,而它的实现也很简单,还是使用Handler有关的Looper,如果对这个不了解的可以去看我之前的博客。

    3、网络执行的选择

      Http请求最终还是需要去执行的,在这个框架中我只使用了HttpURLConnection,而熟悉Android的一定知道,Android现在的HttpURLConnection使用的是大名鼎鼎的okHttp来实现,所以实际上最终还是基于okHttp,关于okHttp我觉得还是值得去研究的,毕竟更底层一些,涉及到网络具体执行的处理,这也是以后的计划,分析okHttp的源码。

    如果觉得我的文章里有任何错误,欢迎评论指正!如果觉得写得好也欢迎大家留言或者点赞,一起进步、一起学习!

    转载请注明原文地址: https://ju.6miu.com/read-949983.html

    最新回复(0)