Androidあれらの疑惑(1)-APplicationの中でsetThemeはどうして発効しません


ApplicationでsetThemeが有効にならない理由
Android開発者たちはAndroid Manifestで知っている.xmlではアプリケーションのthemeタグでグローバルなthemeを設定でき、後続のActivityでこのトピックを継承できます.ただし、カスタムアプリケーションでコードによって動的にsetThemeを設定することは有効ではありません.なぜ有効にならないのか、私たちは以下の問題を解決することができます.
Activityがアプリケーションのテーマにどのように継承されているか
1.ActivityThread.performLaunchActivity()
...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のトピックをグローバルに設定するには、アプリケーションInfoを設定する必要があることは明らかです.theme.まずアプリケーションInfoはActivity Infoの変数にすぎないことを発見しましたが、Activity Infoはどのように作成されたのでしょうか.
3.Activity.attach()
AMSに詳しい開発者はattachという方法を連想しやすい.はい、performLaunchActivityプロセスでは、Amsから渡されたActivity Infoを取得できます.
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で渡されたActivity Infoはどのようにして生成されたのでしょうか.この一連の問題は自然に来た.ここではPMSの知識についてお話しします.起動段階では、PMSは携帯電話全体のappインストールディレクトリをスキャンし、各APKは解釈されてpmsのmPackagesに保存されます.
final ArrayMap mPackages = 
        new ArrayMap();

1つのPackageは1つの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には私たちが望んでいるActivity Infoがあり、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;
        }
}

アプリケーションInfoはpmsに存在し、起動フェーズまたはインストールフェーズで初期化され、amsが関連Activityを起動するとpmsに要求され、pmsは要求に応じてメモリに保存されているActivity Infoを返し、BinderメカニズムとAppプロセスを介して相互にやり取りすることが分かる.したがって、Application全体のトピックを変更するにはAndroid Manifestが必要であることがわかります.xmlではPMSのものを修正できないので修正します.