熊猫儿 发表于 2016-8-30 15:01

我在之前的一篇博客:android 不能在子线程中更新ui的讨论和分析 中分析了 Activity 的创建过程,感兴趣的可以去看看,在博客中分析到 startActivity 方法调用到了 Instrumentation 的 execStartActivity 方法, execStartActivity 方法又会调用 ActivityManagerNative.getDefault().startActivity 方法,最后调用到了 ActivityManagerService 中,但是当时并没有很明白为什么会调用到 AMS 中,所以这里根据上面的 uml 图补充说明一下。其实不光是 Instrumentation 类会调用到 ActivityManagerNative.getDefault() 方法,ActivityManager 中的很多方法都调用到了 ActivityManagerNative.getDefault(),比如 moveTaskToFront 方法:public void moveTaskToFront(int taskId, int flags, Bundle options) {    try {      ActivityManagerNative.getDefault().moveTaskToFront(taskId, flags, options);    } catch (RemoteException e) {      // System dead, we will be dead too soon!    }}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
和 getRunningServices 方法等等等:public List<RunningServiceInfo> getRunningServices(int maxNum)      throws SecurityException {    try {      return ActivityManagerNative.getDefault()                .getServices(maxNum, 0);    } catch (RemoteException e) {      // System dead, we will be dead too soon!      return null;    }}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
直接将函数调用转给了 ActivityManagerNative.getDefault() 方法,看看 getDefault() 函数:public abstract class ActivityManagerNative extends Binder implements IActivityManager{    /**   * Cast a Binder object into an activity manager interface, generating   * a proxy if needed.   */    static public IActivityManager asInterface(IBinder obj) {      if (obj == null) {            return null;      }      IActivityManager in =            (IActivityManager)obj.queryLocalInterface(descriptor);      if (in != null) {            return in;      }      return new ActivityManagerProxy(obj);    }...    static public IActivityManager getDefault() {      return gDefault.get();    }...    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {      protected IActivityManager create() {            IBinder b = ServiceManager.getService("activity");            if (false) {                Log.v("ActivityManager", "default service binder = " + b);            }            IActivityManager am = asInterface(b);            if (false) {                Log.v("ActivityManager", "default service = " + am);            }            return am;      }    };...}

熊猫儿 发表于 2016-8-30 15:07

getDefault 函数通过一个 Singleton 对象对外提供, ServiceManager.getService(“activity”) 返回的是 ActivityManagerService 的 Binder 对象,我们在看看 asInterface 函数,如果 queryLocalInterface 方法返回的是 null ,那么就会去创建一个 ActivityManagerProxy 对象,并且将 AMS 这个 Binder 对象作为参数传递给 ActivityManagerProxy 对象,来简单看看 ActivityManagerProxy 的代码:class ActivityManagerProxy implements IActivityManager{    public ActivityManagerProxy(IBinder remote)    {      mRemote = remote;    }    public IBinder asBinder()    {      return mRemote;    }    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,            String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {      Parcel data = Parcel.obtain();      Parcel reply = Parcel.obtain();      data.writeInterfaceToken(IActivityManager.descriptor);      ...      mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);      reply.readException();      ...    }...}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
[*]19
[*]20
[*]21
[*]22
[*]23
[*]24
[*]25

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
[*]19
[*]20
[*]21
[*]22
[*]23
[*]24
[*]25
看了这里的代码之后就一目了然了,代理对象的函数比如 startActivity 方法最终调用到的还是 AMS 中,ActivityManagerProxy 的作用只是作为代理而已。调用到 AMS 的后续步骤可以回到博客: android 不能在子线程中更新ui的讨论和分析 去看看,这里就重复了。
  还有几点需要在这里特殊说明一下:
[*]第一点:为什么 IActivityManager 需要实现 IInterface 接口,或者为什么 ActivityManagerProxy 需要继承 IInterface 接口的行为
我们看看 IInterface 接口的定义:

/** * Base class for Binder interfaces.When defining a new interface, * you must derive it from IInterface. */public interface IInterface{    /**   * Retrieve the Binder object associated with this interface.   * You must use this instead of a plain cast, so that proxy objects   * can return the correct result.   */    public IBinder asBinder();}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
有一个 asBinder 的方法,而 ActivityManagerProxy 的 asBinder 方法实现在上面已经贴出代码了,所以说 ActivityManagerProxy 中的 asBinder 函数是用来返回 AMS 这个 Binder 对象的;http://blog.csdn.net/self_study/article/details/51628486

熊猫儿 发表于 2016-8-31 14:25

第二点,继承 IBinder 和 Binder 的作用我们知道 AMS 是由 SystemServer 来启动的,它是运行在另一个独立进程中的(这点和 WindowManagerService 类似,对 WMS 感兴趣的可以看看我的上篇博客: java/android 设计模式学习笔记(8)—桥接模式),而 ActivityManagerProxy 是运行于当前进程当中的,此时必须要用到跨进程的通信,继承自 IInterface ,IBinder 接口和 Binder 类也是必然的(关于 IPC 通信,感兴趣的可以去看看我的博客:android IPC通信(下)-AIDL)。到这里,如果对 AIDL 熟悉的童鞋,就应该发现了其实这个 ActivityManagerProxy 和 ActivityManagerService 类就相当于我们写了一个 aidl 文件之后,系统为我们自动生成文件中的 Proxy 类和 Stub 类,所以说 aidl 就是一个使用远程代理模式非常实际的例子。第三点,asInterface 方法的注释 “Cast a Binder object into an activity manager interface, generating a proxy if needed”,所以 if needed 是指的什么情况呢?上面讲到 AIDL 文件生成的类中会自动生成两个类,Proxy 类和 Stub 类,对应的是 ActivityManagerProxy 和 ActivityManagerService 类,AMS 的初始化是在 SystemServer 进程中,所以 ActivityManagerNative 构造函数是在 SystemServer 进程中调用:
public ActivityManagerNative() {    attachInterface(this, descriptor);}
[*]1
[*]2
[*]3

[*]1
[*]2
[*]3
调用到 attachInterface 方法:public void attachInterface(IInterface owner, String descriptor) {    mOwner = owner;    mDescriptor = descriptor;}
[*]1
[*]2
[*]3
[*]4

[*]1
[*]2
[*]3
[*]4
而第二点中 gDefault 对象的 create 函数是在应用进程中调用的,这是两个不同的进程,所以我们再来看看 asInterface 函数:static public IActivityManager asInterface(IBinder obj) {    if (obj == null) {      return null;    }    IActivityManager in =      (IActivityManager)obj.queryLocalInterface(descriptor);    if (in != null) {      return in;    }    return new ActivityManagerProxy(obj);}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
然后是 queryLocalInterface 函数:public IInterface queryLocalInterface(String descriptor) {    if (mDescriptor.equals(descriptor)) {      return mOwner;    }    return null;}

熊猫儿 发表于 2016-8-31 14:25

所以最终这个函数是返回 null 的,也就是说跨进程调用的时候,会 new 一个 ActivityManagerProxy 对象。示例与源码  看了上面的通用代码和 Android 源码的 AMS 机制之后,代理模式应该已经很清楚了,但是上面用到的都是静态代理,都是在编译阶段生成的 class 文件,所以这里以一个动态+保护代理模式的 demo 为例:动态+保护代理  先看看它的 uml 类图:
  http://img.blog.csdn.net/20160723204030779
这里我们用到了 InvocationHandler 这个类,这是 Java 为我们提供的一个便捷动态代理接口,作用就是用来在运行时动态生成代理对象,在这里就不详细介绍了,感兴趣的可以去查阅相关资料(http://paddy-w.iteye.com/blog/841798)。其次是保护代理,这里就以 ProxyA 和 ProxyB 两个代理类为例,一个只能调用 operationA 方法,另一个只能调用 operationB 方法。首先来看看 Subject 和 RealSubject 类:
Subject.classpublic interface Subject {    String operationA();    String operationB();}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
http://static.blog.csdn.net/images/save_snippets.png

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
RealSubjct.classpublic class RealSubject implements Subject{    @Override    public String operationA() {      return "this is operationA";    }    @Override    public String operationB() {      return "this is operationB";    }}

熊猫儿 发表于 2016-8-31 14:26

定义完了抽象主题类和真实主题类之后,开始构造代理类,首先是代理类的虚基类:
ISubjectProxy.classpublic abstract class ISubjectProxy implements InvocationHandler {    protected Subject subject;    public ISubjectProxy(Subject subject) {      this.subject = subject;    }}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
然后是 ProxyA 和 ProxyB 这两个代理子类:
ProxyA.classpublic class ProxyA extends ISubjectProxy{    public ProxyA(Subject subject) {      super(subject);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      if (method.getName().equals("operationB")){            throw new UnsupportedOperationException("ProxyA can't invoke operationB");      }else if (method.getName().equals("operationA")) {            return method.invoke(subject, args);      }      return null;    }}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
ProxyB.classpublic class ProxyB extends ISubjectProxy{    public ProxyB(Subject subject) {      super(subject);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      if (method.getName().equals("operationA")){            throw new UnsupportedOperationException("ProxyB can't invoke operationA");      } else if (method.getName().equals("operationB")) {            return method.invoke(subject, args);      }      return null;    }}

熊猫儿 发表于 2016-8-31 14:27

最后是 Client 的代码:Subject subject = new RealSubject();ISubjectProxy proxy = null;switch (v.getId()) {    case R.id.proxy_a:      proxy = new ProxyA(subject);      break;    case R.id.proxy_b:      proxy = new ProxyB(subject);      break;}Subject sub = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(),      subject.getClass().getInterfaces(), proxy);try {    Log.e("Shawn", sub.operationA());}catch (UnsupportedOperationException e){    Log.e("Shawn", e.getMessage());}try {    Log.e("Shawn", sub.operationB());}catch (UnsupportedOperationException e){    Log.e("Shawn", e.getMessage());}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
[*]19
[*]20
[*]21
[*]22

[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
[*]19
[*]20
[*]21
[*]22
结果:com.android.proxypattern E/Shawn: this is operationAcom.android.proxypattern E/Shawn: ProxyA can't invoke operationBcom.android.proxypattern E/Shawn: ProxyB can't invoke operationAcom.android.proxypattern E/Shawn: this is operationB
[*]1
[*]2
[*]3
[*]4

[*]1
[*]2
[*]3
[*]4
代码很简单,第一点是使用 InvocationHandler 实现了动态代理,第二点是根据 method 的名字实现了保护代理。
  这里只总结了保护代理,虚拟代理这里简单举个例子: moduleA 为 modleB 的 lib,所以如果在 moduleA 中需要用到 moduleB 实现的对象,就可以使用代理模式,具体步骤是在 moduleA 中定义接口,moduleB 去实现该接口,moduleA 中定义一个代理对象并提供一些默认操作,当 moduleB 的相关模块初始化之后,将该对象设置到 moduleA 的代理对象中以替代原来的默认实现,之后代理对象就能成功调用 moduleB 中定义的行为了,而且也实现了延迟加载。远程代理和其他的代理模式大家去网上查阅一下相关资料,万变不离其宗,道理是一样的。总结

熊猫儿 发表于 2016-8-31 14:28




[*]优点:

[*]代理作为调用着和真实对象的中间层,降低了模块间和系统的耦合性;
[*]可以以一个小对象代理一个大对象,达到优化系统提高运行速度的目的;
[*]提供 RealSubject 的权限管理;
[*]容易扩展,RealSubject 和 ProxySubject 都接口化了,RealSubject更改业务后只要接口不变,ProxySubject 可以不做任何修改。
[*]缺点:

[*]调用者和真实对象多了一个中间层,对象的创建,函数调用使用的反射等都增加调用响应的时间;
[*]设计模式的通病:类的增加,不过这点也不严重。

适配器 VS 装饰者 VS 桥接 VS 代理 VS 外观  这几个都是结构型设计模式,他们有些类似,在实际使用过程中也容易搞混,我们在这就给他们做一个对比:适配器模式  适配器模式和其他三个设计模式一般不容易搞混,它的作用是将原来不兼容的两个类融合在一起,uml 图也和其他的差别很大。
  uml 类图:
  http://img.blog.csdn.net/20160611183536884

熊猫儿 发表于 2016-8-31 14:30

装饰者模式  装饰者模式结构上类似于代理模式,但是和代理模式的目的是不一样的,装饰者是用来动态地给一个对象添加一些额外的职责,装饰者模式为对象加上行为,而代理则是控制访问。
  uml 类图:
  http://img.blog.csdn.net/20160611183616916桥接模式  桥接模式的目的是为了将抽象部分与实现部分分离,使他们都可以独立地进行变化,所以说他们两个部分是独立的,没有实现自同一个接口,这是桥接模式与代理模式,装饰者模式的区别。
  uml 类图:
  http://img.blog.csdn.net/20160611184247832

熊猫儿 发表于 2016-8-31 14:32

代理模式  代理模式为另一个对象提供代表,以便控制客户对对象的访问,管理的方式有很多种,比如远程代理和虚拟代理等,这个在上面有,这里就不说了,而装饰者模式则是为了扩展对象。
  uml 类图:
  http://img.blog.csdn.net/20160710102346100外观模式  外观模式提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
  适配器模式将一个或多个类接口变成客户端所期望的一个接口,虽然大多数资料所采用的例子中适配器只适配一个类,但是你可以适配许多类来提供一个接口让客户端访问;类似的,外观模式 也可以只针对一个拥有复杂接口的类提供简化的接口,两种模式的差异,不在于他们“包装”了几个类,而是在于它们的意图。适配器模式 的意图是,“改变”接口符合客户的期望;而外观模式的意图是,提供子系统的一个简化接口。
  uml类图:
  http://img.blog.csdn.net/20160717170502406源码下载  https://github.com/zhaozepeng/Design-Patterns/tree/master/ProxyPattern引用http://blog.csdn.net/jason0539/article/details/22974405
https://en.wikipedia.org/wiki/Proxy_pattern
http://blog.csdn.net/l2show/article/details/46992495
http://paddy-w.iteye.com/blog/841798

熊猫儿 发表于 2016-9-1 16:51

java/android 设计模式学习笔记(10)---建造者模式
标签: 设计模式androidjava
2016-06-19 21:00 6347人阅读 评论(1) 收藏 举报

http://static.blog.csdn.net/images/category_icon.jpg 分类:
Android(67) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg Java(22) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg Android/Java 设计模式(17) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg

版权声明:转载请标明出处http://blog.csdn.net/self_study,对技术感兴趣的同鞋加群544645972一起交流

目录(?)[+]

  这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离。Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。一个复杂的对象有大量的组成部分,比如汽车它有车轮、方向盘、发动机、以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过程无疑会复杂,对于这种情况,为了实现在构建过程中对外部隐藏具体细节,就可以使用 Builder 模式将部件和组装过程分离,使得构建过程和部件都可以自由扩展,同时也能够将两者之间的耦合降到最低。
  转载请注明出处:http://blog.csdn.net/self_study/article/details/51707029。
  PS:对技术感兴趣的同鞋加群544645972一起交流。设计模式总目录  java/android 设计模式学习笔记目录特点  将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。Builder 模式适用的使用场景:
[*]相同的方法,不同的执行顺序,产生不同的事件结果;
[*]多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时;
[*]产品类非常复杂,或者产品类中的调用顺序不同产生不同的作用,这个时候使用建造者模式非常适合;
[*]当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时。
  在实际开发过程中,Builder 模式可以使用工厂模式或者任一其他创建型模式去生成自己的指定组件,Builder 模式也是实现 fluent interface 一种非常好的方法。


页: 12 13 14 15 16 17 18 19 20 21 [22] 23 24 25 26 27 28 29 30 31
查看完整版本: 【Android的一些重要知识6。。。。】