创建LayoutInflater对象,根据所传的上下文对象不同,创建出来的LayoutInflater对象也不同,在不同Activity中创建的LayoutInflater对象也不同,先来看一下,
Activity中的获取LayoutInflater对象及打印的对象地址LayoutInflater.from(this); com.android.internal.policy.impl.PhoneLayoutInflater@41882b90LayoutInflater.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@4189f2f0LayoutInflater.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对象咱们再看一下LayoutInflater.from(getBaseContext())获取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); }其实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对象。
新闻热点
疑难解答