1、Context
相信无论是Android开发新手还是老手,对于Context的使用肯定是不陌生的。在开发中,启动Activity、Service,创建View等操作是都需要有Context的传入,可见Context的重要性。例如我们平时经常传递的this参数究竟指的是什么?其实这里的this指的就是当前Activity的XXActivity.this。XXActivity.this取的就是当前所在的Activity的Context,那么问题来了,这个Context究竟有什么作用呢?在哪些地方需要注意呢?
按字面意思,Context翻译过来就是“上下文”或者“活动”的意思,位于anroid.content.Context中。
有点懒,所以直接在androidStudio中,站在程序的角度看一下吧。
从图中中可以看出Context类的继承关系,Activity、Service、Application等都是Context的子类,都是Context类的一种实现。
2、Context和ApplicaionContext
在android中Context起到关键性的作用,但是最主要的功能是加载和访问资源。在android中有两种Context,一种是 ApplicationContext,一种是activity中的Context。
两者的区别:XXActivity.this和getApplicationContext返回的对象时不一样的。getApplicationContext() 返回应用的上下文,生命周期是整个应用,应用摧毁它才摧毁XXActivity.this的Context 返回当前activity的上下文,属于XXActivity ,XXActivity 摧毁他就摧毁getBaseContext()返回由构造函数指定或setBaseContext()设置的上下文,一般不常用。
3、Context的引用问题和内存泄露的优化
public static synchronized newInstance (final Context mContext)
{
if (mInstance == null)
{
mInstance = new XXClass(context);
}
return mInstance;
}
对于上面的newInstance方法,应该并不陌生,内部保持了对Context的引用;问题在于,这个传进来的Context,来自哪不知道,或者直接传了个this。那么问题就来了,我们的这个类中的mInstance是一个static且强引用的,在其内部引用了XXActivity作为Context,也就是说,只要App运行着,XXActivity就没有办法进行内存回收。而我们的Activity的生命周期肯定没这么长,所以造成了内存泄漏。有人可能会说价格软引用不就行了吗,但问题又来了,软引用后,若被回收了,再去用它,不就报NullPointException错误了吗。
对上述代码做如下修改:
public static synchronized newInstance (final Context mContext)
{
if (mInstance == null)
{
mInstance = new XXClass(context.getApplicationContext());
}
return mInstance;
}
引用的是一个ApplicationContext,它的生命周期和我们的单例对象一致,这样,我们就解决了内存泄漏的问题。
为了防止内存泄露,我们应该注意以下几点:
- 1、不要让生命周期长的对象引用Activity的Context,即保证引用Activity的对象要与Activity本身生命周期是 一样的
- 2、对于生命周期长的对象,可以使用Application中的Context
- 3、避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变 化。
因此应用程序App共有的Context数目公式为:
总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)