Acitivy创建Context的过程(二)

page4
在这里我们分析一下ContextImpl的init函数的具体实现:
final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
        init(packageInfo, activityToken, mainThread, null, null, Process.myUserHandle());
    }

1     final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread,
2             Resources container, String basePackageName, UserHandle user) {
3         mPackageInfo = packageInfo;
4         mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
5         mResources = mPackageInfo.getResources(mainThread);
6
7         if (mResources != null && container != null
8                 && container.getCompatibilityInfo().applicationScale !=
9                         mResources.getCompatibilityInfo().applicationScale) {
10             if (DEBUG) {
11                 Log.d(TAG, "loaded context has different scaling. Using container's" +
12                         " compatiblity info:" + container.getDisplayMetrics());
13             }
14             mResources = mainThread.getTopLevelResources(
15                     mPackageInfo.getResDir(), Display.DEFAULT_DISPLAY,
16                     null, container.getCompatibilityInfo());
17         }
18         mMainThread = mainThread;
19         mActivityToken = activityToken;
20         mContentResolver = new ApplicationContentResolver(this, mainThread, user);
21         mUser = user;
22     }

init函数的主要逻辑就是初始化主要的成员变量
page5
activity的attach函数的定义如下, 注意下面是两个函数:
1     final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
2             Application application, Intent intent, ActivityInfo info, CharSequence title,
3             Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances,
4             Configuration config) {
5         attach(context, aThread, instr, token, 0, application, intent, info, title, parent, id,
6             lastNonConfigurationInstances, config);
7     }
8    
9     final void attach(Context context, ActivityThread aThread,
10             Instrumentation instr, IBinder token, int ident,
11             Application application, Intent intent, ActivityInfo info,
12             CharSequence title, Activity parent, String id,
13             NonConfigurationInstances lastNonConfigurationInstances,
14             Configuration config) {
15         attachBaseContext(context);
16
17         mFragments.attachActivity(this, mContainer, null);
18        
19         mWindow = PolicyManager.makeNewWindow(this);
20         mWindow.setCallback(this);
21         mWindow.getLayoutInflater().setPrivateFactory(this);
22         if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
23             mWindow.setSoftInputMode(info.softInputMode);
24         }
25         if (info.uiOptions != 0) {
26             mWindow.setUiOptions(info.uiOptions);
27         }
28         mUiThread = Thread.currentThread();
29        
30         mMainThread = aThread;
31         mInstrumentation = instr;
32         mToken = token;
33         mIdent = ident;
34         mApplication = application;
35         mIntent = intent;
36         mComponent = intent.getComponent();
37         mActivityInfo = info;
38         mTitle = title;
39         mParent = parent;
40         mEmbeddedID = id;
41         mLastNonConfigurationInstances = lastNonConfigurationInstances;
42
43         mWindow.setWindowManager(
44                 (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
45                 mToken, mComponent.flattenToString(),
46                 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
47         if (mParent != null) {
48             mWindow.setContainer(mParent.getWindow());
49         }
50         mWindowManager = mWindow.getWindowManager();
51         mCurrentConfig = config;
52     }

第15行(Activity->attach)调用attachBaseContext函数, 关于attachBaseContext函数的详细分析可以参考page6文件.
调用完attachBaseContext函数我们明白了, Activity拿着ContextImpl, 而ContextImpl也拿着这个Activity
page6
在这篇文章里, 我们分析一下Activity的attachBaseContext函数的具体逻辑, 其实attachBaseContext函数是从Activity的父类ContextThemeWrapper继承而来的,
我们先来看一下ContextThemeWrapper类的继承体系,
public class ContextThemeWrapper extends ContextWrapper
public class ContextWrapper extends Context

那么ContextThemeWrapper的attachBaseContext函数的具体实现如下:
1     @Override protected void attachBaseContext(Context newBase) {
2         super.attachBaseContext(newBase);
3         mBase = newBase;
4     }

第2行(ContextThemeWrapper->attachBaseContext)调用父类ContextWrapper的attachBaseContext函数:
1 protected void attachBaseContext(Context base) {
2 if (mBase != null) {
3     throw new IllegalStateException("Base context already set");
4 }
5 mBase = base;
6     }
ContextWrapper的attachBaseContext函数会设置成员变量mBase, 使之指向一个Context对象, 也就是ContextImpl了.
ContextWrapper的成员变量mBase的定义如下:
Context mBase;

第3行(ContextThemeWrapper->attachBaseContext)又会初始化成员变量mBase, 我靠!咋又有一个!
ContextThemeWrapper的mBase的定义如下:
private Context mBase;

猜你喜欢

转载自zzu-007.iteye.com/blog/2380765