Activity、Service和Application的Context的区别

1、Context的类图

在这里插入图片描述

  • Context:是一个接口类,主要提供通用接口

  • ContextImpl:Context接口的具体实现类

  • ContextWrapper:Context的包装类,内部持有一个ContextImpl的实例对象mBase,对Context的操作最终都进入ContextImpl类

  • ContextThemeWrapper:该类内部包含了主题(Theme)相关的接口,即android:theme属性指定的。Service不需要主题,所以Service直接继承于ContextWrapper类。而Activity继承此类。

个应用包含的Context个数:Service个数+Activity个数+1(Application类本身对应一个Context对象)。

2、Context的类型

并不是所有的context实例都是等价的。根据Android应用的组件不同,访问的context推向有些细微的差别。

  • Application - 是一个运行在你的应用进程中的单例。在Activity或者Service中,它可以通过getApplication()函数获得,或者人和继承于context的对象中,通过getApplicationContext()方法获得。不管你是通过何种方法在哪里获得的,在一个进程内,你总是获得到同一个实例。

  • Activity/Service - 继承于ContextWrapper,它实现了与context同样API,但是代理这些方法调用到内部隐藏的Context实例,即我们所知道的基础context。任何时候当系统创建一个新的Activity或者Service实例的时候,它也创建一个新的ContextImpl实例来做所有的繁重的工作。每一个Activity和Service以及其对应的基础context,对每个实例来说都是唯一的。

  • BroadcastReciver - 它本身不是context,也没有context在它里面,但是每当一个新的广播到达的时候,框架都传递一个context对象到onReceive()。这个context是一个ReceiverRestrictedContext实例,它有两个主要函数被禁掉:registerReceiver()和bindService()。这两个函数在BroadcastReceiver.onReceive()不允许调用。每次Receiver处理一个广播,传递进来的context都是一个新的实例。

  • ContentProvider - 它本身也不是一个Context,但是它可以通过getContext()函数给你一个Context对象。如果ContentProvider是在调用者的的本地(例如,在同一个应用进程),getContext()将返回的是Application单例。然而,如果调用这和ContentProvider在不同的进程的时候,它将返回一个新创建的实例代表这个Provider所运行的包。

3、不同Context的能力

在这里插入图片描述

注:NO1 表示Application context的确可以开始一个Activity,但是它需要创建一个新的task。这可能会满足一些特定的需求,但是在你的应用中会创建一个不标准的回退栈(back stack),这通常是不推荐的或者不是是好的实践。

NO2 表示这是非法的,但是这个填充(inflation)的确可以完成,但是是使用所运行的系统默认的主题(theme),而不是你app定义的主题。

NO3 在Android4.2以上,如果Receiver是null的话(这是用来获取一个sticky broadcast的当前 值的),这是允许的。

4、与UI相关的都用Activity

从前面的表格中可以看到,application context有很多功能并不是合适去做,而这些功能都与UI相关。实际上,只有Activity能够处理所有与UI相关的任务。其他类别的context实例功能都差不多。

尝试显示一个使用Aplication context创建的Dialog,或者使用Application context开始一个Activity,系统会抛出一个异常,让你的application崩溃,非常强的告诉你某些地方出了问题。

填充View(inflating layout)和使用的Context有很大关系。当你使用Application context来inflate一个布局的时候,框架并不会报错,并返回一个使用系统默认的主题创建一个完美的view给你,而没有考虑你的applicaiton自定义的theme和style。这是因为Acitivity是唯一的绑定了在manifast文件种定义主题的Context。其他的Context实例将会使用系统默认的主题来inflater你的view。导致显示的结果并不是你所希望的。可以参考博客 http://www.doubleencore.com/2013/05/layout-inflation-as-intended/

5、 使用Context的小经验

1、可能有些情况下,在某些Application的设计中,我们可能既必须长期保存一个的引用,并且为了完成与UI相关的工作又必须保存一个Activity。如果出现这种情况,我将会强烈建议你重新考虑你的设计,它将是一个很好的“反框架”教材。

2、绝大多数情况下,使用在你的所工作的组建内部能够直接获取的Context。只要这个引用没有超过这个组建的生命周期,你可以安全的保存这个引用。一旦你要保存一个context的引用,它超过了你的Activity或者Service的生命周期范围,甚至是暂时的,你就需要转换你的引用为Application context。

6、一个APP中有多少个Context

通常等于 Application + Activity + Service 的数量,而Application通常为1,因为应用通常是单进程。

7、Activity、Service、Applciation的对比总结

Activity

  • 1、UI相关的Context都推荐使用Activity,否则有可能会有异常
  • 2、Activity的功能最全面,可以在任何需要Context的地方使用Activity

Service

  • 1、不能用来创建Dialog
  • 2、如果用来进行视图填充(LayoutInflation),设置的主题不会生效,只会显示默认主题
  • 3、如果用来启动一个Activity,新的Activity会在一个新的task任务栈,不建议这么使用

Applciation

  • 1、直接用来创建创建Dialog,会抛异常Crash,除非进行特殊设置,所以不建议这么使用
  • 2、和Service相同,不建议用来进行视图填充(LayoutInflation),否则只显示默认主题
  • 3、和Service相同,不建议用来启动Activity
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值