標籤:
一.概述
這篇文章主要解答一些在平時學習工作過程中遇到的一些比較值得研究的問題。
二.問題
1.DecorView是何時被建立的
是在PhoneWindow的generateDecor中被建立的
protected DecorView generateDecor() { return new DecorView(getContext(), -1); }
2.ViewRootImpl是何時被建立的
是在WindowManagerGlobal的addView方法中建立的
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { //省去大量代碼 ViewRootImpl root; View panelParentView = null;//省去部分代碼 root = new ViewRootImpl(view.getContext(), display); ...... }
3.Activity載入布局的流程
在Activity中調用setContentView載入布局,setContentView最終調用PhoneWindow的setContentView方法,在此方法中將根布局xml檔案解析成View添加到DecorView中,然後從根布局檔案中找到id為contente的父容器,將我們在setContentView中指定的布局檔案通過inflate的方式添加進去
//將我們的布局檔案添加到mContentParent中,這個mContentParent是根布局中id為content的一個FrameLayout mLayoutInflater.inflate(layoutResID, mContentParent);
4.Window對象何時被建立
在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) { attachBaseContext(context); mFragments.attachActivity(this, mContainer, null); //建立window對象 mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } if (info.uiOptions != 0) { mWindow.setUiOptions(info.uiOptions); } mUiThread = Thread.currentThread(); ..... }
5.Application對象何時被建立
在Instrumentation的newApplication方法中
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return newApplication(cl.loadClass(className), context); }
6.View繪製的起點在何處
ViewRootImpl的performTraversals方法
private void performTraversals() { //省去海量代碼 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);//省去部分代碼 performLayout(lp, desiredWindowWidth, desiredWindowHeight); //省去大量代碼 performDraw(); ..... }
7.startActivity的流程
startActivity最終會調用startActivityForResult
public void startActivityForResult(Intent intent, int requestCode, Bundle options) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); .... }
實際調用的是Instrumentation的execStartActivity
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Fragment target, Intent intent, int requestCode, Bundle options) { //核心功能在這個whoThread中完成,其內部scheduleLaunchActivity方法用於完成activity的開啟 IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); //真正開啟activity的地方 int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mWho : null, requestCode, 0, null, null, options); //對結果進行檢查,拋異常 checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; }
IApplicationThread 看名字就知道是一個介面,我們找找實作類別,
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread
private class ApplicationThread extends ApplicationThreadNative
ApplicationThread 用來完成Activity各個狀態的切換
8.DecorView何時被添加到Window中
在Activity的makeVisible方法中
void makeVisible() { if (!mWindowAdded) { ViewManager wm = getWindowManager(); wm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; } mDecor.setVisibility(View.VISIBLE); }
Android疑痛點解答