android study 16 about context

Author Avatar
Xzhah 8月 07, 2022
  • 在其它设备中阅读本文章

Background

装饰器模式

​ 在网上看到一个比较形象的比喻,装饰类可以比作一个画框,目标类比作一幅画。黄框可以有自己新增的功能,画框和画是相互独立的,不会耦合,画框可以动态的扩展画的功能(比如挂在墙上)。

举例:

​ 首先实现一个画的接口: interface Paint。然后实现它的实体类:ShitPaint implement Paint。然后需要创建一个Shape接口的抽象装饰类:PaintDecorator implemebt Paint,并且需要持有Pait的实现对象。最后创建实体装饰类RedPaintDecorator extends PaintDecorator ,新增自己的功能。

Context

​ android中context可以说是频繁出现,但是这个context到底是个什么呢?它是应用和系统的桥梁,是应用访问系统资源的接口,也可以认为是应用所持有的安卓王国凭证。

​ Context是安卓系统提供的一个抽象类,通过它可以访问系统资源,调用应用程序级操作,获取全局信息。有了Context,开发者才可以:弹出一个toast,启动一个Activity,获取程序布局文件,访问数据库。这些操作都需要和系统交互,java类只有在有了context类过后,才能成为组件,才有了组件的功能。

​ 涉及Context一般有两种用法:调用Context的方法,或者调用接口时需要Context参数。这些行为意味着需要访问系统相关资源。Context从何而来?来自AMS,AMS是系统级进程,他有系统级操作的能力。应用程序受AMS调控,在程序启动的过程中,AMS会把一个“凭证”跨进程通信传给应用。程序把这个凭证封装成Context,并提供一系列接口。这样的好处是,应用程序级的操作,都在系统的调控下进行,系统可以限制各种情景下的权限,同时防止恶意攻击。

​ Application类的context和Activity的context权利是不同的,生命周期也不一样。Activity开放给用户也只有部分有限的权利,开发者要获取Context也只能从Activity,Application等组件中获取。

Context家族

​ Context及其子类情况:最顶层是Context抽象类,定义了一系列与系统交互的接口。ContextWrapper是Context的子类,但是并不会直接实现Context的接口,而是把接口的实现托管给ContextImpl,ContextImpl是Context接口的实现者。AMS的凭证也在ContextImpl中,然后把ContextImpl赋值给ContextWrapper。这里就会用到装饰者模式。Application和Service继承自ContextWrapper,也就可以调用Context的接口。Activity更特殊,他有界面,所以需要一个主题。ContextThemeWrapper在ContextWrapper的基础上增加与主题相关的操作。Activity继承了ContextThemeWrapper。

​ 这样设计的优点:运用装饰者模式,向外屏蔽ContextImpl的内部逻辑,同时如果ContextImpl的内部实现改变了,也不会影响ContextWrapper。并且扩展也很方便,比如Service和Activity的情景不同,需要的接口方法也不同,但是与系统交互的接口相同。使用装饰者模式就可以扩展出很多特定的功能,只需要把ContextImpl赋值给装饰器类就行。

Context分类

​ Context最终的实现类有:Application,Activity,Service三类,ContextImpl会被这三者持有,这三类有何不同呢?

​ Appilcation只有一个,且是全局Context,可以访问包信息等资源。Application Context生命周期长,整个应用程序运行期间都会存在。同时开发者可以自定义实现Application,做一些全局的初始化操作。但是注意不要把Application当成工具类给全局使用。

​ Activity继承自ContextThemeWrapper,试一个拥有主题的context对象。Activity常用于与UI有关的操作,常规可以直接使用activity.this。

​ Service继承自ContextWrapper,也可以直接使用service.this使用context,且service没有界面,不需要主题。

​ Provider使用Application的context,Receiver使用Activity的context。这是为什么呢?因为Provider是伴随着应用启动创建的,在这时候Application被初始化后会赋值给Provider,这时候Provider就拥有context了。而Receiver是哪个组件创建广播,则context便是哪个组件,这是注册过程中决定的。所以一般是Acvtivity中创建,那么Receiver的context一般也就是activity了。

references

https://segmentfault.com/a/1190000038357455#:~:text=%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%8A%BD%E8%B1%A1%E7%B1%BB,%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%BA%A7%E7%9A%84%E6%93%8D%E4%BD%9C%E3%80%82

https://www.runoob.com/design-pattern/decorator-pattern.html