美文网首页AndroidAndroid开发经验谈Android开发
【Android】不同Context引发的问题

【Android】不同Context引发的问题

作者: zaxer | 来源:发表于2017-08-23 17:31 被阅读199次

遇到这么个问题:

两个应用以相同的方式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);

}

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

相关文章

网友评论

  • chandarlee:两种方式都能拿到theme,只不过拿到的是不同的theme。application 拿到的是默认的theme,这个theme由targetsdk决定!而activity在创建的时候,会根据具体的theme属性设置(activity指定了就用它,没有就用application指定的那个)调用settheme,再次拿出来时肯定是对的
    zaxer:是啊,能拿到,但是不一样,给Application设置了Theme,通过ActivityContext 创建的View是可以有Theme里面设置的样式,而通过ApplicationContext创建的是系统默认的样式。
  • 14b54e286699:为你点赞

本文标题:【Android】不同Context引发的问题

本文链接:https://www.haomeiwen.com/subject/uhzddxtx.html