在Android应用开发中,最常用的组件大概非Activity莫属了,Activity究竟是什么,可能有各种各样的解释,但从安卓源码看来,Activity是一个Context对象,中文解释就是一个上下文对象,所谓上下文就是具有很强资源访问能力的一个对象,上下文对象不仅于Activity,包括Service和Application都是Context对象,我们需要Context对象也一般是进行资源访问。
在Activity中,很多情况下我们需要获取上下文对象,譬如资源访问、加载布局、构建适配器等等。这时候对于如何获取上下文对象,有几种选择:1.Activity.this,或者直接用this,但在设置监听的时候,我们一般采用匿名内部类的方式,这时候this指代的就不是当前的Activity,而是那个匿名的内部类,会出现异常,故要用Activity.this;2.getApplicationContext(),这种方法也能获取到上下文对象;其他的还有BaseContext(),getApplication()之类的,大同小异,就不一一列举了,当然,getApplication()获取的是应用对象,与上下文对象有所区别,此处略过不表。
我在使用的过程中发现,当访问资源或者存取变量数据的时候,getApplicationContext()一般是不会出现问题了,也习惯了使用这种方式,而在更新UI的时候,却经常报错,有时候空指针,有时候其他致命错误,改用Activity.this却可以。为了探究问题根源所在,便有心去搜集了一些资料,在stackoverflow上面看到有人对该问题作出了推测:
解释的意思是:当需要更改UI的时候,最好采用Activity.this的方法来获取上下文对象,使用getApplicationContext()可能会出现异常,譬如在当前界面创建一个TextView的时候,如果传入的是ApplicationContext,则应用会抛出异常;而当你需要一些跨Activity的使用时,譬如获取ContentResolver时,应该使用ApplicationContext,因为你需要的对象并不必且不应该与当前Activity绑定,而是独立存在于Application中,如果使用Activity.this获取上下文对象,该Activity有可能在一个应用中被多次启用和销毁,当Activity被销毁时,通过Activity.this获取到的上下文对象也就不复存在了。
为了验证此回答的合理性,我去查阅了一下Android源码,里面关于getApplication()的注释是这样的:
意思是:返回当前进程的一个全局、单例的应用对象,通常仅当你需要一个生命周期与当前Context(一般是当前Activity)完全无关的组件时你才需要用到它,一旦你启用它,该组件会绑定持续到应用结束而不是当前界面结束。
根据官方注释,我们知道getApplicationContext()获取到对象的生命的周期伴随整个Application,而从前面我们知道,Activity.this只存在于Activity的生命周期之内,当Activity被销毁之后,再想调用基于该Activity上下文被创建的对象时,会出现异常。
综上所述,我们应该根据对象的生命周期来获取相应的上下文对象,比如更新UI的都是在当前Activity上进行操作,当Activity被销毁时,这个对象也就没有存在的必要了,还有一些其他的对象,即便不是有关UI的,但只要生命周期不大于Activity的,建议使用Activity.this来获取上下文对象,为保险起见,在适当的时候调用gc,防止内存泄漏。对于一些不依存于当前Activity的对象,比如ContentResolver,比如保存用户信息以及其他生命周期大于当前Activity的对象,都就当使用getApplicationContext()来获取上下文对象。