• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android源码装饰模式---ContextWrapper

Android源码装饰模式---ContextWrapper

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了contextwrapper,android源码设计模式,android源码,android源码下载,android源码网站等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android源码装饰模式---ContextWrapper


如果说Android源码中哪个地方装饰模式应用的最明显的话,那肯定是非ContextWrapper莫属了,ContextWrapper是一个透明的经典的装饰模式。本文将通过装饰器模式分析Context源码结构。本文基于的Android源码是(android 5.0.0)。首先先介绍一下装饰模式。

装饰模式

意图

装饰模式动态地给对象添加额外的职责,就添加功能来说,它比子类的方式更加灵活。

UML图

decorator

简单代码

class Component{
    public void operate1(){
        //do operate1
        System.out.println("operate1");
    }
}

class ComponentDecorator extends Component{
    private Component mComponent;
    public ComponentDecorator(Component component){
        mComponent = component;
    }

    public void operate1(){
        // 添加相关的职责
        System.out.println("print before");
        mComponent.operate1();
    }
}

class ComponentChild{
    public void operate1(){
        //do operate1
        System.out.println("child operate1");
    }
}

public static void main(String [] args){
    ComponentChild component = new ComponentChild();
    ComponentDecorator decorator = new ComponnentDecorator(component);
    decorator.operate1();
}

上面的代码就简单实现了装饰模式,通过把被装饰的对象作为装饰器的成员变量,当调用装饰器的操作的时候,装饰器还是会调用被装饰对象的操作,但是装饰器可以给对应的操作添加相关功能。装饰器透明的实现就是跟被装饰对象的接口一致,不添加新的接口,但是现在更多的实现方式是半透明的。装饰模式与子类实现方式比,它能够装饰被装饰对象的各种子类,甚至可以装饰装饰器对象(装饰器之间互相装饰),这样比子类化添加功能更加灵活。如果用子类的方式,将会导致非常多的子类。

ContextWrapper

下面介绍一下Android源码中装饰器的使用:ContextWrapper(装饰器有个别名Wrapper)。先看UML图。

此处输入图片的描述

Context

Context是一个全局应用环境接口,具体的实现由Android系统完成。它能访问应用资源,并且能够启动Activity,Service,接收broadcast。

它是一个抽象类,里面包含了各种方法的声明,应该将它作为一个接口类来看待。

ContextWrapper

这是一个Context的包装器,里面包含了一个mBase,ContextWrapper就是包装了mBase。而

ContextThemeWrapper, Activity, Application, Service, ReceiverRestrictedContext

ContextThemeWrapper这个是包含主题的装饰器,而Activity是它的子类。Application, Service, ReceiverRestrictedContext都是ContextWrapper的子类。每一个应用都会有一个Application。Android源码中已经有的Application有EmailApplication,LauncherApplication, Browser等等。

ContextImpl

这个是真正实现Context的类,Context是为应用环境类,它包含了跟环境相关的各种操作:getResource(资源管理,包含了getAssets,layout, string,drawable等等), getPackageManager(包管理器), getContentResolver(用于获取内容模型,比如访问ContentProvider), startActivity(启动Activity), ***Service(包含一系列Service相关操作,start,bind,unbind,stop), registerBroadcast/unregisterBroadcast/sendBroadcast(Broadcast相关)

这里简单介绍一下这几个关键方法的实现方式

getResource

这是获取资源的接口,得到Resource对象。ContextImpl里面有个mResource成员变量,android里面由mResource去读取资源。mResource由ResourceManager生成。现在很多Android资源动态加载是直接通过下面这种方式实现的。

AssetManager assets = AssetManager.class.newInstance();
try{
    Method method = AssetManager.class.getMethod("addAssetPath",String.class);
    method.invoke(assets,dexPath); //dexPath 表示动态dex包路径
}catch(Exception e){
    e.printStackTrace
}
r = new Resources(assets,getResources.getDisplayMetrics(),getResources.getConfiguration());

不过assets的addAssetPath是一个隐藏函数,需要通过反射去调用。

其实Android的资源框架大致就是如下过程:
- 根据layout,values,drawable等生成对应的ID,保存在R.id文件下面,而Android自带的资源在com.android.R.id里面。assets不会赋予id。
- Android用不同的资源目录后缀来适配不同的语言环境,屏幕大小,比如说drawable-en-w360。Android有一个对应的表,按照顺序匹配,对于drawable,本着不超过对应手机的参数的最大值来匹配。Android在打包的时候会将根据这些参数建立一个索引。
- 打包到resources.arsc文件中

运行的时候应用读取过程
- 先去掉跟手机环境完全不匹配的资源目录,比如现在是中文环境,则去掉en目录
- assets由AssetsManager来访问。其他对应的资源根据MMC表的顺序,按照索引表一个一个的维度来匹配,筛选,直到找到对应的资源。如果没有找到则抛出异常。

上述过程如果想要详细了解可参见罗升阳的博客

getPackageManager

返回包管理器,包管理器可以管理安装在系统中的应用程序包相关的各种信息。可以添加权限,可以查看对应包名的包信息,指定组件的组件信息,安装应用包等等。Android里面不同的应用程序报名绝对不同相同,包就对应了应用程序。所以从这里去理解PackageManager,他就是管理涉及到包管理(应用级相关的信息处理)的管理器。

getContentResolver

返回一个ContentResolver,ContentResolver是用于获取Content模型的,像ContentProvider就是通过ContentResolver来访问。

Activity操作

Context包含了Activity的启动操作,Activity的启动过程简单来说就是经过下面几个步骤:
1. mMainThread.instrumentation.execStartActivity
mMainThread是ActivityThread类型,它是管理着应用程序主线程的执行,像调度Activity,Broadcast等,instrumentation是一个Instrumentation类型,他是Android测试框架,在这里是为了监控Activity的活动,里面会有一个ActivityMonitor去监控被调用的Activity,用ActivityMonitor也可以等待一个指定的Activity启动。也可以阻止一个Activity的启动。
  通过这种方式启动Activity主要就是为了监控Activity的启动活动,在测试中将会大有用处。启动完后,也可以检查启动后的返回组件信息。
2. 在execStartActivity的函数中,进行完监控后,就是通过ActivityManagerNative来启动指定的Activity。

int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

看到Native其实就可以想到它是通过一种IPC机制来访问的了,具体是ActivityManagerProxy通过Binder进行IPC。
由Binder机制来访问ActivityManagerService,ActivityManagerService是进行Activity,Service, Broadcast管理的核心服务。 由ActivityManagerService.startActivity 会经过mStackSupervisor 以及 ActivityStack 进行相关处理 然后经过ApplicationThread, 最后到主线程的Handler(H)启动Activity
Service

Service除了包含startService,stopService,bindService,unbindService。Service最终也是在ActivityManagerService中管理,但是Service不同的,在ActivityManagerService里面管理的是是ActiveServices。但是最终控制Service的流程还是会到达Handler中

BroadCastReceiver

Context中有sendBroadcast, registerReceiver, unregisterReceiver。对应的都会通过ActivityManagerNative调用ActivityManagerService的相关函数。broadcastIntent是处理sendBroadcast的, ActivityManagerService中也有registerReceiver, unregisterReceiver。ActivityManagerService里面保存有一个Broadcast的ReceiverList,注册的时候将Receiver保存起来,发送广播的时候,根据保存的IntentFilter来找到对应Receiver,另外BroadCastReceiver还有sticky,是注册的时候如果符合已有的sticky广播,则立刻发送给Receiver。

 
对于Activity,Service启动流程,可以去参考罗升阳的博客,他的博客是基于早期的Android版本的,其实很多地方还是有很多变化了。所以如果想了解最新的源码,建议参考博客,自己去阅读源码。下面讨论一下Context这部分用装饰模式的优势

ContextW

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android源码装饰模式---ContextWrapper

相关文章

  • 2017-05-26Android之使用Bundle进行IPC,androidbundleipc
  • 2017-05-26[Android]Activity的生命周期
  • 2017-05-26第二个activity,启动第二个activity
  • 2017-05-26android设备使用usb串口传输数据,android设备usb串口
  • 2017-05-26[android] 数据的异步加载和图片保存,
  • 2017-05-26not allowed to access to crontab because of pam configuration
  • 2017-05-26PostgreSql数据库的神器 FDW
  • 2017-05-26Android中Fragment的两种创建方式,androidfragment
  • 2017-05-227.5.2 WebView和JavaScrip交互基础
  • 2017-05-26浅谈Windows下SVN在Android Studio中的配置和基本使用,svnandroid

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android取消EditText自动获取焦点默认行为,androidedittext
    • 声明和使用权限,声明使用权限
    • [Android]Activity的生命周期
    • unity安卓读写目录,unity安卓读写
    • 7.5.6 WebView处理网页返回的错误码信息
    • Solaris IPMP两种配置方法
    • android基础部分再学习--AIDL
    • Android常用命令行-ADB,android-adb
    • ACCESS 触发器delete table事件变量使用及连续删除
    • nginx 1.12 stream 日志设置

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有