精华内容
下载资源
问答
  • :fire:警告:fire:该库尚未收到任何格式的Snow Snow Trevor Perrin噪声协议的实现,该协议被设计为“难以上手”。 :fire:警告:fire:该图书馆尚未接受任何正式审核。 看起来像什么? 有关更完整TCP客户端/服务器示例...
  • 客户端、服务端传输数据,数据可以有一定的格式,双方必须先约定好。 BS编程,即Browser、server开发。Browser浏览器,一种特殊的客户端,支持HTTP(s)协议,能够通过URL向服务端发起请求,等待服务端返回HTML等数据...
    1. CS即客户端,服务器编程。
      客户端。服务器之间需要使用Socket 约定协议、版本(往往使用的协议是TCP或者UPD),指定地址和端口,就可以通信了。
      客户端、服务端传输数据,数据可以有一定的格式,双方必须先约定好。
    2. BS编程,即Browser、server开发。
      Browser浏览器,一种特殊的客户端,支持HTTP(s)协议,能够通过URL向服务端发起请求,等待服务端返回HTML等数据,并在浏览器内可视化展示的程序。
      Server,支持HTTP(s)协议,能够接受众多客户端发起的HTTP协议请求,经过处理,将HTML等数据返回给浏览器。
      本质上来说,BS是一种特殊的CS,即客户端必须是一种支持HTTP协议且能解析并渲染HTML的软件,服务端必须是能够接收多客户端HTTP访问的服务器软件。
      BS开发分为2端开发
      客户端开发,或者称为前端开发。HTML,CSS javascript等
      服务器端开发,python有WSGI DJANGO Flask、 Tornado

    3. HTTP协议
      练习:安装httpd服务,观察http协议
      协议
      3.1 http协议的无状态协议:
      同一个客户端的2次请求之间没有任何关系,从服务器端角度来说,它不知道这2个请求来自同一个客户端。
      3.2 cookie
      1.键值对信息,
      2.浏览器发起每一个请求时,都会把cookie信息发给服务器端。
      3.是一种客户端。服务器端传递数据的技术。
      4.服务端可以通过判断这些信息,求确定这次请求是否和之前的请求有关联
      5.一般来说cookie信息在服务器端生产,返回给客户端。
      6.客户端可以自己设置cookie信息。
    4. URL组成
      URL可以说就是地址,统一资源定位符,每一个链接指向一个资源供客户端访问。
      例如:通过下面的URL 访问网页。
      访问静态资源时,通过上面这个URL访问的是网站某路径下的index.html文件,而这个文件对应磁盘上的真实的文件。就会从磁盘上读取这个文件,并把文件的内容发回浏览器端。
    5. HTTP消息:
      消息分为Request、Response。
      Request:浏览器向服务器发起的请求
      Response:服务器对客户端请求的响应
      请求和响应消息都是由请求行、Header消息报头、Body消息正文组成。
      请求:请求消息行:请求方法Method 请求路径 协议版本CRLF

    请求方法Method
    GET 请求获取URL对应的资源
    POST 提交数据至服务器端
    HEAD 和GET类似,不过不返回消息正文

    常见传递信息的方式
    1、GET方法使用Query String
    通过查询字符串在URL中传递参数
    2、POST方法提交数据
    使用表单提交数据,文本框input的name属性分别为age、weight、height
    3、URL中本身就包含着信息
    响应
    响应消息行:协议版本 状态码 消息描述CRLF

    状态码在响应头第一行
    1xx 提示信息,表示请求已被成功接收,继续处理
    2xx 表示正常响应
    200 正常返回了网页内容
    3xx 重定向
    301 页面永久性移走,永久重定向。返回新的URL,浏览器会根据返回的url发起新的request请求
    302 临时重定向
    304 资源未修改,浏览器使用本地缓存。
    4xx 客户端请求错误
    404 Not Found,网页找不到,客户端请求的资源有错
    400 请求语法错误
    401 请求要求身份验证
    403 服务器拒绝请求
    5xx 服务器端错误
    500 服务器内部错误
    502 上游服务器错误,例如nginx反向代理的时候
    无状态,有连接和短连接
    无状态,指的是服务器无法知道2次请求之间的联系,即使是前后2次同一个浏览器也没有任何数据能够判
    断出是同一个浏览器的请求。后来可以通过cookie、session来判断。
    有连接,是因为它基于TCP协议,是面向连接的,需要3次握手、4次断开。
    短连接,Http 1.1之前,都是一个请求一个连接,而Tcp的连接创建销毁成本高,对服务器有很大的影响。所以,
    自Http 1.1开始,支持keep-alive,默认也开启,一个连接打开后,会保持一段时间(可设置),浏览器再访问该
    服务器就使用这个Tcp连接,减轻了服务器压力,提高了效率。
    推荐图书《HTTP权威指南》

    展开全文
  • 完整 RPC 框架主要有三部分组成:通信框架、通信协议、序列化和反序列化格式。根据我经验,想要开发一个完整 RPC 框架,并且应用到线上生产环境,至少需要投入三个人力半年以上时间。这对于大部分中小团队来...

    完整的 RPC 框架主要有三部分组成:通信框架、通信协议、序列化和反序列化格式。根据我的经验,想要开发一个完整的 RPC 框架,并且应用到线上生产环境,至少需要投入三个人力半年以上的时间。这对于大部分中小团队来说,人力成本和时间成本都是不可接受的,所以我建议还是选择开源的 RPC 框架比较合适。

    那么业界应用比较广泛的开源 RPC 框架有哪些呢?

    简单划分的话,主要分为两类:一类是跟某种特定语言平台绑定的,另一类是与语言无关即跨语言平台的。

    跟语言平台绑定的开源 RPC 框架主要有下面几种。

    Dubbo:国内最早开源的 RPC 框架,由阿里巴巴公司开发并于 2011 年末对外开源,仅支持 Java 语言。

    Motan:微博内部使用的 RPC 框架,于 2016 年对外开源,仅支持 Java 语言。

    Tars:腾讯内部使用的 RPC 框架,于 2017 年对外开源,仅支持 C++ 语言。

    Spring Cloud:国外 Pivotal 公司 2014 年对外开源的 RPC 框架,仅支持 Java 语言,最近几年生态发展得比较好,是比较火的 RPC 框架。

    而跨语言平台的开源 RPC 框架主要有以下几种。

    gRPC:Google 于 2015 年对外开源的跨语言 RPC 框架,支持常用的 C++、Java、Python、Go、Ruby、PHP、Android Java、Objective-C 等多种语言。

    Thrift:最初是由 Facebook 开发的内部系统跨语言的 RPC 框架,2007 年贡献给了 Apache 基金,成为 Apache 开源项目之一,支持常用的 C++、Java、PHP、Python、Ruby、Erlang 等多种语言。

    所以很明显,如果你的业务场景仅仅局限于一种语言的话,可以选择跟语言绑定的 RPC 框架中的一种;如果涉及多个语言平台之间的相互调用,就应该选择跨语言平台的 RPC 框架。

    针对每一种 RPC 框架,它们具体有何区别?该如何选择呢?接下来,我就从每个框架的实现角度来具体给你讲解。当你知道了他们的具体实现,也就能知道他们的优缺点以及适用场景了。

    限定语言平台的开源 RPC 框架

    1. Dubbo

    先来聊聊 Dubbo,Dubbo 可以说是国内开源最早的 RPC 框架了,目前只支持 Java 语言,它的架构可以用下面这张图展示。

    mahua

    从图中你能看到,Dubbo 的架构主要包含四个角色,其中 Consumer 是服务消费者,Provider 是服务提供者,Registry 是注册中心,Monitor 是监控系统。

    具体的交互流程是 Consumer 一端通过注册中心获取到 Provider 节点后,通过 Dubbo 的客户端 SDK 与 Provider 建立连接,并发起调用。Provider 一端通过 Dubbo 的服务端 SDK 接收到 Consumer 的请求,处理后再把结果返回给 Consumer。

    可以看出服务消费者和服务提供者都需要引入 Dubbo 的 SDK 才来完成 RPC 调用,因为 Dubbo 本身是采用 Java 语言实现的,所以要求服务消费者和服务提供者也都必须采用 Java 语言实现才可以应用。

    我们再来看下 Dubbo 的调用框架是如何实现的。

    通信框架方面,Dubbo 默认采用了 Netty 作为通信框架。

    通信协议方面,Dubbo 除了支持私有的 Dubbo 协议外,还支持 RMI 协议、Hession 协议、HTTP 协议、Thrift 协议等。

    序列化格式方面,Dubbo 支持多种序列化格式,比如 Dubbo、Hession、JSON、Kryo、FST 等。

    1. Motan

    Motan 是国内另外一个比较有名的开源的 RPC 框架,同样也只支持 Java 语言实现,它的架构可以用下面这张图描述。

    mahua

    Motan 与 Dubbo 的架构类似,都需要在 Client 端(服务消费者)和 Server 端(服务提供者)引入 SDK,其中 Motan 框架主要包含下面几个功能模块。

    register:用来和注册中心交互,包括注册服务、订阅服务、服务变更通知、服务心跳发送等功能。Server 端会在系统初始化时通过 register 模块注册服务,Client 端会在系统初始化时通过 register 模块订阅到具体提供服务的 Server 列表,当 Server 列表发生变更时也由 register 模块通知 Client。

    protocol:用来进行 RPC 服务的描述和 RPC 服务的配置管理,这一层还可以添加不同功能的 filter 用来完成统计、并发限制等功能。

    serialize:将 RPC 请求中的参数、结果等对象进行序列化与反序列化,即进行对象与字节流的互相转换,默认使用对 Java 更友好的 Hessian 2 进行序列化。

    transport:用来进行远程通信,默认使用 Netty NIO 的 TCP 长链接方式。

    cluster:Client 端使用的模块,cluster 是一组可用的 Server 在逻辑上的封装,包含若干可以提供 RPC 服务的 Server,实际请求时会根据不同的高可用与负载均衡策略选择一个可用的 Server 发起远程调用。

    1. Tars

    Tars 是腾讯根据内部多年使用微服务架构的实践,总结而成的开源项目,仅支持 C++ 语言,它的架构图如下。

    mahua

    Tars 的架构交互主要包括以下几个流程:

    服务发布流程:在 web 系统上传 server 的发布包到 patch,上传成功后,在 web 上提交发布 server 请求,由 registry 服务传达到 node,然后 node 拉取 server 的发布包到本地,拉起 server 服务。

    管理命令流程:web 系统上的可以提交管理 server 服务命令请求,由 registry 服务传达到 node 服务,然后由 node 向 server 发送管理命令。

    心跳上报流程:server 服务运行后,会定期上报心跳到 node,node 然后把服务心跳信息上报到 registry 服务,由 registry 进行统一管理。

    信息上报流程:server 服务运行后,会定期上报统计信息到 stat,打印远程日志到 log,定期上报属性信息到 prop、上报异常信息到 notify、从 config 拉取服务配置信息。

    client 访问 server 流程:client 可以通过 server 的对象名 Obj 间接访问 server,client 会从 registry 上拉取 server 的路由信息(如 IP、Port 信息),然后根据具体的业务特性(同步或者异步,TCP 或者 UDP 方式)访问 server(当然 client 也可以通过 IP/Port 直接访问 server)。

    1. Spring Cloud

    Spring Cloud 是为了解决微服务架构中服务治理而提供的一系列功能的开发框架,它是完全基于 Spring Boot 进行开发的,Spring Cloud 利用 Spring Boot 特性整合了开源行业中优秀的组件,整体对外提供了一套在微服务架构中服务治理的解决方案。因为 Spring Boot 是用 Java 语言编写的,所以目前 Spring Cloud 也只支持 Java 语言平台,它的架构图可以用下面这张图来描述。

    mahua

    由此可见,Spring Cloud 微服务架构是由多个组件一起组成的,各个组件的交互流程如下。

    请求统一通过 API 网关 Zuul 来访问内部服务,先经过 Token 进行安全认证。

    通过安全认证后,网关 Zuul 从注册中心 Eureka 获取可用服务节点列表。

    从可用服务节点中选取一个可用节点,然后把请求分发到这个节点。

    整个请求过程中,Hystrix 组件负责处理服务超时熔断,Turbine 组件负责监控服务间的调用和熔断相关指标,Sleuth 组件负责调用链监控,ELK 负责日志分析。

    1. 对比选型

    介绍完这 4 种限定语言的开源 RPC 框架后,我们该如何选择呢?

    很显然,如果你的语言平台是 C++,那么只能选择 Tars;而如果是 Java 的话,可以选择 Dubbo、Motan 或者 Spring Cloud。这时你又要问了,它们三个又该如何抉择呢?

    仔细分析,可以看出 Spring Cloud 不仅提供了基本的 RPC 框架功能,还提供了服务注册组件、配置中心组件、负载均衡组件、断路器组件、分布式消息追踪组件等一系列组件,也难怪被技术圈的人称之为“Spring Cloud 全家桶”。如果你不想自己实现以上这些功能,那么 Spring Cloud 基本可以满足你的全部需求。而 Dubbo、Motan 基本上只提供了最基础的 RPC 框架的功能,其他微服务组件都需要自己去实现。

    不过由于 Spring Cloud 的 RPC 通信采用了 HTTP 协议,相比 Dubbo 和 Motan 所采用的私有协议来说,在高并发的通信场景下,性能相对要差一些,所以对性能有苛刻要求的情况下,可以考虑 Dubbo 和 Motan。

    跨语言平台的开源 RPC 框架

    1. gRPC

    先来看下 gRPC,它的原理是通过 IDL(Interface Definition Language)文件定义服务接口的参数和返回值类型,然后通过代码生成程序生成服务端和客户端的具体实现代码,这样在 gRPC 里,客户端应用可以像调用本地对象一样调用另一台服务器上对应的方法。
    mahua

    它的主要特性包括三个方面。

    通信协议采用了 HTTP/2,因为 HTTP/2 提供了连接复用、双向流、服务器推送、请求优先级、首部压缩等机制,所以在通信过程中可以节省带宽、降低 TCP 连接次数、节省 CPU,尤其对于移动端应用来说,可以帮助延长电池寿命。

    IDL 使用了ProtoBuf,ProtoBuf 是由 Google 开发的一种数据序列化协议,它的压缩和传输效率极高,语法也简单,所以被广泛应用在数据存储和通信协议上。

    多语言支持,能够基于多种语言自动生成对应语言的客户端和服务端的代码。

    1. Thrift

    再来看下 Thrift,Thrift 是一种轻量级的跨语言 RPC 通信方案,支持多达 25 种编程语言。为了支持多种语言,跟 gRPC 一样,Thrift 也有一套自己的接口定义语言 IDL,可以通过代码生成器,生成各种编程语言的 Client 端和 Server 端的 SDK 代码,这样就保证了不同语言之间可以相互通信。它的架构图可以用下图来描述。

    (图片来源:https://github.com/apache/thrift/raw/master/doc/images/thrift-layers.png)

    从这张图上可以看出 Thrift RPC 框架的特性。

    支持多种序列化格式:如 Binary、Compact、JSON、Multiplexed 等。

    支持多种通信方式:如 Socket、Framed、File、Memory、zlib 等。

    服务端支持多种处理方式:如 Simple 、Thread Pool、Non-Blocking 等。

    1. 对比选型

    那么涉及跨语言的服务调用场景,到底该选择 gRPC 还是 Thrift 呢?

    从成熟度上来讲,Thrift 因为诞生的时间要早于 gRPC,所以使用的范围要高于 gRPC,在 HBase、Hadoop、Scribe、Cassandra 等许多开源组件中都得到了广泛地应用。而且 Thrift 支持多达 25 种语言,这要比 gRPC 支持的语言更多,所以如果遇到 gRPC 不支持的语言场景下,选择 Thrift 更合适。

    但 gRPC 作为后起之秀,因为采用了 HTTP/2 作为通信协议、ProtoBuf 作为数据序列化格式,在移动端设备的应用以及对传输带宽比较敏感的场景下具有很大的优势,而且开发文档丰富,根据 ProtoBuf 文件生成的代码要比 Thrift 更简洁一些,从使用难易程度上更占优势,所以如果使用的语言平台 gRPC 支持的话,建议还是采用 gRPC 比较好。

    总结
    以上就是我对几种使用最广泛的开源 RPC 框架的选型建议,也是基于它们目前现状所作出的判断,从长远来看,支持多语言是 RPC 框架未来的发展趋势。正是基于此判断,各个 RPC 框架都提供了 Sidecar 组件来支持多语言平台之间的 RPC 调用。

    Dubbo 在去年年底又重启了维护,并且宣称要引入 Sidecar 组件来构建Dubbo Mesh提供多语言支持。

    Motan 也在去年对外开源了其内部的 Sidecar 组件:Motan-go,目前支持 PHP、Java 语言之间的相互调用。

    Spring Cloud 也提供了 Sidecar 组件spring-cloud-netflix-sideca,可以让其他语言也可以使用 Spring Cloud 的组件。

    所以未来语言不会成为使用上面这几种 RPC 框架的约束,而 gRPC 和 Thrift 虽然支持跨语言的 RPC 调用,但是因为它们只提供了最基本的 RPC 框架功能,缺乏一系列配套的服务化组件和服务治理功能的支撑,所以使用它们作为跨语言调用的 RPC 框架,就需要自己考虑注册中心、熔断、限流、监控、分布式追踪等功能的实现,不过好在大多数功能都有开源实现,可以直接采用。

    展开全文
  • 代码格式篇代码格式缩进方法书写方法调用@public和@private标记符协议(Protocols)闭包(Blocks)数据结构字面量写法nil检查 代码格式 缩进 不要在工程里使用Tab键,使用空格来进行缩进。不要去修改Xcode > ...

    代码格式

    缩进

    不要在工程里使用Tab键,使用空格来进行缩进。不要去修改Xcode > Preferences > Text Editing里的Tab和自动缩进的默认的 4 个空格设置,即使用 Xcode 的默认设置即可。

    方法的书写

    一个典型的 Objective-C 方法应该是这样的:

    - (void)writeVideoFrameWithData:(NSData *)frameData timeStamp:(int)timeStamp {
        ...
    }
    

    在-和(void)之间应该有一个空格,第一个大括号{的位置在方法所在行的末尾,同样应该有一个空格。

    如果一个方法有特别多的参数或者名称很长,应该将其按照:来对齐分行显示:

    -(id)initWithModel:(IPCModle)model
           ConnectType:(IPCConnectType)connectType
            Resolution:(IPCResolution)resolution
              AuthName:(NSString *)authName
              Password:(NSString *)password
                   MAC:(NSString *)mac
                  AzIp:(NSString *)az_ip
                 AzDns:(NSString *)az_dns
                 Token:(NSString *)token
                 Email:(NSString *)email
              Delegate:(id<IPCConnectHandlerDelegate>)delegate;
    

    在分行时,如果第一段名称过短,后续名称可以以Tab的长度(4个空格)为单位进行缩进:

    - (void)short:(GTMFoo *)theFoo
            longKeyword:(NSRect)theRect
      evenLongerKeyword:(float)theInterval
                  error:(NSError **)theError {
        ...
    }
    

    方法调用

    方法调用的格式和书写差不多,可以按照方法的长短来选择写在一行或者分成多行:

    //写在一行
    [myObject doFooWith:arg1 name:arg2 error:arg3];
    
    //分行写,按照':'对齐
    [myObject doFooWith:arg1
                   name:arg2
                  error:arg3];
    
    //第一段名称过短的话后续可以进行缩进
    [myObj short:arg1
              longKeyword:arg2
        evenLongerKeyword:arg3
                    error:arg4];
    

    以下写法是错误的:

    //错误,要么写在一行,要么全部分行
    [myObject doFooWith:arg1 name:arg2
                  error:arg3];
    [myObject doFooWith:arg1
                   name:arg2 error:arg3];
    
    //错误,按照':'来对齐,而不是关键字
    [myObject doFooWith:arg1
              name:arg2
              error:arg3];
    

    @public和@private标记符

    @public和@private标记符应该以 一个空格 来进行缩进:

    @interface MyClass : NSObject {
     @public
      ...
     @private
      ...
    }
    @end
    

    协议(Protocols)

    在书写协议的时候注意用<>括起来的协议和类型名之间是没有空格的,比如IPCConnectHandler(),这个规则适用所有书写协议的地方,包括方法声明、类声明、实例变量等等:

    @interface MyProtocoledClass : NSObject<NSWindowDelegate> {
     @private
        id<MyFancyDelegate> _delegate;
    }
    
    - (void)setDelegate:(id<MyFancyDelegate>)aDelegate;
    @end
    

    闭包(Blocks)

    根据block的长度,有不同的书写规则:

    • 较短的block可以写在一行内。
    • 如果分行显示的话,block的右括号}应该和调用block那行代码的第一个非空字符对齐。
    • block内的代码采用4个空格的缩进。
    • 如果block过于庞大,应该单独声明成一个变量来使用。
    • 和(之间,和{之间都没有空格,参数列表的右括号)和{之间有一个空格。
    //较短的block写在一行内
    [operation setCompletionBlock:^{ [self onOperationDone]; }];
    
    //分行书写的block,内部使用4空格缩进
    [operation setCompletionBlock:^{
        [self.delegate newDataAvailable];
    }];
    
    //使用C语言API调用的block遵循同样的书写规则
    dispatch_async(_fileIOQueue, ^{
        NSString* path = [self sessionFilePath];
        if (path) {
          // ...
        }
    });
    
    //较长的block关键字可以缩进后在新行书写,注意block的右括号'}'和调用block那行代码的第一个非空字符对齐
    [[SessionService sharedService]
        loadWindowWithCompletionBlock:^(SessionWindow *window) {
            if (window) {
              [self windowDidLoad:window];
            } else {
              [self errorLoadingWindow];
            }
        }];
    
    //较长的block参数列表同样可以缩进后在新行书写
    [[SessionService sharedService]
        loadWindowWithCompletionBlock:
            ^(SessionWindow *window) {
                if (window) {
                  [self windowDidLoad:window];
                } else {
                  [self errorLoadingWindow];
                }
            }];
    
    //庞大的block应该单独定义成变量使用
    void (^largeBlock)(void) = ^{
        // ...
    };
    [_operationQueue addOperationWithBlock:largeBlock];
    
    //在一个调用中使用多个block,注意到他们不是像方法那样通过':'对齐的,而是同时进行了4个空格的缩进
    [myObject doSomethingWith:arg1
        firstBlock:^(Foo *a) {
            // ...
        }
        secondBlock:^(Bar *b) {
            // ...
        }];
    

    数据结构的字面量写法

    应该使用可读性更好的字面量来构造NSArray,NSDictionary等数据结构,避免使用冗长的alloc,init方法。

    如果构造代码写在一行,需要在括号两端留有一个空格,使得被构造的元素于与构造语法区分开来:

    //正确,在字面量的"[]"或者"{}"两端留有空格
    NSArray *array = @[ [foo description], @"Another String", [bar description] ];
    NSDictionary *dict = @{ NSForegroundColorAttributeName : [NSColor redColor] };
    
    //不正确,不留有空格降低了可读性
    NSArray* array = @[[foo description], [bar description]];
    NSDictionary* dict = @{NSForegroundColorAttributeName: [NSColor redColor]};
    

    如果构造代码不写在一行内,构造元素需要使用 两个空格 来进行缩进,右括号]或者}写在新的一行,并且与调用字面量那行代码的第一个非空字符对齐:

    NSArray *array = @[
      @"This",
      @"is",
      @"an",
      @"array"
    ];
    
    NSDictionary *dictionary = @{
      NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12],
      NSForegroundColorAttributeName : fontColor
    };
    

    构造字典时,字典的Key和Value与中间的冒号:都要留有一个空格,多行书写时,也可以将Value对齐:

    //正确,冒号':'前后留有一个空格
    NSDictionary *option1 = @{
      NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12],
      NSForegroundColorAttributeName : fontColor
    };
    
    //正确,按照Value来对齐
    NSDictionary *option2 = @{
      NSFontAttributeName :            [NSFont fontWithName:@"Arial" size:12],
      NSForegroundColorAttributeName : fontColor
    };
    
    //错误,冒号前应该有一个空格
    NSDictionary *wrong = @{
      AKey:       @"b",
      BLongerKey: @"c",
    };
    
    //错误,每一个元素要么单独成为一行,要么全部写在一行内
    NSDictionary *alsoWrong= @{ AKey : @"a",
                                BLongerKey : @"b" };
    
    //错误,在冒号前只能有一个空格,冒号后才可以考虑按照Value对齐
    NSDictionary *stillWrong = @{
      AKey       : @"b",
      BLongerKey : @"c",
    };
    

    nil检查

    因为在 Objective-C 中向nil对象发送命令是不会抛出异常或者导致崩溃的,只是完全的“什么都不干”,所以,只在程序中使用nil来做逻辑上的检查。

    另外,不要使用诸如nil == Object或者Object == nil的形式来判断。

    //正确,直接判断
    if (!objc) {
    	...	
    }
    
    //错误,不要使用nil == Object的形式
    if (nil == objc) {
    	...	
    }
    
    展开全文
  • 最近看到了一篇关于阿里何洪辉的singlenet框架,然后自己结合了mvp框架自己架构了一个简单的程序...//首先是request的抽象类,根据http协议的格式设置response内容 package net; import java.io.UnsupportedEncodingE
    最近看到了一篇关于阿里何洪辉的singlenet框架,然后自己结合了mvp框架自己架构了一个简单的程序框架,接下去我将以登录模块来说明一下我的这个小框架
    首先是singlenet的框架,这个框架的知识是照搬书上的

    //首先是request的抽象类,根据http协议的格式设置response内容

    package net;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by Administrator on 2017/4/5.
     */
    
    public abstract class Request<T> implements Comparable<Request<T>> {
        public static enum HttpMethod{
            GET,
            POST,
            PUT,
            DELETE
        }
        public static enum Priority{
            LOW,
            NORMAL,
            HIGHT,
            IMMEDIATE
        }
        //设置默认编码
        private static String DEFAULT_PARAMS_ENCODING ="UTF-8";
        //请求序列号
        protected int mSerialNum = 0;
        //请求优先级
        protected Priority priority =Priority.NORMAL;
        //是否取消请求
        protected  boolean isCancle = false;
        //是否需要缓存
        private boolean mShouldCache =true;
        //请求回调
        public RequestListener<T> mRequestListener;
        //请求url
        private String mUrl ="";
        //请求方法
        HttpMethod mMethod =HttpMethod.GET;
        //请求的head
        private Map<String,String> mHeads = new HashMap<String,String>();
        //请求参数
        private Map<String,String> mBodyParams = new HashMap<String,String>();
        public Request(HttpMethod mMethod,String mUrl,RequestListener<T> mRequestListener){
            this.mMethod = mMethod;
            this.mUrl = mUrl;
            this.mRequestListener = mRequestListener;
        }
        public abstract T parseResponse(Response response);
        public final void deliveryResponse(Response response){
            T result = parseResponse(response);
            //设置监听
            if( mRequestListener!=null){
                int stCode =response!=null?200:-1;
                String msg = response!=null?"ok":"unknow error";
                mRequestListener.onComplete(stCode,result,msg);
            }
        }
        protected String getParamsEncoding(){
            return DEFAULT_PARAMS_ENCODING;
        }
        public String getBodyContendType(){
            return "application/x-www-form-urlencoded;charset="+getParamsEncoding();
        }
        public Map getParams(){
            return mBodyParams;
        }
    
        public static String getDefaultParamsEncoding() {
            return DEFAULT_PARAMS_ENCODING;
        }
    
        public static void setDefaultParamsEncoding(String defaultParamsEncoding) {
            DEFAULT_PARAMS_ENCODING = defaultParamsEncoding;
        }
    
        public int getmSerialNum() {
            return mSerialNum;
        }
    
        public void setmSerialNum(int mSerialNum) {
            this.mSerialNum = mSerialNum;
        }
    
        public Priority getPriority() {
            return priority;
        }
    
        public void setPriority(Priority priority) {
            this.priority = priority;
        }
    
        public boolean isCancle() {
            return isCancle;
        }
    
        public void setCancle(boolean cancle) {
            isCancle = cancle;
        }
    
        public boolean ismShouldCache() {
            return mShouldCache;
        }
    
        public void setmShouldCache(boolean mShouldCache) {
            this.mShouldCache = mShouldCache;
        }
    
        public HttpMethod getmMethod() {
            return mMethod;
        }
    
        public void setmMethod(HttpMethod mMethod) {
            this.mMethod = mMethod;
        }
    
        public String getmUrl() {
            return mUrl;
        }
    
        public void setmUrl(String mUrl) {
            this.mUrl = mUrl;
        }
    
        public Map<String, String> getmHeads() {
            return mHeads;
        }
    
        public void setmHeads(Map<String, String> mHeads) {
            this.mHeads = mHeads;
        }
    
        public Map<String, String> getmBodyParams() {
            return mBodyParams;
        }
    
        public void setmBodyParams(Map<String, String> mBodyParams) {
            this.mBodyParams = mBodyParams;
        }
    
        public byte[] getBody(){
            Map<String,String> params = getParams();
    
            if(params!=null&¶ms.size()>0){
                return  encodedParams(params,getParamsEncoding());
            }
            return null;
        }
        //body格式
        private byte[] encodedParams(Map<String,String> params,String paramsEncoding){
            StringBuilder encodedParamters = new StringBuilder();
            int size =params.entrySet().size();
            int index =1;
            try {
            for(Map.Entry<String,String> entry:params.entrySet()){
                    encodedParamters.append(URLEncoder.encode(entry.getKey(),paramsEncoding));
                    encodedParamters.append("=");
                    encodedParamters.append(URLEncoder.encode(entry.getValue(),paramsEncoding));
                    if(index!=size){
                    encodedParamters.append("&");
                    }
                         index++;
                  }
                return encodedParamters.toString().getBytes(paramsEncoding);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return  new byte[0];
        }
    
        @Override
        public int compareTo(Request<T> another) {
            Priority myPriority = getPriority();
            Priority anotherPriority = another.getPriority();
            return myPriority.equals(anotherPriority)?this.getmSerialNum()-another.getmSerialNum():myPriority.ordinal()-anotherPriority.ordinal();
    
        }
        //回调接口
        public static interface  RequestListener<T>{
            public void onComplete(int stCode,T response,String errMsg);
        }
    }
    

    //然后一个jsonRequest的实现,覆盖父类的数据解析方法,返回jsonobject

    package net;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    /**
     * Created by Administrator on 2017/4/30.
     */
    
    public class JsonRequest extends Request<JSONObject>{
        public JsonRequest(HttpMethod mMethod, String mUrl, RequestListener<JSONObject> mRequestListener) {
            super(mMethod, mUrl, mRequestListener);
        }
    
        @Override
        public JSONObject parseResponse(Response response) {
            if(response!=null){
            String jsonString  = new String(response.getRowData());
            try {
                return new JSONObject(jsonString);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            }
            return null;
        }
    }
    
    //response类,接收网络请求的响应内容

    package net;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.ProtocolVersion;
    import org.apache.http.StatusLine;
    import org.apache.http.message.BasicHttpResponse;
    import org.apache.http.util.EntityUtils;
    
    import java.io.IOException;
    
    /**
     * Created by Administrator on 2017/4/5.
     */
    
    public class Response extends BasicHttpResponse {
        byte[] rowData = new byte[0];
        private int statusCode;
    
        public int getStatusCode() {
            return statusCode;
        }
    
        @Override
        public void setStatusCode(int statusCode) {
            this.statusCode = statusCode;
        }
    
        public Response(StatusLine statusline) {
            super(statusline);
        }
    
        public Response(ProtocolVersion ver, int code, String reason) {
            super(ver, code, reason);
        }
    
        @Override
        public void setEntity(HttpEntity entity) {
            super.setEntity(entity);
            rowData = entityToBytes(entity);
        }
        public byte[] getRowData(){
            return rowData;
        }
        private byte[] entityToBytes(HttpEntity entity){
            try {
                return EntityUtils.toByteArray(entity);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new byte[0];
        }
    }
    

    //response和request完成后,书写一个请求队列进行处理请求

    package net;
    
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.PriorityBlockingQueue;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * Created by Administrator on 2017/4/5.
     */
    
    public class RequestQueue{
        private BlockingQueue<Request<?>> mRequestQueue= new PriorityBlockingQueue<Request<?>>();
        private AtomicInteger atomicInteger = new AtomicInteger(0);
        public static int DEFAULT_CORE_NUMS = Runtime.getRuntime().availableProcessors()+1;
        private int mDispatcherNums =DEFAULT_CORE_NUMS;
        private NetWorkExecutor[] mDispatchers = null;
        private HttpStack httpStack;
        public  RequestQueue(){
            this(DEFAULT_CORE_NUMS,null);
        }
        protected  RequestQueue(int coreNums,HttpStack httpStack){
            this.mDispatcherNums = coreNums;
            this.httpStack = httpStack!=null?httpStack:HttpStackFactory.createHttpStack();
        }
        private final void startNetworkExecutors(){
            mDispatchers = new NetWorkExecutor[mDispatcherNums];
            for(int i=0;i<mDispatcherNums;i++){
                mDispatchers[i] = new NetWorkExecutor(mRequestQueue,httpStack);
                mDispatchers[i].start();
            }
        }
        public void start(){
            stop();
            startNetworkExecutors();
        }
        public void stop(){
            if(mDispatchers!=null&&mDispatchers.length>0){
                for(int i=0;i<mDispatchers.length;i++){
                    mDispatchers[i].quit();
                }
            }
        }
        public void addRequest(Request<?> request){
            if(!mRequestQueue.contains(request)){
                request.setmSerialNum(generateSerialNumber());
                mRequestQueue.add(request);
            }
        }
        private int generateSerialNumber(){
            return atomicInteger.incrementAndGet();
        }
    
    }
    

    //请求队列中的执行器,获得请求队列开启线程进行处理

    package net;
    
    
    
    
    
    
    
    import android.util.Log;
    import android.util.LruCache;
    
    import java.util.concurrent.BlockingQueue;
    
    /**
     * Created by Administrator on 2017/4/9.
     */
    
    public class NetWorkExecutor extends Thread {
        private BlockingQueue<Request<?>> mRequestQueue;
        private HttpStack mHttpStack;
        private static ResponseDelivery mResponseDelivery = new ResponseDelivery();
        private static LruCache<String,Response> mreqCache = new LruCache<String,Response>(100);
        private boolean isStop = false;
        public NetWorkExecutor(BlockingQueue<Request<?>> mRequestQueue,HttpStack httpStack){
            this.mRequestQueue=mRequestQueue;
            this.mHttpStack = httpStack;
        }
    
        @Override
        public void run() {
            while(!isStop){
                try {
                    final Request<?> request = mRequestQueue.take();
                    if(request.isCancle()){
                        Log.d("###","###取消执行");
                        continue;
                    }
                    Response response=null;
                    if(isUserCache(request)){
                        response=mreqCache.get(request.getmUrl());
                    }else{
                        response = mHttpStack.performRequest(request);
                        if(response==null){
                            System.out.println("返回response为空");
                        }
                        if(request.ismShouldCache()&&isSuccess(response)){
                            mreqCache.put(request.getmUrl(),response);
                        }
                    }
                    mResponseDelivery.deliveryResponse(request,response);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        private boolean isSuccess(Response response){
            return response!=null&&response.getStatusCode()==200;
        }
        private boolean isUserCache(Request<?> request){
            return request.ismShouldCache()&& mreqCache.get(request.getmUrl())!=null;
        }
        public void quit(){
            isStop=true;
            interrupt();
        }
    }
    

    //接下去是网络请求的真正执行者,通过request获取response

    package net;
    
    import com.baidu.trace.T;
    
    import org.apache.http.Header;
    import org.apache.http.HttpEntity;
    import org.apache.http.ProtocolVersion;
    import org.apache.http.StatusLine;
    import org.apache.http.entity.BasicHttpEntity;
    import org.apache.http.message.BasicHeader;
    import org.apache.http.message.BasicHttpResponse;
    import org.apache.http.message.BasicStatusLine;
    
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.ProtocolException;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * Created by Administrator on 2017/4/9.
     */
    
    public class HttpUrlConnecStack implements HttpStack {
        @Override
        public Response performRequest(Request<?> request) {
            HttpURLConnection urlConnection =null;
            try {
                urlConnection =createUrlConnection(request.getmUrl());
                System.out.println("设置头部");
                setRequestHeaders(urlConnection,request);
                System.out.println("设置参数");
                setRequestParams(urlConnection,request);
                urlConnection.connect();
                return fetchResponse(urlConnection);
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("异常是"+e.toString());
            }finally {
                if(urlConnection!=null){
                    urlConnection.disconnect();
                }
            }
            return null;
        }
        private HttpURLConnection createUrlConnection(String url) throws IOException {
            URL newURL = new URL(url);
            URLConnection urlConnection = newURL.openConnection();
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            return (HttpURLConnection) urlConnection;
        }
        private void setRequestHeaders(HttpURLConnection connection,Request<?> request){
            Set<String> headersKeys = request.getmHeads().keySet();
            for(String headerName:headersKeys){
                connection.addRequestProperty(headerName,request.getmHeads().get(headerName));
            }
        }
        protected void setRequestParams(HttpURLConnection connection,Request<?> request) throws IOException {
            Request.HttpMethod method=request.getmMethod();
            connection.setRequestMethod(method.toString());
            //connection.setRequestMethod("POST");
            byte[] body =request.getBody();
            String params = new String(body);
            System.out.println("参数是"+params);
            if(body!=null){
                connection.setDoInput(true);
                connection.addRequestProperty("Content-Type",request.getBodyContendType());
                DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
                dataOutputStream.write(body);
                dataOutputStream.close();
            }
        }
        private Response fetchResponse(HttpURLConnection connection) throws IOException {
            ProtocolVersion protocolVersion = new ProtocolVersion("HTTP",1,1);
            int responseCode = connection.getResponseCode();
            if(responseCode==-1){
                System.out.println("抛出异常!");
                throw new IOException("Could not retrieve response code from HttpUrlConnection");
            }
            System.out.println("请求链接成功!");
            StatusLine responseStatus = new BasicStatusLine(protocolVersion,connection.getResponseCode(),connection.getResponseMessage());
            Response response = new Response(responseStatus);
            response.setStatusCode(connection.getResponseCode());
           response.setEntity(entityFromURLConnection(connection));
            addHeadersToResponse(response,connection);
            return response;
        }
        private HttpEntity entityFromURLConnection(HttpURLConnection connection){
            BasicHttpEntity entity = new BasicHttpEntity();
            InputStream inputStream =null;
            try {
                inputStream = connection.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
                inputStream= connection.getErrorStream();
            }
            entity.setContent(inputStream);
            entity.setContentLength(connection.getContentLength());
            entity.setContentType(connection.getContentType());
            return entity;
        }
        private void addHeadersToResponse(BasicHttpResponse response,HttpURLConnection connection){
            for(Map.Entry<String,List<String>> header:connection.getHeaderFields().entrySet()){
                if(header.getKey()!=null){
                    Header h = new BasicHeader(header.getKey(),header.getValue().get(0));
                    response.setHeader(h);
                }
            }
        }
    
    
    }
    

    //response传递者,将response传递到UI线程中

    package net;
    
    import android.os.Handler;
    import android.os.Looper;
    
    import java.util.concurrent.Executor;
    
    /**
     * Created by Administrator on 2017/4/9.
     */
    
    public class ResponseDelivery implements Executor {
        Handler mResponseHandler = new Handler(Looper.getMainLooper());
        public void deliveryResponse(final Request<?>request,final  Response response){
            Runnable responseRunnable = new Runnable() {
                @Override
                public void run() {
                    request.deliveryResponse(response);
                }
            };
            execute(responseRunnable);
        }
        @Override
        public void execute(Runnable runnable) {
            mResponseHandler.post(runnable);
        }
    }
    
    以上整个网络框架就完成了,接下去就是结合mvp框架

    //首先是view的接口

    package viewinterface;
    
    /**
     * Created by Administrator on 2017/4/30.
     */
    
    public interface LoginViewInterface {
        void loginSuccess();
        void loginFailed(String errorMessage);
        void registFailed(String errorMessage);
        void regustSuccess();
        void doLogin();
        void doRegist();
    
    }
    
    //view的实现LoginView,充当view视图,只进行视图的转换

    package com.example.administrator.exercise;
    
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.content.Intent;
    import android.net.wifi.WifiInfo;
    import android.net.wifi.WifiManager;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import FileUtils.ImageLoader;
    import Manager.MyDialogFactory;
    import chart.imp.ImgeSelectorActivity;
    import present.LoginPresent;
    import viewinterface.LoginViewInterface;
    
    /**
     * Created by Administrator on 2017/4/30.
     */
    
    public class LoginActivtity extends Activity implements LoginViewInterface,View.OnClickListener{
      private TextView phoneText ;
        private TextView passwordText;
        private Button loginButton;
        private Button registButton;
        private ImageView logoImage;
        private LoginPresent present;
        private ProgressDialog dialog;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            init();
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
        }
    
        private void init(){
            phoneText = (TextView) findViewById(R.id.phone_text);
            passwordText = (TextView) findViewById(R.id.password_text);
            loginButton = (Button) findViewById(R.id.login_button);
            registButton = (Button) findViewById(R.id.regist_button);
            logoImage = (ImageView) findViewById(R.id.logo_image);
            present = new LoginPresent(this);
            dialog = MyDialogFactory.getInstance().createProgressDialog("请稍后。。。",this);
            setListener();
        }
        private void setListener(){
            loginButton.setOnClickListener(this);
            registButton.setOnClickListener(this);
            logoImage.setOnClickListener(this);
        }
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.login_button:
                    present.login(phoneText.getText().toString().trim(),
                            passwordText.getText().toString());
                    break;
                case R.id.regist_button:
                    present.regist(phoneText.getText().toString().trim(),
                            passwordText.getText().toString().trim());
                    break;
    
            }
    
        }
    
        @Override
        public void loginSuccess() {
            Toast.makeText(this,"成功",Toast.LENGTH_LONG).show();
            Intent intent = new Intent();
            intent.setClass( LoginActivtity.this,MainActivity.class);
            startActivity(intent);
            dialog.dismiss();
        }
    
        @Override
        public void loginFailed(String errorMessage) {
            Toast.makeText(this,"登录失败:"+errorMessage,Toast.LENGTH_LONG).show();
            dialog.dismiss();
        }
    
        @Override
        public void registFailed(String errorMessage) {
            Toast.makeText(this,"注册失败"+errorMessage,Toast.LENGTH_LONG).show();
            dialog.dismiss();
        }
    
        @Override
        public void regustSuccess() {
            Toast.makeText(this,"注册成功",Toast.LENGTH_LONG).show();
            dialog.dismiss();
        }
    
        @Override
        public void doLogin() {
            dialog.show();
    
        }
    
        @Override
        public void doRegist() {
            dialog.show();
    
    
        }
    }
    
    //present中介,实现onLoginListener接口,接收model中不同的情况进行不同的处理,同时拥有view 和model的对象,对view和model进行解耦数据获取数据后直接在里面进行设置视图

    package present;
    
    import org.json.JSONObject;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import Listener.OnLoginListener;
    import model.LoginModel;
    import model.LoginModelInterface;
    import proxy.MiddleNetProxy;
    import proxy.ResponsReceiver;
    import viewinterface.LoginViewInterface;
    
    /**
     * Created by Administrator on 2017/4/30.
     */
    
    public class LoginPresent implements  OnLoginListener {
        LoginViewInterface loginViewInterface;
        LoginModelInterface loginModelInterface;
        public LoginPresent( LoginViewInterface loginViewInterface){
            this.loginViewInterface = loginViewInterface;
            loginModelInterface = new LoginModel();
            loginModelInterface.setOnLoginListener(this);
    
        }
        public void login(String phone,String password){
                loginModelInterface.doLogin(phone,password);
        }
        public void regist(String phone,String password){
            if(!"".equals(phone)&&!"".equals(password)){
                loginViewInterface.doRegist();
            loginModelInterface.doRegist(phone,password);
            }
        }
        @Override
        public void loginSuccess() {
            loginViewInterface.loginSuccess();
        }
    
        @Override
        public void loginFailed(String errorMessage) {
            loginViewInterface.loginFailed(errorMessage);
        }
    
        @Override
        public void registFailed(String errorMessage) {
            loginViewInterface.registFailed(errorMessage);
        }
    
        @Override
        public void regustSuccess() {
            loginViewInterface.regustSuccess();
        }
    }
    
    //然后是model数据获取,集成responseReveive,在hanler中处理网络中介返回来的response,并且通过onLoginListener传递给present,
    
    

    package model;
    
    import android.content.Context;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import java.util.HashMap;
    
    import FileUtils.TempURL;
    import Listener.OnLoginListener;
    import proxy.MiddleNetProxy;
    import proxy.ResponsReceiver;
    
    /**
     * Created by Administrator on 2017/5/4.
     */
    
    public class LoginModel implements LoginModelInterface , ResponsReceiver<JSONObject>{
        private static String KEY_ACCOUNT = "userPhone";
        private  static String KEY_PASSWORD = "userPassword";
        private static String TYPE_LOGIN  = "LOGIN";
        private static String TYPE_REGIST = "REGIST";
        private Context context;
        public LoginModel(){
            
        }
       public  LoginModel(Context context){
            this.context = context;
        }
        @Override
        public void setOnLoginListener(OnLoginListener onLoginListener) {
            this.onLoginListener = onLoginListener;
        }
        private OnLoginListener onLoginListener;
        @Override
        public int doLogin(String account, String passWord) {
            HashMap<String,String> loginMap = new HashMap<String,String>();
            loginMap.put(KEY_ACCOUNT,account);
            loginMap.put(KEY_PASSWORD, passWord);
            MiddleNetProxy.getInstance().postJsonRequest(TempURL.host+"/User/login",this,loginMap,null,false);
            return 0;
        }
    
        @Override
        public int doRegist(String account, String passWord) {
            HashMap<String,String> registMap = new HashMap<String,String>();
            System.out.println("账号是"+account);
            registMap.put(KEY_ACCOUNT,account);
            registMap.put(KEY_PASSWORD,passWord);
            MiddleNetProxy.getInstance().postJsonRequest(TempURL.host+"/User/addUser",this,registMap,null,false);
            return 0;
        }
    
    
        @Override
        public void handlerResponse(int stCode, JSONObject response, String errMsg) {
    
            if(response==null)return;
            System.out.println("result="+response.toString());
            //根据返回的协议进行分发
            try {
                String type = response.getString(TYPE);
                if(TYPE_LOGIN.equalsIgnoreCase(type)){
                    String msg = response.getString(MSG);
                    String info = response.getString(INFO);
                    if(MSG_OK.equalsIgnoreCase(msg)){
                        if(onLoginListener!=null){
                            onLoginListener.loginSuccess();
                        }
                    }else if(MSG_ERROR.equalsIgnoreCase(msg)){
                        if(onLoginListener!=null){
                            onLoginListener.loginFailed(info);
                        }
                    }
                }else if(TYPE_REGIST.equalsIgnoreCase(type)){
                    String msg = response.getString(MSG);
                    String info = response.getString(INFO);
                    if(MSG_OK.equalsIgnoreCase(msg)){
                        if(onLoginListener!=null){
                            onLoginListener.regustSuccess();
                        }
                        }else if(MSG_ERROR.equalsIgnoreCase(msg)){
                        if(onLoginListener!=null){
                            onLoginListener.registFailed(info);
                        }
                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
    
        }
    }
    
    //网络请求中介,用于传递请求,管理请求队列

    package proxy;
    
    
    import net.JsonRequest;
    import net.Request;
    import net.RequestQueue;
    import net.ResponseDelivery;
    
    import org.json.JSONObject;
    
    import java.util.Map;
    
    /**
     * Created by Administrator on 2017/4/30.
     */
    
    public class MiddleNetProxy {
        public static MiddleNetProxy instance;
        private static RequestQueue mQueue = new RequestQueue();
        MiddleNetProxy(){
            mQueue.start();
        }
        public static  synchronized  MiddleNetProxy getInstance(){
            if(instance==null){
                instance = new MiddleNetProxy();
            }
            return instance;
        }
        public static void postJsonRequest(String url, final ResponsReceiver receiver,Map<String,String> body,Map<String,String>  header,boolean isUseCase){
            JsonRequest request = new JsonRequest(Request.HttpMethod.POST, url, new Request.RequestListener<JSONObject>() {
                @Override
                public void onComplete(int stCode, JSONObject response, String errMsg) {
                        if(receiver!=null){
                            receiver.handlerResponse(stCode,response,errMsg);
                        }
                }
            });
            request.setmShouldCache(isUseCase);
            if(header!=null)
            request.setmHeads(header);
            if(body!=null){
                request.setmBodyParams(body);
            }
            mQueue.addRequest(request);
        }
    
    
    }
    

    //model请求网络完成后的回调,网络中介完成请求后,通过responseReveive传递给model

    public interface ResponsReceiver<T> {
        void handlerResponse(int stCode,T response, String errMsg);
    }
    
    //onLoginListener获得present引用,因为present中实现了该接口,所以可以直接在model里面使用onLoginListener来调用present的视图设置的函数

    public interface OnLoginListener {
        void loginSuccess();
        void loginFailed(String errorMessage);
        void registFailed(String errorMessage);
        void regustSuccess();
    }
    
    这是最近自己结合两者设置的一个框架,后续有时间可能还会慢慢解耦,有意见请大家提出来~~~~




    展开全文
  • 但是, 设计框架将遵循windows版飞鸽传书的协议框架.数据包格式:版本号:包编号:用户名:机器名:命令字:附加信息如 1:2067943:liu :d14:32:hello以上是一个发送消息的数据包格式,其中32是标示的发消息...
  • WCF 基础框架

    2019-10-08 08:58:21
    1,契约:契约一语个服务公共接口一部分,一个服务契约定义了服务端公开方法,使用传递协议,可访问地址,传输消息格式等内容,主要包括数据契约,消息契约,服务契约等。 2,服务运行:定义了服务在...
  • # HTTP项目实战- 深入理解HTTP协议- 模拟后台服务程序基本流程和大致框架- 每一个...V02-解析传入http协议- 根据http协议格式,逐行读取信息- 按行读取后信息,需要进行拆解,# 推荐书籍- 日本人写 “图解Htt...
  • Unity3d实战之Unity3d网络游戏实战篇(9):协议 ... 一套通用服务端框架要支持不同游戏所使用各种协议格式。所谓协议就是通信规则,例如:如果发送端直接发送一串数值数据给接收端,接收端并不...
  • 在网络中,协议都是用来通信的,这就需要通信的格式,就像大家写信一样,必须按照信封提供的格式写,比如说收件人地址、姓名、邮编等等的,这是硬性规定,看见这个格式,OK 邮件就认为合乎我的规定,可以发送了。...
  • 1, HDFS 文件操作 ...文件命令的格式: hadoop fs -cmd &lt;args&gt; URI:scheme://authority/path scheme类似于一个协议,可以是 file 或者 hdfs authori...
  • 我觉得这本书写确实不错,堪称经典,市面上这样的书实在太少了,所以在这里发布下,供大家共享。本书从编程技术、项目实践以及软件工程角度出发,如果大家想学习基础语法部分,建立去下载别书籍。当然这本书也...
  • 我觉得这本书写确实不错,堪称经典,市面上这样的书实在太少了,所以在这里发布下,供大家共享。本书从编程技术、项目实践以及软件工程角度出发,如果大家想学习基础语法部分,建立去下载别书籍。当然这本书也...
  • 我觉得这本书写确实不错,堪称经典,市面上这样的书实在太少了,所以在这里发布下,供大家共享。本书从编程技术、项目实践以及软件工程角度出发,如果大家想学习基础语法部分,建立去下载别书籍。当然这本书也...
  • 我觉得这本书写确实不错,堪称经典,市面上这样的书实在太少了,所以在这里发布下,供大家共享。本书从编程技术、项目实践以及软件工程角度出发,如果大家想学习基础语法部分,建立去下载别书籍。当然这本书也...
  • 10.3.1 Internet文本信件的格式标准——RFC 822 290 10.3.2 信件的头部 291 10.3.3 构造和分析符合RFC 822标准的电子信件 296 10.4 MIME编码解码与发送附件 296 10.4.1 MIME概述 296 10.4.2 MIME定义的新的信...
  • 中内容主要集中在大多数企业常见问题之上,如安装和升级到oracle database 11g数据库软件、创建数据库、导出和导入数据、数据库备份与恢复、性能调优,等等。  本书还提供了dba完成本职工作必备基本uniix...
  •  本书适合linux开发人员、移动设备开发人员、android系统框架层和底层开发人员、有意图深入学习android人员、以及从事手机研发读者阅读 作译者  韩超 中国大陆地区资深工程师,也是嵌入式Linux相关技术在...
  • Web Service是一项基于XML分布式软件实现技术,以SOAP协议作为网络通信协议,以XML文档作为数据交换格式,允许不同平台、不同语言应用程序之间相互调用。 对于Java,已经由大量开源框架来实现Web Service,...
  • 书的目录 序(一) 序(二) 编者的话 第1章 操作系统概述 1 1.1 计算机系统概观 2 1.1.1 计算机的发展与分类 2 1.1.2 计算机系统 3 1.2 操作系统的概念 6 1.2.1 操作系统的地位 6 1.2.2 操作...
  • 1.2 IPTV系统结构及关键技术 1.2.1 IPTV业务平台 1.2.2 IP承载网络 1.2.3 用户接收终端 1.3 IPTV相关标准 1.3.1 总体框架标准 1.3.2 音视频压缩编码标准 1.3.3 流媒体文件格式 1.3.4 流媒体传输...
  • 整个系列文章大概有 15 篇左右,从我是如何成为一个前端工程师,到各种前端框架的知识。 在线阅读地址:http://ued.party/ 关注我微信公众号(扫描下面二维码或搜索 Phodal),回复书籍,可下载电子书版本 ...
  • 16.1 通用查询组件的创建 16.2 通用报表模块的制作 第17章 通用基础数据维护模块的设计 17.1 界面设计 17.2 代码实现 17.2.1 以目录树的格式显示部门档案数据 17.2.2 利用目录树导航数据 17.2.3 利用目录树操作数据 ...
  • 3.2.1 从糟糕数据格式中读取数据 34 3.2.2 从多个文件中读取数据 36 3.3 附言 42 3.4 其他格式 43 3.5 小结 45 第4章 纯文本中潜在噪音数据 46 4.1 使用哪种纯文本编码? 46 4.2 猜测文本编码格式 50 ...
  • iPhone开发秘籍(第2版)--详细书签版

    热门讨论 2012-12-11 13:42:25
     iPhone开发重量级参考  揭示官方文档未详述细节  代码示例清晰易懂 内容简介  《iphone开发秘籍(第2版)》提供了关于iphone sdk以及iphone开发全面信息,对iphone sdk中各种组件做了深入浅出介绍,...
  • L6.4 Qt 5 SVG格式图片显示方法:概念解析 246 XML 246 第7章 Qt 5图形视图框架 247 7.1 图形视图体系结构 247 7.1.1 Graphics View特点 247 7.1.2 Graphics View三元素 248 7.1.3 GraphicsView坐标系统 249 ...
  • 争论的内容十分广泛,从URL的格式到系统结构,从扩展性到界面开发,如果有时间的话,我尽量将其中部分内容翻译过来,还是很精彩的。(TSS上很多的讨论都非常精彩,如果英文好的话,建议经常上去看看,国外的牛人就是...
  • 5.3.2 使用格式String资源 80 5.3.3 使用String数组 81 5.3.4 使用颜色 82 5.3.5 使用尺寸 82 5.3.6 使用简单Drawable资源 83 5.3.7 使用图像 84 5.3.8 使用动画 88 5.3.9 使用菜单 89 5.3.10...
  • 实例005——使用C++实现格式化数据IO 实例006——实现数字金额中文大写转换 实例007——将十进制数转换为二进制输出 实例008——产生随机数 实例009——实现排序操作 实例010——使用Windows API创建程序...
  • 实例005——使用C++实现格式化数据IO 实例006——实现数字金额中文大写转换 实例007——将十进制数转换为二进制输出 实例008——产生随机数 实例009——实现排序操作 实例010——使用Windows API创建...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 197
精华内容 78
关键字:

框架协议书的格式