android settheme不起作用,Android那些疑惑(1)-Application中setTheme为什么不生效

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 {

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的东西。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值