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. 深入理解final关键字

    在了解了final关键字的基本用法之后,这一节我们来看一下final关键字容易混淆的地方. 1.类的final变量和普通变量有什么区别? 当用final作用于类的成员变量时,成员变量(注意是类的成员变 ...

  2. 关于一些基础的Java问题的解答(七)

    31. 反射的作用与原理 简单的来说,反射机制其实就是指程序在运行的时候能够获取自身的信息.如果知道一个类的名称或者它的一个实例对象, 就能把这个类的所有方法和变量的信息(方法名,变量名,方法,修饰符 ...

  3. swiper display:none 后 在显示 滑动问题

    一般这种问题  必须在本身元素  或者父元素  显示出来  然后调用swiper实例 或者只需加两行 observer:true, // 修改swiper自己或子元素时,自动初始化swiper obs ...

  4. 剑指架构师系列-持续集成之Maven+Nexus+Jenkins+git+Spring boot

    1.Nexus与Maven 先说一下这个Maven是什么呢?大家都知道,Java社区发展的非常强大,封装各种功能的Jar包满天飞,那么如何才能方便的引入我们项目,为我所用呢?答案就是Maven,只需要 ...

  5. 牛客网编程练习之PAT乙级(Basic Level):1041 说反话

    直接分隔取反即可 AC代码: import java.util.Scanner; /** * @author CC11001100 */ public class Main { public stat ...

  6. Go 语言变量作用域

    作用域为已声明标识符所表示的常量.类型.变量.函数或包在源代码中的作用范围. Go 语言中变量可以在三个地方声明: 函数内定义的变量称为局部变量 函数外定义的变量称为全局变量 函数定义中的变量称为形式 ...

  7. Python 3.3.2 round函数并非"四舍五入"

    对于一些貌似很简单常见的函数,最好还是去读一下Python文档,否则当你被某个BUG折磨得死去活来时,还不知根源所在.尤其是Python这种不断更新的语言.(python 2.7 的round和3.3 ...

  8. 将luarocks整合进openresty

    缘由 随着功能需求的深入, openresty领域的包已经不够用了, 需要lua领域本身累积的库, 也就是luarocks. 本文讲解了windows 10桌面和ubuntu server两套系统的方 ...

  9. Mac OS: How to keep network connection alive after sleep

    Do the following: Find out what the network interface is for your wifi. Mine is "en1" for ...

  10. Android Multimedia框架总结(十八)Camera2框架从Java层到C++层类关系

    Agenda: getSystemService(Context.CAMERA_SERVICE) CameraManager.getCameraIdList() ICameraService.aidl ...