Android中Context相关知识整理

1、Context的种类

我们来Context的继承结构。(图片来自:http://blog.csdn.net/guolin_blog/article/details/47028975)

Android中Context相关知识整理_第1张图片

从这个类中,我们可以看到Context有三种类型:Application、Activity、Service。

另外,从上面可以轻易的看出它使用了装饰者模式,也就是说Application、Activity、Service都属于Context,而具体Context的功能则是由ContextImpl类去实现的。

2、Context的数量

从上面我们知道,Context有Application、Activity和Service三种类型,一个应用的Context数量如下:

Context数量 = Activity数量 + Service数量 + 1

3、三种类型的Context是如何创建的?

可以参考这篇文章:Android应用Context详解及源码解析

4、三种类型的Context的生命周期

(1)每个应用启动的时候首先会创建Application对象,每个应用都有一个唯一的全局Application对象,与整个应用的生命周期相同,所以Application这个Context的生命周期就是整个应用的生命周期。
(2)Activity这个Context的生命周期就是Activity的生命周期。
(3)Service这个Context的生命周期就是Service的生命周期。

5、Context的引用问题

知道上面的生命周期之后,我们需要知道这个生命周期有什么作用,在很多的地方,我们都需要传入一个Context对象,那么我们到底要传入什么样的Context呢?如果这个Context传入不当,很可能出现内存泄漏的情况,下面举个例子,我们在编写一些工具类的时候,可能会编写成单例的方式,这些工具类大多需要去访问资源,也就说需要Context的参与。

public class CustomManager  {  
    private static CustomManager sInstance;  
    private Context mContext;  

    private CustomManager(Context context) {  
        this.mContext = context;  
    }  

    public static synchronized CustomManager getInstance(Context context) {  
        if (sInstance == null) {  
            sInstance = new CustomManager(context);  
        }  
        return sInstance;  
    }  

}

上面这种单例的写法,我们可能会经常遇到,问题在于,这个Context哪来的我们不能确定,很大的可能性,你在某个Activity里面为了方便,直接传了个this;这样问题就来了,我们的这个类中的sInstance是一个static且强引用的,在其内部引用了一个Activity作为Context,也就是说,我们的这个Activity只要我们的项目活着,就没有办法进行内存回收。而我们的Activity的生命周期肯定没这么长,所以造成了内存泄漏。

下面来对代码进行修改

public static synchronized CustomManager getInstance(Context context) {  
    if (sInstance == null) {  
        sInstance = new CustomManager(context.getApplicationContext());  
    }  
    return sInstance;  
} 

这样,我们就解决了内存泄漏的问题,因为我们引用的是一个ApplicationContext,它的生命周期和我们的单例对象一致。

6、Context的应用场景

Android中Context相关知识整理_第2张图片

大家注意看到有一些NO上添加了一些数字,其实这些从能力上来说是YES,但是为什么说是NO呢?下面一个一个解释:

数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task。一般情况不推荐。

数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。

数字3:在receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。

另外,ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。

参考文章:Android Context 上下文 你必须知道的一切

7、getApplication()、getApplicationContext()和getBaseContext()

(1)getApplication()与getApplicationContext()返回的都是Application对象。
(2)和getBaseContext()返回的是ContextImpl对象。

具体原因可以参考文章:

Android Context完全解析,你所不知道的Context的各种细节

Android应用Context详解及源码解析

你可能感兴趣的:(android,context)