Application中setTheme为什么不生效

Android开发者们都知道在AndroidManifest.xml中可以通过Application的theme标签来设置全局的theme,后续的Activity都可以继承这个主题。不过在自定义Application中通过代码动态去setTheme是不会生效的。为什么不会生效呢,我们可以通过以下来解决这个问题。

Activity是怎么继承到Application的主题的

1.ActivityThread.performLaunchActivity()

在ActivityThread.performLaunchActivity方法中,在回调Activity onCreate之前会设置Activity的主题。

int theme = r.activityInfo.getThemeResource();if (theme != 0) {    //设置主题    activity.setTheme(theme);}activity.mCalled = false;if (r.isPersistable()) {    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {    mInstrumentation.callActivityOnCreate(activity, r.state);}

2.ActivityInfo.getThemeResource()

//获取Activity主题的策略如下://1.假如在AndroidManifest.xml中设置了Activity的主题,那么优先使用Activity的主题//2.没有设置Activity的主题那么使用Application设置的主题//3.假如Application也没有设置主题,那么什么都不做。public final int getThemeResource() {   return theme != 0 ? theme : applicationInfo.theme;}

很明显,要想全局设置Activity的主题,必须设置applicationInfo.theme。首先我们发现applicationInfo只是ActivityInfo一个变量,那么ActivityInfo又是怎么创建的呢?

3.Activity.attach()

熟悉AMS的开发者很容易联想到attach这个方法。是的,在performLaunchActivity流程中,可以获取到Ams传递过来的ActivityInfo .

final void attach(Context context, ActivityThread aThread,            Instrumentation instr, IBinder token, int ident,            Application application, Intent intent, ActivityInfo info,            CharSequence title, Activity parent, String id,            NonConfigurationInstances lastNonConfigurationInstances,            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {        attachBaseContext(context);        ...}

4.PackageManagerService

那么在AMS传递过来的ActivityInfo是怎么生成的呢?这一系列的问题自然而来。这里就涉及到PMS的知识了。
在开机阶段,PMS会扫描整个手机上的app安装目录,每一个APK都会被解释然后保存到pms的mPackages。

final ArrayMap mPackages =         new ArrayMap();

一个Package就代表一个apk,Package里面保存了Activity列表,Receiver列表,Service列表等

 public final ArrayList permissions = new ArrayList(0); public final ArrayList permissionGroups = new ArrayList(0); public final ArrayList activities = new ArrayList(0); public final ArrayList receivers = new ArrayList(0); public final ArrayList providers = new ArrayList(0); public final ArrayList services = new ArrayList(0);

其中Activity里面就有我们想要的ActivityInfo,而applitionInfo的设置也是初始化的时候给赋值的。

public final static class Activity extends Component<ActivityIntentInfo> {        public final ActivityInfo info;        public Activity(final ParseComponentArgs args, final ActivityInfo _info) {            super(args, _info);            info = _info;            //这里赋值,一个包下所有Activity的applicationInfo一样            info.applicationInfo = args.owner.applicationInfo;        }}

可以知道,applicationInfo存在于pms中,在开机阶段或者安装阶段被初始化,然后ams启动相关Activity的时候,都会向pms请求,接着pms根据请求返回保存在内存中的ActivityInfo,通过Binder机制和App进程交互。所以,从上面我们可以知道要更改整个Application中的主题必须AndroidManifest.xml中修改,因为你无法修改PMS的东西。

更多相关文章

  1. android 的 Gallery 的简单使用
  2. Android(安卓)5.0使用android:onClick属性出现崩溃的原因及解决
  3. Android(安卓)按钮点击切换背景,同时修改文字颜色
  4. Android中SoundPool 类使用利弊
  5. Android(安卓)Studio如何设置代码自动提示
  6. (转)ANDROID强制锁定竖屏_APP固定设置竖屏或横屏
  7. 如何在Windows上设置Android环境变量/路径
  8. Android主题定制及修改
  9. intellij idea 设置用真机测试android

随机推荐

  1. Android中获取系统内存信息以及进程信息-
  2. 使用ijkplayer播放一个网络视频
  3. Android将图上以base64编码的格式上传到n
  4. android 中 Chronometer 计时器的使用
  5. android在XML中画横线、竖线和虚线
  6. Android 常用第三方组件
  7. 【android】Application 使用分析
  8. 2013.12.03(5) ——— android ActionbarSh
  9. Android Makefile中如何自定义Product
  10. Android EspressoUI自动化