美文网首页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