Android中面向协议编程的深入浅出

http://blog.csdn.net/sk719887916/article/details skay编写

说起协议,现实生活中大家第一感觉会想到规则或者约定,确实协议的本意就是一种约束,每个人事物都遵守的准则或法则,如果拿生活中的列子来说 法律本身就是一种协议 每个人自然人去遵守,只有遵守了这个法则,执行法律的法院才会对遵守的人管辖有效,当然前提是你必须是在某个国家的法律之内,如果不是某个法律的协议范围之内,当然法院的执法者是无法对其他国家的自然人进行管理的,也就需要一个中间的桥接者进行沟通,比如目前的大使馆就是做这种协议转换的作用。而大使馆又是一个更高层次的协议。

面向协议

那对于编程语言来说协议的范围可以有多方面的解释,不同的语言对协议也有着不同的定义,但是他们的最终目的还是和上面说到的现实问题相一致的,就拿java语言来说 协议是什么,在从事java开发多年的人也未必听说过协议,但说起规则,大家都会想到java接口,确实interface是约束某种规则的,我们定义了某个功能的一些方法,让其他功能遵守了这个协议(java是实现这个接口),才能正常的实用起功能。java对于协议编程有我们熟知的面向接口编程一说,这只是对协议编程的一种细化,java中的接口更是对一种具体api的运用的编程,那么这样的接口编程其实未必是一种行为的协议编程,为什么这么讲呢 我们可以看看OC的中的协议编程。

OC的运用是由于iOS移动开发的兴起而的到广泛运用,然后oc也是一种面向对象语言,也拥有java一样的oop思想,而只不过和我的java的接口有所不同,oc中用了协议一词,它让某个类去遵守某个协议,这样也许更确切显示生活中的协议,OC协议中没有抽象类一说,只有一个单纯的@protocol来进行声明,但是他的实现类并不是我们java中的接口实现类,这里要明确一点OC语言每个类都有一个声明类和实现类,而OC的对于协议的实现类我们要和OC本身的语法要进行区分对待,协议用关直接在继承类(NSObject)后面 <协议名>即可,他的协议也有必须实现和选择实现两种

  1. @required:表示必须强制实现的方法
  2. @optional:表示可以有选择性的实现方法

JAVA中用abstract 来定义我们的可选规则和不可选规则,而java中真正的接口类不如说是协议,还不如说他是oc中的代理,于是协议和代理其实密切关联的。

  1. 面向切面

    说完了协议的概念和在编程语言中的定义,大家会想到面向切面编程,也就是从上面提到的面向接口编程一样,会问到面向协议,面向接口,面向切面,面向对象有啥区别。今天你就以本人的见解给大家梳理一遍

  2. 面向对象

    面向对象是把任何东西看成一个基本单元,大的基本单元包含小的基本单元,就是把一个整体的东西做到细化,从而是实现整体的组装。

  3. 面向接口

    面向接口狭义的定义就是对java的接口API的完美运用,编程者建议我们都用接口实现功能重组,其实也是基于面向对象语言的一种特性的多态的扩展,其实这种采用注入方式,或者我们Java1.5新增的注解其实也是对于接口的延生,那么面向接口一般用在小规模的编程中,如果放到整个编程架构,那么面向接口还是去无法完美说服力

  4. 面向切面

    提到面向切面其实也是对于面向接口的总结,他是将代码现实化,如果我们说道面向接口,大家第一感官就会想到java类的接口类,并不关心一个现实生活中的具体代表什么,那么面向切面来了,他是将我的事物分成一个个事物单元和事物组件,那么这个组件就可以担负起桥接单元的功能,而这个组件有一定的约束力哦,只有符合该组件的要求才能由他来连接,那么通俗的将我们并不关系某个组件由什么组成,我们也只要知道这个单元是符合这个组件的越束就行,就类似我们所说的热插拔,插座和插头的功能,而这种广泛运用在服务端比较多,著名的spring就利用面向切面思想,依赖我们需要的配置注入,其实也就延生客户端的面向协议编程诞生。

    面向协议

    那么面向协议该怎么做解释呢,在我们的移动端的开发中,我觉得用面向协议总结上面123点的结合一起比较合适,面向协议并不是只是对具体API的运用,也不是对某种局部功能的拆分细化,更不是对某种方法的抽象,也不是说某个功能我们要去完成必须去写一个dao,用daoIPML(javaweb端的常用做法),而是将我的某种规则(某种功能)去和具体调用和分离,也和具体实施者做分离,不管我具体的由谁去做这个规则的实施,但是这个规则是存在,而具体调用规则的人也灵活的,那么移动端的面向协议方可这么认为。

安卓面向协议编程

通看安卓源码我们可以看到谷歌工程师喜欢用xxxManger, xxxMangerImpl,XXXRoot, BaseXXX, 自我分析很久,也许这只是他们的编程习惯而已,更有可能安卓只是一个移动端操作系统,而某些组件更是唯一一组功能集合的管理者,因此以管理者命名的原因居多。在这里暂且不管原因,我们看他实现的整个过程中,所有的组件都是在我们的ActivityThred(以下简称AT)去做动态注入的,也就是说不管是viewRootImpL, ActivtiyManferImpl,都是在AT做实现类的注入,如果某些Manager需要上层调用,那么他会将此Manager绑定到我们的Context静态类中,因此我们在很对地方拿到上下文,就可以得到某些Manager的原因,然后这些manager并不是具体的实现类,都是由他们的IMPL去完成,如果我去做重写或者覆盖东西,其实context内部也利用外部重载进来的代码进行实现,我们就拿普通的onClick()事件来说,比如我在某个界面中给某个view注入单击事件

mView.setOnClickListener("我们自己定义的OnClickListener实现类");

我么看过这个listener后他也就是个接口源码如下

/**
* Interface definition for a callback to be invoked when a view is clicked.
* */
 public interface OnClickListener {
/**
 * Called when a view has been clicked.
 *
 * @param v The view that was clicked.
 */
void onClick(View v);
}

看到他会把我们的listener加入到ListenerInfo中用来一个TAG将事件和view做绑定,

 public void setOnClickListener(OnClickListener l) {
if (!isClickable()) {
    setClickable(true);
}
getListenerInfo().mOnClickListener = l;

}

这些其中的事件传递就不在做些说,那么他由我们的最底层的viewrootImpl(activity的消费事件最终也有viewrootIMpl来进行原始的调用)来进行处理最后回调到我的下面方法

public boolean callOnClick() {
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
    li.mOnClickListener.onClick(this);
    return true;
}
return false;

}

代码里的只是调用了OnClickListener的onClick()然后就会将我们代码实现的处理逻辑执行,这充分给我们的开发者有自我扩展的能力,不但不会影响源码的其他代码,而且还给了开发者有自己去实现的方式,这也只是一种面向协议的简单运用。

Mvp面向协议编程架构运用

mvp是一种架构模式,我们通常可以将安卓当中的视图和数据分离,采用presenter来进行管理,数据和模型是无法直接通信的,这和mvc的根本区别就是视图和模型无任何交集。

这里写图片描述

但是在庞大的安卓源码中可能并不是只是一个视图和数据模型的分离,也有可能是众多presenter的分离,这将会产生功能之间的mvp架构模式,rootPresener来管理众多的childPresenter, 那么这种面像协议的编程就来了 我们可以看看安卓某些某块的源码(ViewManger)

public interface ViewManager {

public void addView(View view, ViewGroup.LayoutParams params);

public void updateViewLayout(View view, ViewGroup.LayoutParams params);

public void removeView(View view)

}

其实也是一一个接口类我们的具体实现类如下ViewGroup去实现,看看其中的addView()的实现

 public void addView(View child, int index, LayoutParams params) {

   if (DBG) {
      System.out.println(this + " addView");
   }

  // addViewInner() will call child.requestLayout() when setting the new LayoutParams
  // therefore, we call requestLayout() on ourselves before, so that the child's   request
   // will be blocked at our level
   requestLayout();
   invalidate();
   addViewInner(child, index, params, false);

  }

但是具体的添加视图(addview)只是一个动作性方法,源码又提供了一个进行逻辑性的接口类(ViewParent) 源码部分:

  public interface ViewParent {

     public void requestLayout();

     public boolean isLayoutRequested();

     public void requestTransparentRegion(View child);

     public void invalidateChild(View child, Rect r);

     public ViewParent invalidateChildInParent(int[] location, Rect r);

     :::::::略

    public void bringChildToFront(View child);

    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);

    public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
    boolean immediate)
  }

两个抽象的接口都是由viewgroup去实现,而viewgroup是在viewroot在启动activtiy时候帮到我们的acitivty的,一次一连串的功能协议就走通了,接下来我们可以想想这种思想的好处,为何不直接调用呢,

面向协议编程好处

  1. 增加扩展功能,也更容易保障具体实现类代码的安全
  2. 增加新的传参方式(代码块)
  3. 更容易实现低耦合的思想
  4. 将具体的实现者进行和执行者分离

这里说个题外话,谷歌喜欢视图层运用Root, Child, 逻辑用Base Normal, 核心开放类用Manager,一般便于维护。这些类是无法修改的。其实只是一种编程的习惯,这和java jdk的命名习惯有很大区别的。

Android 面向协议编程 体会优雅编程之旅的更多相关文章

  1. python优雅编程之旅

    偶然的机会坐上了python的贼船,无奈只能一步步踏上王者之巅..... 参考博客地址:https://mp.weixin.qq.com/s/OZVT3iFrpFReqdYqVhUf6g 1.交换赋值 ...

  2. fir.im Weekly - 揭秘 iOS 面向协议编程

    本期 fir.im Weekly 重点推荐关于 iOS 面向协议编程相关文章,还有 iOS 多线程安全.Swift 进阶.Android MVVM 应用框架.Android 蓝牙实践等技术文章分享和工 ...

  3. Swift -POP( 面向协议编程)与OOP(面向对象编程)

    面向协议编程(Protocol Oriented Programming,简称POP),是Swift的一种编程范式,Apple于2015年WWDC提出的,如果大家看Swift的标准库,就会看到大量PO ...

  4. 为什么说swift是面向协议编程--草稿

    为什么说swift是面向协议编程 public protocol ReactiveCompatible { /// Extended type associatedtype CompatibleTyp ...

  5. 编程范式 --- 面向协议编程(Protocol Oriented Programming,简称POP)

    面向协议编程(Protocol Oriented Programming,简称POP) 是Swift的一种编程范式,Apple于2015年WWDC踢出 在Swift的标准库中,能见到大量POP的影子 ...

  6. Swift 学习笔记(面向协议编程)

    在Swift中协议不仅可以定义方法和属性,而且协议是可以扩展的,最关键的是,在协议的扩展中可以添加一些方法的默认实现,就是在协议的方法中可以实现一些逻辑,由于这个特性,Swift是可以面向协议进行编程 ...

  7. Android面向切面编程(AOP)(转)

    转自:https://www.jianshu.com/p/aa1112dbebc7 一.简述 1.AOP的概念 如果你用java做过后台开发,那么你一定知道AOP这个概念.如果不知道也无妨,套用百度百 ...

  8. (54)LINUX应用编程和网络编程之九Linux网络通信实践

    3.9.1.linux网络编程框架 3.9.1.1.网络是分层的 (1)OSI 7层模型(理论指导) (2)网络为什么要分层 (3)网络分层的具体表现 3.9.1.2.TCP/IP协议引入(网络分层实 ...

  9. Android开发学习之路--网络编程之xml、json

    一般网络数据通过http来get,post,那么其中的数据不可能杂乱无章,比如我要post一段数据,肯定是要有一定的格式,协议的.常用的就是xml和json了.在此先要搭建个简单的服务器吧,首先呢下载 ...

随机推荐

  1. Vue.js + Webpack

    vue.js Vue.js是一个构建数据驱动的 web 界面的库.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件 以上是Vue.js官方定义,故名思议,以数据驱动视 ...

  2. PLSQL(1)

      PLSQLl编程                       plsql是Oracle在标准的sql语言上的扩展 特点:可以在数据库中定义变量,常量,还可以使用条件语句和判断语句以及异常等   P ...

  3. Socket.io应用之联网拖拽游戏

    服务器端代码: const express=require('express'); const http=require('http'); const sio=require('socket.io') ...

  4. git报错:'fatal:remote origin already exists

    git报错:'fatal:remote origin already exists'怎么处理?附上git常用操作以及说明.   git添加远程库的时候有可能出现如下的错误, 怎么解决? 只要两步: 1 ...

  5. 一口一口吃掉Hibernate(七)——继承映射

    前几篇博文中讲到了常用的几种关联映射.其实hibernate中还有一种"省劲儿"的映射,那就是--"继承映射". 学了这么多的关系映射了,继承映射,从字面上也能 ...

  6. HTMLParser使用简介

    HTMLParser具有小巧,快速的优点,缺点是相关文档比较少(英文的也少),很多功能需要自己摸索.对于初学者还是要费一些功夫的,而一旦上手以后,会发现HTMLParser的结构设计很巧妙,非常实用, ...

  7. WPF ListBox/ListView/DataGrid 虚拟化时的滚动方式

    ListBox的滚动方式 分为像素滚动和列表项滚动 通过ListBox的附加属性ScrollViewer.CanContentScroll来设置.因此ListBox的默认模板中,含有ScrollVie ...

  8. day05 Servlet 开发和 ServletConfig 与 ServletContext 对象

    day05 Servlet 开发和 ServletConfig 与 ServletContext 对象 1. Servlet 开发入门 - hello world 2. Servlet 的调用过程和生 ...

  9. java中的final和volatile详解

    相比synchronized,final和volatile也是经常使用的关键字,下面聊一聊这两个关键字的使用和实现 1.使用 final使用: 修饰类表示该类为终态类,无法被继承 修饰方法表示该方法无 ...

  10. Java第5次实验提纲(Java图形界面编程)

    1. Swing与NetBeans 使用NetBeans编写简单界面.见GUI实验参考文件中的0.第06次实验(图形程序设计.事件处理与Swing).doc 题目1: Swing用户界面组件与事件处理 ...