Android中的Context理解
1、sdk当中关于Context的介绍
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows
access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
http://developer.android.com/reference/android/content/Context.html
Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的由整个Android应用程序所实现。它允许获取应用当中特定的资源和类,同时允许调用应用级的操作,如启动Activity,broadcasting和接收intents等等。
从以上的描述当中,我们基本获得不了什么信息,更无法理性的认识Context。
我们再来看看Context是子类和部分方法如下:
其中Application、Activity、Service等我们在开发当中常用的类,都是其子类,我们在这里也无法认识到它的作用。右图,我们可以看到,我们平时用到的startActivty();startService();等方法都在这里,在这里,我们可以看到Context的第一个作用:
2、第一个作用
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system.
他提供一个全局的接口,并且这些接口由Android应用程序当中特定的类实现。
我们再来看看Activity的源码:
这里,startActivity()的实现调用了Context中没有的startActivityForResult方法得以实现开启新的窗体的Activity的功能。
我们再看看我们平时用到的startService方法,非常遗憾我们没有在Activity当中找到startService的实现,但是我们继续往上找,找到了ContentWrapper时,我们找到了startService的实现
类似的Application,service等,都可以找到其相应的函数的实现。Context功能之一就是将常用的公共方法抽取出来,然后由各个组件实现,这真是第一句话的意思。
3、第二个作用
It allows access to application-specific resources and classes, as well as
up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
它允许获取应用当中特定的资源和类,同时允许调用应用级的操作,如启动Activity,broadcasting和接收intents等等。其实该类为LONG型,类似Win32中的Handle句柄,很多方法需要通过
Context才能识别调用者的实例,比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的 实例为Activity,而到了一个button的onClick(View view)等方法时,我们用this时就会报错,所以我们可能使用ActivityName.this来解决,主要原因是因为实现Context的类主要有Android特有的几个模型,Activity、Service以及BroadcastReceiver。
对于以上几句话的理解,我们可以看看TextView的构造函数
可以看到起参数为Context但是我们在实际开发当中
这两种定义都可以实现。this表示这个类的某个实例,而getApplicationContext()得到的是Context(),两个风马牛不相及的事物为什么能放在TextView的构造函数里,而不报错呢,这就是Context的第二个作用,句柄。标识应用程序中的不同对象和同类对象中的不同的实例。
4、两种不同的Context
![](http://my.csdn.net/uploads/201204/22/1335100379_3709.png)
![](http://my.csdn.net/uploads/201204/22/1335100390_7472.png)
5、内存泄露
当屏幕旋转的时候,系统会销毁当前的activity,保存状态信息,再创建一个新的。
比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏 幕的时候都销毁这个图片,重新加载。实现这个要求的简单想法就是定义一个静态的Drawable,这样Activity 类创建销毁它始终保存在内存中。实现类似:
6、避免context相关的内存泄露,记住以下几点:
- 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
- 对于生命周期长的对象,可以使用application context
- 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
7、制造Application context的方法
每个activity都是context,里面包含了运行时的状态。同样application也有一个context,android会保证这个context是唯一的实例。
做一个你自己的application context需要继承android.app.Application,然后在app的manifest里面说明这个类。android会自动帮你创建你这个类的实例,接着你用Context.getApplicationContext()方法就能在各个activity里面获得这个application context了。
小文章,边看边写,欢迎纠错。