Android源码中的抽象工厂---IPolicy

抽象工厂应用是很广的,在Android源码中,这个IPolicy就是一个简单的抽象工厂模式。下面分析一下IPolicy及其实现,以及创建的相关对象(源码基于5.0.0)。

抽象工厂

意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

UML类图

通过继承抽象工厂,可以产生不同的产品系列

代码示例

    abstract class AbsFactory{
        public abstract AbsProductA createProduct1();
        public abstract AbsProdcutB createProduct2();
    }

    abstract class AbsProductA{
    }
    abstract class AbsProductB{
    }
    class ProductA1 extends AbsProductA{
    }
    class ProductB1 extends AbsProductB{
        public void interactWithProductA(AbsProductA product){ //与ProductA关联
        }
    }

    class ConcreteFactory1 extends AbsFactory{
        private static ConcreteFactory instance = new ConcreteFactory();
        public ConcreteFactory getInstance(){
            return instance;
        }
        public AbsProductA createProductA(){
            return new ProductA1();
        }
        public AbsProdcutB createProductB(){
            return new ProductB1();
        }
    }

    public static void main(String[] args){
        ConcreteFactory instance = ConcreteFactory.
        AbsProductA product1 = instance.createProductA();
        AbsProductB product2 = instance.createProductB();
        product2.interactWithProductA(product1);
    }

抽象工厂就是创建一系列相互关联的对象,这样每一个抽象工厂的具体实现创建的对象都是相互关联的,而且可以是不同的产品系列,相当于从上层就设计好了一套产品规范。这里只是简单介绍了一下抽象工厂。如果想很好的理解可以参考设计模式:可复用面向对象软件的基础关于抽象工厂的介绍。下面介绍IPolicy。

IPolicy

IPolicy在com.android.internal.policy包下面。它是关于Android窗口,窗口管理,布局加载,以及事件回退Handler这一系列窗口相关产品的抽象工厂。先看IPolicy的UML类图。

UML图

IPolicy是产生窗口屏幕相关对象的抽象接口,在Android手机源码中,com.android.internal.policy.impl.Policy是它的唯一一个实现,按照源码中的注释所说的,是Policy是IPolicy的一个简单实现,用来生成对象集合。Policy创建一系列的Phone的窗口相关对象:PhoneWindow,PhoneLayoutInflater,PhoneWindowManager,PhoneFallbackEventHandler。从UML图就可以看出,IPolicy算是一个典型的抽象工厂,只不过在源码中只有一个具体的工厂实现。

另外Policy的实现还有一点特殊的地方,它使用static域将他需要创建的对象都预先load出来,也就是说当虚拟机加载Policy类的时候,就会加载它创建的对象的class。

相关对象介绍

下面分别介绍IPolicy创建的每个对象

PolicyManager

PolicyManager相当于是这个抽象工厂的客户端,它只有静态方法,他它的静态方法跟IPolicy的接口是相对应的。它内部包含了一个Policy对象,相当于是Policy的一个代理,对应的创建操作都会交给Policy去创建,比如说makeNewWindow方法的实现:

// The static methods to spawn new policy-specific objects
public static Window makeNewWindow(Context context) {
    return sPolicy.makeNewWindow(context);
}

Window与PhoneWindow

Window是Android中的窗口,每个Activity都会对应着一个Window,在Activity的attach方法中,就有Window的创建代码:

    final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, IVoiceInteractor voiceInteractor) {
        attachBaseContext(context);

        mFragments.attachActivity(this, mContainer, null);

        mWindow = PolicyManager.makeNewWindow(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        ...

attach方法是将Context,application等赋值给Activity,在Activiy启动的过程会调用。我们弹出的对话框(Dialog),里面也是有一个Window的。另外与Activity对应的还有启动窗口(Starting Window)。一个Window还可以有子Window。另外Android中还有一些其他的窗口还有输入法窗口,状态栏窗口,壁纸窗口。

窗口有一个专门的窗口管理服务WindowManagerService,在WindowManagerService中与每个Activity对应的为AppWindowToken,而AppWindowToken描述的是一组窗口(一组WindowState),对应于Activity中Context的各种窗口。

而手机中, Window的具体实现是PhoneWindow。PhoneWindow是对应着Android手机的Window实现。PhoneWindow里面包含了DecorView, DecorView包含了标题栏以及具体View(由setContentView设置)。它们之间的关系如下:

而真正直接关联Window与View的是WindowManager,由Window.setWindowManager设置。每个Window都会对应一个WindowManager。通过WindowManager的addView,updateViewLayout,removeView来添加,更新,移除Window中的View。

通过context.getSystemService(Context.WINDOW_SERVICE)可以获得WindowManager,这个就是Activity的mWindow的WindowManager,而WindowManager的具体实现是WindowManagerImpl,而WindowManagerImpl又会将Window的相关操作(addView, removeView)交给WindowManagerGlobal来实现。WindowManagerGlobal是一个单例模式,里面包含了一个ViewRootImpl列表(ArrayList),一个View列表, 一个WindowManager.LayoutParams列表,三个链表相互对应,表示一个View对应的LayoutParams和ViewRoot。WindowManagerGlobal获取了WindowManagerService的Binder接口IWindowManager。ViewRootImpl通过WindowManagerGlobal的IWindowManager获取WindowSession(Binder的Proxy),将ViewRootImpl的W(Binder对象)传给WindowManagerService,来与WindowManagerService相互通信。他们之间的UML图如下:

WindowManagerPolicy,PhoneWindowManager

这个WindowManagerPolicy不同于Window中介绍的WindownManager,Window中介绍的WindowManager是属于Window与View交互的管理,而WindowManagerPolicy则是更多地倾向于对Window屏幕的管理,比如说启动窗口就是由它创建的。也包括一个具体的屏幕管理,比如说获取屏幕显示的大小,屏幕旋转,屏幕设置等等。PhoneWindowManager是WindowManagerPolicy在手机规格下的实现。WindowManagerPolicy还有一个内部静态类WindowManagerPolicy.WindowState,它是由WindowManagerService管理的,从一个窗口开始添加就存在,到窗口移除就删除,是一个窗口的状态接口,可以获得当前窗口所属的进程,包名,当前的Frame

LayoutInflater,PhoneLayoutInflater

LayoutInflater应该都比较熟悉,它是Android中用于XML布局加载的类,它是一个抽象类,PhoneLayoutInflater是它在Android手机上面的实现。PhoneLayoutInflater中主要是实现了onCreateView方法和cloneInContext方法。

FallbackEventHandler,PhoneFallbackEventHandler

这个是回退事件Handler,主要是为了处理回退事件(Fallback)。

IPolicy抽象工厂的设计分析

如果只看IPolicy,PolicyManager,Policy的UML,你会发现其实这三个部分也像是一个策略模式的UML图。这部分里面本身也可以说是一种策略,一种创建的策略。但把IPolicy作为抽象工厂理解会更为合适,它负责生成一系列相关产品,却不用管产品的具体实现。

首先说说这四个产品之间的关系,Window是表示窗口,抽象的窗口管理,而WindowManagerPolicy是关于窗口屏幕的管理策略,LayoutInflater是XML解析器,将XML解析为Window中具体元素View,最后FallbackEventHandler是回退事件Handler,事件会作用在窗口上面。这四个产品在不同的产品簇的具体表现会是不一样的,但是他们又有相互之间的关联。用一个统一的创建接口,在使用这些接口的时候会更加方便。

就拿Phone的这四种产品实现来说,Phone的Window,以及WindowManagerPolicy自然是不同的,另外LayoutInflater也会有所不同,比如XML的View可能限制不一样,在PhoneLayoutInflater中会从包名前缀为”android.widget.”,”android.webkit.”,”android.app.”这三个来创建View。另外如果产品簇是TV的话,FallbackEventHandler处理可能是直接回退到上一个台,而Phone的话会是返回上一个操作。

用四个工厂方法实现

其实四种不同的产品(Window,WindowManagerPolicy,LayoutInflater,是XML解析器,将XML解析为Window中具体元素View,最后FallbackEventHandler),如果用四个工厂方法也肯定是可以的,但是会缺乏将本来应该有相互关联的产品拆分开了,抽象工厂一定程度上提高了它们之间的耦合性。

扩展优势分析

假如除了Phone外,又突然有了一种新的产品簇(比如说TV,智能手表,我暂时并没有调查这两种的实现方式),那么只需要创建一个对应Policy,以及对应的产品系列,然后将PolicyManager的IPolicy指向新产品簇的Policy就好了。

时间: 2024-10-12 09:01:49

Android源码中的抽象工厂---IPolicy的相关文章

访何红辉:谈谈Android源码中的设计模式

最近Android 6.0版本的源代码开放下载,刚好分析Android源码的技术书籍<Android源码设计模式解析与实战>上市,我们邀请到它的作者何红辉,来谈谈Android源码中的设计模式,以及近期Android开发中的一些热点话题. 受访嘉宾介绍: 何红辉(@MrSimp1e),前友盟Android工程师,活跃于国内各大技术社区,热爱开源,热爱技术,热爱分享.Android开源库 AndroidEventBus . Colorful 作者, 开发技术前线 站长,<Android源码

Android源码中的FLAG为何使用16进制

1.在阅读源码的时候经常发现有一些标志属性使用一些位操作来判断是否具有该标志,增加标志或者去除标志. 比如View.java中的 /** * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when * calling setFlags. */ private static final int NOT_FOCUSABLE = 0x00000000; /** * This view wants keystrokes. Us

为什么android源码中有的public方法,在官网会查不到并且我们也用不了?

比如,看这个: 在android开发官网上搜是搜不到这个方法的,我们也调用不了,为什么呢?这是因为我们只能调用到android Framework层给我们提供的api,而这个方法框架层不开放调用,所以自然我们就调用不到了.不过,我们可以通过反射的方式间接调用此类方法(详细见我上一篇博客). 附在线看android源代码网址:http://grepcode.com/project/repository.grepcode.com/java/ext/com.google.android/android

The Independent JPEG Group&#39;s JPEG software Android源码中 JPEG的ReadMe文件

The Independent JPEG Group's JPEG software========================================== README for release 6b of 27-Mar-1998==================================== This distribution contains the sixth public release of the Independent JPEGGroup's free JPEG

在Android源码中查找Java代码中native函数对应的C++实现

Android源码中很多关键代码都是C++实现的,java通过jni来调用,经常会看到java中这样的代码: static native Thread currentThread(); 如何根据方法名找到其对应的C++实现,有两个方法. 先来个java代码的示例VMThread.java: package java.lang; class VMThread { Thread thread; int vmData; VMThread(Thread t) { thread = t; } native

Eclipse与Android源码中ProGuard工具的使用

由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的理解和认识简要的做个笔记,有异议或者不解的,可以直接留言. 什么是ProGuard工具? ProGuard是android提供的一个免费的工具,它能够移除工程中一些没用的代码,或者使用语义上隐晦的名称来重命名代码中的类.字段和函数等,达到压缩.优化和混淆代码的功能.具体来说,使用ProGuard工具

Android 源码中的设计模式

最近看了一些android的源码,发现设计模式无处不在啊!感觉有点乱,于是决定要把设计模式好好梳理一下,于是有了这篇文章. 面向对象的六大原则 单一职责原则 所谓职责是指类变化的原因.如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责.而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因.通俗的说,即一个类只负责一项职责,将一组相关性很高的函数.数据封装到一个类中. 开闭原则 对于扩展是开放的,这意味着模块的行为是可以扩展的.当应用的需求改变时,我们可以对模块进行扩展,使其

android源码中修改wifi热点默认始终开启

在项目\frameworks\base\wifi\java\android\net\wifi\WifiStateMachine.java里面,有如下的代码,是设置wifi热点保持状态的:如下: private class HotspotAutoDisableObserver extends ContentObserver { public HotspotAutoDisableObserver(Handler handler) { super(handler); mContext.getConte

Android源码中中一种常见的struct使用方法

直接看例子: #include<iostream> #include<stdlib.h> using namespace std; struct Base{ int ba; int bb; void printB(){ cout<<"base print"<<endl; } }; struct A{ struct Base b; int aa; void printA(){ cout<<"A print"&