創(chuàng)建LayoutInflater對象,根據(jù)所傳的上下文對象不同,創(chuàng)建出來的LayoutInflater對象也不同,在不同Activity中創(chuàng)建的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根據(jù)LayoutInflate的form方法中的實現(xiàn),其實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中創(chuàng)建的,所以創(chuàng)建的對象不同
下面咱來看一下LayoutInflater創(chuàng)建過程,咱們來跟蹤一下代碼,就拿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; }該方法中調(diào)用了Context的getSystemService()方法,因為傳的是this,即是Activity對象,Activity是也是Context對象,他們的繼承關(guān)系為:Activity -> ContextThemeWrapper -> ContextWrapper -> Context。所以看Context的子類是否重寫了getSystemService()方法,正好ContextThemeWrapper重寫了,Activity也重寫了,但和LayoutInflater沒有關(guān)系,所以我們看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,執(zhí)行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; }該方法又是在哪里調(diào)用的呢,是在Activity的attach方法中調(diào)用的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又是在哪里調(diào)用的呢,在ActivityThread中調(diào)用的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); }看到?jīng)],返回的對象是new ContextImpl出來的,所以之前的getBaseContext()獲取的就是ContextImpl對象。所以不同對象的Context中的ContextImpl對象就不同,所以創(chuàng)建出來的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; }我們在跟進(jìn)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中獲取,如果沒有就去創(chuàng)建createService,因為其實抽象的,所以看其實現(xiàn)類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對象在其沒有執(zhí)行cloneInContext(this)方法時創(chuàng)建的PhoneLayoutInflater對象。再一個就是LayoutInflater.from(getApplication());獲取LayoutInflater對象方式,因為getApplication()獲取的是全局的Application對象,其內(nèi)部的ContextImpl對象也不同,所以得到的LayoutInflater對象和之前兩個也不同,還有就是不管在哪個Activity中g(shù)etApplication()獲取的Context都是同一個對象,所以LayoutInflater.from(getApplication());獲取的LayoutInflater對象都是同一個。好了,這就是為什么不同的Context對象獲取LayoutInflater是不同的對象。從剛開始的getBaseContext(); android.app.ContextImpl@41882338就可以看出getBaseContext()獲取的是ContextImpl對象,和getApplication().getBaseContext(); android.app.ContextImpl@41870230獲取的都是同一個ContextImpl對象。
新聞熱點
疑難解答