【Android】不同Context引发的问题

遇到这么个问题:

两个应用以相同的方式new一个控件,但是显示的样式却不一样,最后追溯代码,最终定位到原来传入的context不一样,一个为Activity的,另一个是Application的。

一、Context是什么?

语境、上下文,即环境的信息或者场景,它的实现是由Android系统提供的,访问app的资源,启动activity,获取系统服务,创建View等都会牵扯到Context。

二、Context创建

1、创建Application时会创建一个ApplicationContext,生命周期跟随应用走,当Application被摧毁时Context才被摧毁。 

2、创建Activity时会创建一个Activity的Context,生命周期跟随Activity。 

3、创建Service时创建Service的Context,生命周期跟随Service。

Context的总数 = Activity(个数)+Service(个数)+1个Application的Context。

三、获取Context

1、getContext(); 

2、getBaseContext(); 

3、getApplicationContext(); 

4、this;

四种方法获取的Context如下:

Context获取

通过View.getContext()和Activity.this其实时相同的,getBaseContext获取到的是ContextImpl的,getApplicationContext获取的是Application的。

四、通过Context获取资源

最常见的方法就是getContext().getResource(),通过这个方法可以获取String,Drawable等资源。 还有自定义View的时候也常用到context.obtainStyledAttributes()这个方法。

由上面第三点getContext的不同可以知道如果在应用里通过obtainStyledAttributes获取资源,使用getContext()和getApplicationContext() 是不一样的。

例如应用在Manifest里设置了App的Theme,通过getApplicationContext().getTheme是可以取得应用的Theme;但是通过Activity的context.getTheme是获取不到的。

会有部分人误认为只要设置了Application的Theme,Activity里getTheme就是正确的,我就是那个人。以下是Context的部分类图:

Context部分类图

可以很明显地看到Activity是继承ContextThemeWrapper,而Application是继承ContextWrapper的,ContextThemeWrapper里重写了setTheme方法。

setTheme方法

如果使用getContext获取资源,取决于Context是属于哪一个。

一个简单的例子:

Manifest设置了如下样式:

主题Theme

使用两个不同的Context创建EditText,其对应的样式也不一样:

不同Context

ActivityContext的EditText可以有主题定制的颜色,而getApplication的则没有,因为在EditText的初始化时使用的是context.obtainStyledAttributes 这个方法,而这个方法调用的是getTheme().obtainStyledAttributes,由上面可以知道context的不同,getTheme也是不同的,所以出现这样的问题。

public final TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) {

    return getTheme().obtainStyledAttributes(attrs);

}

这种小问题,稍不注意有时候也是个大麻烦。

你可能感兴趣的:(【Android】不同Context引发的问题)