创建LayoutInflater对象,根据所传的上下文对象不同,创建出来的LayoutInflater对象也不同,在不同Activity中创建的LayoutInflater对象也不同,先来看一下,
- Activity中的获取LayoutInflater对象及打印的对象地址
- LayoutInflater.from(this); com.android.internal.policy.impl.PhoneLayoutInflater@41882b90
- LayoutInflater.from(getApplication()); com.android.internal.policy.impl.PhoneLayoutInflater@418da098
- LayoutInflater.from(getBaseContext()); com.android.internal.policy.impl.PhoneLayoutInflater@41882b40
- getSystemService(Context.LAYOUT_INFLATER_SERVICE); com.android.internal.policy.impl.PhoneLayoutInflater@41882b90
- getApplication().getSystemService(Context.LAYOUT_INFLATER_SERVICE);com.android.internal.policy.impl.PhoneLayoutInflater@418da098
- getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);com.android.internal.policy.impl.PhoneLayoutInflater@41882b40
- getBaseContext(); android.app.ContextImpl@41882338
- getApplication().getBaseContext(); android.app.ContextImpl@41870230
- 另一Activity中的获取LayoutInflater对象及打印的对象地址
- LayoutInflater.from(this); com.android.internal.policy.impl.PhoneLayoutInflater@4189f2f0
- LayoutInflater.from(getApplication()); com.android.internal.policy.impl.PhoneLayoutInflater@418da098
- LayoutInflater.from(getBaseContext()); com.android.internal.policy.impl.PhoneLayoutInflater@4189f2a0
- getSystemService(Context.LAYOUT_INFLATER_SERVICE); com.android.internal.policy.impl.PhoneLayoutInflater@4189f2f0
- getApplication().getSystemService(Context.LAYOUT_INFLATER_SERVICE);com.android.internal.policy.impl.PhoneLayoutInflater@418da098
- getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);com.android.internal.policy.impl.PhoneLayoutInflater@4189f2a0
- getBaseContext(); android.app.ContextImpl@4189ecd8
- getApplication().getBaseContext(); android.app.ContextImpl@41870230
根据LayoutInflate的form方法中的实现,其实LayoutInflater.from(this);LayoutInflater.from(getApplication());LayoutInflater.from(getBaseContext());和getSystemService(Context.LAYOUT_INFLATER_SERVICE);getApplication().getSystemService(Context.LAYOUT_INFLATER_SERVICE);getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);其实是一个意思,所以他们获取的对象都是一样的,那为什么不同上下文对象获取的LayoutInflater对象也不同呢,因为不同Context对象中的mBase(ContextImpl)对象不同,LayoutInflater就是在ContextImpl中创建的,所以创建的对象不同
下面咱来看一下LayoutInflater创建过程,咱们来跟踪一下代码,就拿LayoutInflater.from(this)来说,看LayoutInflater中的form()方法
- public static LayoutInflater from(Context context) {
- LayoutInflater LayoutInflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- if (LayoutInflater == null) {
- throw new AssertionError('LayoutInflater not found.');
- }
- return LayoutInflater;
- }
该方法中调用了Context的getSystemService()方法,因为传的是this,即是Activity对象,Activity是也是Context对象,他们的继承关系为:Activity -> ContextThemeWrapper -> ContextWrapper -> Context。所以看Context的子类是否重写了getSystemService()方法,正好ContextThemeWrapper重写了,Activity也重写了,但和LayoutInflater没有关系,所以我们看ContextThemeWrapper中的getSystemService()方法
- public Object getSystemService(String name) {
- if (LAYOUT_INFLATER_SERVICE.equals(name)) {
- if (mInflater == null) {
- mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
- }
- return mInflater;
- }
- return getBaseContext().getSystemService(name);
- }
一开始的时候,mInflater肯定是为null,执行LayoutInflater.from(getBaseContext())方法,又回到了刚开始的LayoutInflater.from()方法,不一样的是这次上下文的对象是ContextImpl对象,为什么是ContextImpl,我们看getBaseContext()方法
- public Context getBaseContext() {
- return mBase;
- }
该返回就只返回了mBase,我们看其是在哪里赋值的,是在ContextWrapper类的attachBaseContext方法中赋值的
- protected void attachBaseContext(Context base) {
- if (mBase != null) {
- throw new IllegalStateException('Base context already set');
- }
- mBase = base;
- }
该方法又是在哪里调用的呢,是在Activity的attach方法中调用的
- 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);
- ......
- }
attach又是在哪里调用的呢,在ActivityThread中调用的
- private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
- ......
- if (activity != null) {
- Context appContext = createBaseContextForActivity(r, activity);
- CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
- Configuration config = new Configuration(mCompatConfiguration);
- if (DEBUG_CONFIGURATION) Slog.v(TAG, 'Launching activity '
- + r.activityInfo.name + ' with config ' + config);
- activity.attach(appContext, this, getInstrumentation(), r.token,
- r.ident, app, r.intent, r.activityInfo, title, r.parent,
- r.embeddedID, r.lastNonConfigurationInstances, config,
- r.referrer, r.voiceInteractor);
- ......
- }
- ......
- }
而appContext又是createBaseContextForActivity(r, activity)方法返回的,
- private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
- ......
- ContextImpl appContext = ContextImpl.createActivityContext(
- this, r.packageInfo, displayId, r.overrideConfig);
- appContext.setOuterContext(activity);
- Context baseContext = appContext;
- final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
- String pkgName = SystemProperties.get('debug.second-display.pkg');
- if (pkgName != null && !pkgName.isEmpty()
- && r.packageInfo.mPackageName.contains(pkgName)) {
- for (int id : dm.getDisplayIds()) {
- if (id != Display.DEFAULT_DISPLAY) {
- Display display =
- dm.getCompatibleDisplay(id, appContext.getDisplayAdjustments(id));
- baseContext = appContext.createDisplayContext(display);
- break;
- }
- }
- }
- return baseContext;
- }
baseContext又是通过ContextImpl的createActivityContext()方法获取的
- static ContextImpl createActivityContext(ActivityThread mainThread,
- LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
- if (packageInfo == null) throw new IllegalArgumentException('packageInfo');
- return new ContextImpl(null, mainThread, packageInfo, null, null, false,
- null, overrideConfiguration, displayId);
- }
看到没,返回的对象是new ContextImpl出来的,所以之前的getBaseContext()获取的就是ContextImpl对象。所以不同对象的Context中的ContextImpl对象就不同,所以创建出来的LayoutInflater的对象可能就不同,往下看
所以我们再看LayoutInflater.from()中的context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)语句,这个context就是ContextImpl对象,看其方法
- @Override
- public Object getSystemService(String name) {
- return SystemServiceRegistry.getSystemService(this, name);
- }
SystemServiceRegistry的getSystemService方法
- public static Object getSystemService(ContextImpl ctx, String name) {
- ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
- return fetcher != null ? fetcher.getService(ctx) : null;
- }
我们在跟进getService()
- static abstract interface ServiceFetcher<T> {
- T getService(ContextImpl ctx);
- }
- static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
- private final int mCacheIndex;
- public CachedServiceFetcher() {
- mCacheIndex = sServiceCacheSize++;
- }
- @Override
- @SuppressWarnings('unchecked')
- public final T getService(ContextImpl ctx) {
- final Object[] cache = ctx.mServiceCache;
- synchronized (cache) {
- // Fetch or create the service.
- Object service = cache[mCacheIndex];
- if (service == null) {
- service = createService(ctx);
- cache[mCacheIndex] = service;
- }
- return (T)service;
- }
- }
- public abstract T createService(ContextImpl ctx);
- }
它会先从cache中获取,如果没有就去创建createService,因为其实抽象的,所以看其实现类
- registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
- new CachedServiceFetcher<LayoutInflater>() {
- @Override
- public LayoutInflater createService(ContextImpl ctx) {
- return new PhoneLayoutInflater(ctx.getOuterContext());
- }});
到这里终于看到了LayoutInflater 对象 PhoneLayoutInflater,其实这还不是LayoutInflater.from(this)的最终对象,看ContextThemeWrapper 的mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);其实他在得到对象的时候又clone了一个
- public LayoutInflater cloneInContext(Context newContext) {
- return new PhoneLayoutInflater(this, newContext);
- }
又new出了一个PhoneLayoutInflater对象,这才是LayoutInflater.from(this)返回的LayoutInflater对象
- public Object getSystemService(String name) {
- if (LAYOUT_INFLATER_SERVICE.equals(name)) {
- if (mInflater == null) {
- mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
- }
- return mInflater;
- }
- return getBaseContext().getSystemService(name);
- }
其实LayoutInflater.from(getBaseContext())获取LayoutInflater对象就是LayoutInflater.from(this)获取的LayoutInflater对象在其没有执行cloneInContext(this)方法时创建的PhoneLayoutInflater对象。再一个就是LayoutInflater.from(getApplication());获取LayoutInflater对象方式,因为getApplication()获取的是全局的Application对象,其内部的ContextImpl对象也不同,所以得到的LayoutInflater对象和之前两个也不同,还有就是不管在哪个Activity中getApplication()获取的Context都是同一个对象,所以LayoutInflater.from(getApplication());获取的LayoutInflater对象都是同一个。
好了,这就是为什么不同的Context对象获取LayoutInflater是不同的对象。从刚开始的getBaseContext(); android.app.ContextImpl@41882338就可以看出getBaseContext()获取的是ContextImpl对象,和getApplication().getBaseContext(); android.app.ContextImpl@41870230获取的都是同一个ContextImpl对象。
联系客服