Activity啟動(1)----流程


    Activity啟動過程中做了哪些事情?下面的時序圖展示里啟動過程中函數的調用過程, 從圖中可以知道大概流程。

在介紹細節的時候是從上往下函數調用過程介紹的,如果不知道某個函數是在哪里被誰調用的,可以回過頭來看下時序圖。下面是對一些細節進行介紹。

1. 在Android中有兩種操作會引發Activity的啟動,一種用戶點擊Launcher的應用程序圖標時,Launcher會為啟動應用程序的主Activity。另外一種是在已經起來的Activity內部通過調用startActvity接口啟動新的Activity。每一個Activity都可以在內部啟動新的Activity。圖中就是從一個Activity調用startActivity啟動另外一個Activity開始。

startActivity()@Activity.java

public void startActivity(Intent intent, Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
}

 startActivity()中調用攜帶requestCode參數的startActivityForResult()啟動新的activity。

 startActivityForResult()@Activity.java

public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
    //一般的Activity的mParent為null
    if (mParent == null) {
        //調用Instrumentation.execStartActivity()啟動新的Activity。mMainThread類型為ActivityThread, 在attach()函數被回調時被賦值。 
        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);
        if (ar != null) {    // 如果activity之前已經啟動,而且處於阻塞狀態,execStartActivity函數直接返回要啟動的activity的result或者null。(注意:這就是Activity.onActivityResult()會在啟動另外一個activity啟動時被回調的原因。
            // 若result非空,發送結果給本activity,即onActivityResult會被調用。
            mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                                            ar.getResultData());
        }
        if (requestCode >= 0) {
            // 如果這次啟動需要被啟動的activity返回一個結果,則在收到返回結果前,本activity保持不可見。
            mStartedActivity = true;
        }
 
        final View decor = mWindow != null ? mWindow.peekDecorView() : null;
        if (decor != null) {
            decor.cancelPendingInputEvents();
        }
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        //在ActivityGroup內部的Activity調用startActivity的時候會走到這里,內部處理邏輯和上面是類似的
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

Instrumentation類的功能是輔助Activity的監控和測試,接着看execStartActivity()函數的實現。

execStartActivity()@Instrumentation.java

 1 public ActivityResult execStartActivity(
 2         Context who, IBinder contextThread, IBinder token, Activity target,
 3         Intent intent, int requestCode, Bundle options) {
 4     //將contextThread轉成ApplicationThread.
 5     IApplicationThread whoThread = (IApplicationThread) contextThread;  6     if (mActivityMonitors != null) {
 7         synchronized (mSync) {
 8              //檢查是否存在這個activity
 9             final int N = mActivityMonitors.size();
10             for (int i=0; i<N; i++) {
11                  final ActivityMonitor am = mActivityMonitors.get(i);
12                  if (am.match(who, null, intent)) {
13                      am.mHits++;
14                      if (am.isBlocking()) {                       //若找到,而且處於阻塞狀態,直接返回。         
15                          return requestCode >= 0 ? am.getResult() : null;
16                      }
17                      break;
18                 }
19             }
20         }
21     }
22     try {
23         intent.migrateExtraStreamToClipData();     //轉移數據
24         intent.prepareToLeaveProcess();            //准備讓intent離開一個app進程
25         //通過AcitivityManagerNative與ActivityManagerService關聯起來,兩個類的關系如下圖,由ActivityManagerService去執行實際動作。
26         int result = ActivityManagerNative.getDefault() 27  .startActivity(whoThread, who.getBasePackageName(), intent,
28                     intent.resolveTypeIfNeeded(who.getContentResolver()),
29                     token, target != null ? target.mEmbeddedID : null,
30                     requestCode, 0, null, null, options);
31         //檢查啟動結果,如果無法打開activity,則拋出諸如ActivityNotFoundException類似的各種異常
32         checkStartActivityResult(result, intent);
33     } catch (RemoteException e) {
34     }
35     return null;
36 }

2. ActivityManager的功能是與系統中所有運行着的Activity交互提供了接口,主要的接口圍繞着運行中的進程信息,任務信息,服務信息等,它的大多數功能都是調用了ActivityManagerNative類接口來完成的。
ActivityManager相關靜態類圖如下圖,可以看出這是典型的Proxy模式:

 

    結合面的類結構圖,其中ActivityManager是一個客戶端,為了減少它與ActivityManagerService的耦合度,在這中間使用了ActivityManagerNative類,該類內部使用ActivityManagerProxy代理類,所有對 ActivityManagerService的訪問都轉換成對代理類的訪問,這樣ActivityManager就與ActivityManagerService解耦了。
    為了讓代理類與被代理類保持一致的接口,由IActivityManager作為ActivityManagerProxy和ActivityManagerNative的公共接口,ActivityManagerService繼承於ActivityManagerNative,也具有相同的接口。

圖中綠色的部分是在SDK中開放給應用程序開發人員的接口,藍色的部分是Proxy模式的實現,紅色的部分是底層的服務實現,是真正的動作執行者。

3. startActivity()@ActivityManagerService.java

 @Override
 public final int startActivity(IApplicationThread caller, String callingPackage,
           Intent intent, String resolvedType, IBinder resultTo,
           String resultWho, int requestCode, int startFlags,
           String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
     return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                                resultWho, requestCode, startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
 }
  
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
         Intent intent, String resolvedType, IBinder resultTo,
         String resultWho, int requestCode, int startFlags,
         String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
             false, true, "startActivity", null);
     // TODO: Switch to user app stacks here.
    return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
             null, null, options, userId);
}

類ActivityStackSupervisor是用來輔助ActivityManagerService對Activity和Task的管理的。其中用ActivityStackSupervisor類型來進行對Task的操作,用ActivityStack對Acitivity進行操作。

4. 調用mStackSupervisor.startActivityMayWait()函數后,會執行下面幾個函數,調用關系參照時序圖,函數里涉及很多細節,這里只簡單描述下它們的主要功能:

調用9. ActivityStackSupervisor.startActivityLocked():  檢查啟動權限,創建新的ActivityRecord。

調用10. ActivityStackSupervisor.startActivityUncheckedLocked():處理intent攜帶的launch flags, launchMode。(后面再研究launch相關的flag和mode)

調用11. ActivityStack.startActivityLocked():將activity放到所屬task的頂部,重置Task(resetTaskIfNeededLocked),調用WindowManager.setAppStartingWindow()。

調用13. ActivityStackSupervisor.resumeTopActivitiesLocked():判斷ActivityStack數組中是否存在target ActivityStack。

調用14. ActivityStack.resumeTopActivityLocked(): 從當前activity切換到要啟動的activity。

調用15. ActivityStackSupervisor.startSpecificActivityLocked():獲取ProcessRecord(若要啟動的activity的應用已經在運行),若獲取ProcessRecord存在則調用realStartActivityLocked(),否則調用 ActivityManagerServices.startProcessLocked()創建新的ProcessRecord,最后調用Process.start()啟動新的進程(最終調用Zygote啟動新的進程,為了避免混淆,這部分在時序圖中沒有體現,后面再研究)。

調用16. ActivityStackSupervisor.realStartActivityLocked(): 調用mWindowManager.setAppVisibility()設置app可見。

調用19. ActivityThread.scheduleLauncherActivity(): 發送Message LAUNCH_ACTIVITY給Handler.

5. Handler接收到message后,執行ActivityThread.handleLaunchActivity()。

handleLaunchActivity()@ActivityThread.java

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 
    ......
    Activity a = performLaunchActivity(r, customIntent);  // 返回一個activity.
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed);
        
        if (!r.activity.mFinished && r.startsNotResumed) {
            // 當這個activity沒有finished而且沒有處於resumed狀態時,Acivity Manager實際上想要這個activity以paused狀態開始,因為它需要可見,但是又不在前台。 
            // 為此,需要經過正常啟動(因為activity希望在它們的window被顯示前,它們第一次運行時通過onResume),然后暫停它。The activity manager actually wants this one to start out
//然而,在這種情況下,不需要走完整的暫停周期(比如freezing等),因為activity假定它可以剛好保留它當前的所有狀態。 try { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity);                ...... } catch (SuperNotCalledException e) { ...... } catch (Exception e) { ...... } r.paused = true; } } else { ...... } }

6.進一步看performLaunchActivity(),這個函數做了幾件重要的事情:創建activity實例,調用Activity.attach()設置參數,觸發Activity.onCreate()。

performLaunchActivity()@ActivityThread.java

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {        // 填充package info
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                                       Context.CONTEXT_INCLUDE_CODE);
    }

    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(mInitialApplication.getPackageManager());
        r.intent.setComponent(component);      //設置Component
    }
    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName,
        r.activityInfo.targetActivity);
    }

    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);    // 根據Activity的類名,通過Java反射機制創建對應的Activity.
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        ......
    }

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (activity != null) {
            Context appContext = createBaseContextForActivity(r, activity);      // Activity中getContext()函數返回的就是這個對象。
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            ......
            // 將Context,ActivityThread,Instrumentation,Application等設置給新建的Activity,供activity使用。
            activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config);

            if (customIntent != null) {
                 activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);                                             // 設置theme
            }
            
            activity.mCalled = false;
            mInstrumentation.callActivityOnCreate(activity, r.state);                  // 這個函數會使Activity的onCreate()函數被調用
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            if (!r.activity.mFinished) {
                activity.performStart();                                            // 這個函數會使Activity的onStart()函數被調用
                r.stopped = false;
            }
            if (!r.activity.mFinished) {
                if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                mInstrumentation.callActivityOnPostCreate(activity, r.state);
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;
        mActivities.put(r.token, r);
    } catch (SuperNotCalledException e) {
        ...... 
    } catch (Exception e) {
        ......
    }
    return activity;
}

7.下面分析下Activity.attach()函數,它創建window對象,設置window manager。

attach()@Activity.java

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);            // 把context賦值給父類的mBase成員

    mFragments.attachActivity(this, mContainer, null);

    mWindow = PolicyManager.makeNewWindow(this);            // 調用PolicyManager的函數創建Window對象。
    mWindow.setCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
        mWindow.setSoftInputMode(info.softInputMode);          //設置輸入法mode
    }
    if (info.uiOptions != 0) {
        mWindow.setUiOptions(info.uiOptions);
    }
    mUiThread = Thread.currentThread();
    // 賦值給Acitivity的各個成員
    mMainThread = aThread;                            //mMainThread實際上為ActivityThread。
    mInstrumentation = instr;
    mToken = token;
    mIdent = ident;
    mApplication = application;
    mIntent = intent;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mTitle = title;
    mParent = parent;
    mEmbeddedID = id;
    mLastNonConfigurationInstances = lastNonConfigurationInstances;

    // 創建WindowManager對象並設置給window,供window使用.
 mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                             mToken, mComponent.flattenToString(),
                             (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
        mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();   // 保存WindowManager對象.
    mCurrentConfig = config;
}

8. 其中一個關鍵的函數PolicyManager.makeNewWindow()返回的Window對象,實際上是一個PhoneWindow對象。

具體創建過程參考下面代碼:

class PolicyManager@PolicyManager.java

public final class PolicyManager {
    private static final String POLICY_IMPL_CLASS_NAME =
        "com.android.internal.policy.impl.Policy";

    private static final IPolicy sPolicy;      // sPolicy為單例的IPolicy對象。
    static {
        // Pull in the actual implementation of the policy at run-time
        try {
            Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
            sPolicy = (IPolicy)policyClass.newInstance();   // 創建Policy對象。
        } catch (ClassNotFoundException ex) {
            ......
        }
    }
    // Cannot instantiate this class
    private PolicyManager() {}

    // The static methods to spawn new policy-specific objects
    public static Window makeNewWindow(Context context) {
        return sPolicy.makeNewWindow(context);    //通過Policy對象的makeNewWindow創建一個Window。
    }
    ......
}

class Policy@Policy.java

public class Policy implements IPolicy {
    private static final String TAG = "PhonePolicy";

    private static final String[] preload_classes = {
        "com.android.internal.policy.impl.PhoneLayoutInflater",
        "com.android.internal.policy.impl.PhoneWindow",
        "com.android.internal.policy.impl.PhoneWindow$1",
        "com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback",
        "com.android.internal.policy.impl.PhoneWindow$DecorView",
        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
    };

    static {
        // For performance reasons, preload some policy specific classes when
        // the policy gets loaded.
        for (String s : preload_classes) {        // 加載所有的類
            try {
                Class.forName(s);
            } catch (ClassNotFoundException ex) {
                ......
            }
        }
    }
    public Window makeNewWindow(Context context) {
        return new PhoneWindow(context);                // 實際返回的PhoneWindow對象。
    }
    ......
}

9. setWindowManager()@Window.java

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
    mAppToken = appToken;
    mAppName = appName;
    mHardwareAccelerated = hardwareAccelerated || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
    if (wm == null) {
        wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
    }
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);             // 創建一個WindowManagerImpl對象
}

到這里可以看到,Activity成員變量mWindow實際上是PhoneWindow類型, 變量mWindowManager實際上是WindowManagerImpl。這

10. Acitivity.attach()函數被調用之后,performLaunchActivity還會觸發Activity.onCreate()函數被調用,在這個函數中會調用setContentView()函數設置Activity的UI內容。

setContentView()有三種實現,它們的功能基本一致,都是將view添加到mContentParent中:

setContentView()@Activity.java

// 通過一個布局資源設置activity的內容。 public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initActionBar(); } // 直接將View作為內容直接設置到activity的視圖層次中。這種方式設置給view的layoutparams將不起作用,默認為MATCH_PARENT. public void setContentView(View view) { getWindow().setContentView(view); initActionBar(); } // 設置activity的內容為view, 並設置view的LayoutParams. public void setContentView(View view, ViewGroup.LayoutParams params) { getWindow().setContentView(view, params); initActionBar(); }

下面給出其中一種實現:

setContentView()@PhoneWindow.java

public void setContentView(View view, ViewGroup.LayoutParams params) { if (mContentParent == null) { installDecor();                // 初始化DecorView和mContentParent. } else { mContentParent.removeAllViews(); } mContentParent.addView(view, params); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } }

installDecor()@PhoneWindow.java

private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); ...... } if (mContentParent == null) { mContentParent = generateLayout(mDecor); mTitleView = (TextView)findViewById(com.android.internal.R.id.title); // 創建標題欄  ...... } }

generateDecor()@PhoneWindow.java

protected DecorView generateDecor() { return new DecorView(getContext(), -1); // DecorView從FrameLayout派生,同時實現RootViewSurfaceTaker接口。 }

generateLayout()@PhoneWindow.java

protected ViewGroup generateLayout(DecorView decor) { ...... // Inflate the window decor. int layoutResource; // 根據情況獲取相應的標題欄資源ID。 int features = getLocalFeatures(); if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) { if (mIsFloating) { ...... layoutResource = res.resourceId; } ...... } mDecor.startChanging(); View in = mLayoutInflater.inflate(layoutResource, null);        //inflate 標題欄 decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); // 加入標題欄  ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); // ID_ANDROID_CONTENT:xml布局文件中main layout的ID, 實際上是mDecorView的一部分。  ...... mDecor.finishChanging(); return contentParent; }

findViewById()@Window.java

public View findViewById(int id) { return getDecorView().findViewById(id); }

通過上面的代碼可以看到,在Activity.onCreate()函數里調用setContentView設置的View,實際上會作為DecorView的子view。DecorView還處理了標題欄顯示等工作。 

addView()@ViewGroup.java

 

public void addView(View child, int index, LayoutParams params) {
    // addViewInner()函數中設置LayoutParams時會調用child.requestLayout(),在這里調用,為了在這里阻塞child的request.
 requestLayout();
    invalidate(true);     //在下一篇文章中會介紹這個函數
    addViewInner(child, index, params, false);
}

11. 我們接着看handleLaunchActivity()中的handleResumeActivity()函數,

handleResumeActivity()@ActivityThread.java

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) {
    ......
    ActivityClientRecord r = performResumeActivity(token, clearHide);          //會調用到Activity.onResume().

    if (r != null) {
        final Activity a = r.activity;
        final int forwardBit = isForward ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

        // If the window hasn't yet been added to the window manager,
        // and this guy didn't finish itself or start another activity,
        // then go ahead and add the window.
        // 若這個activity的window沒有加到window manager中,而且它沒有自己finish或者啟動另外一個acitivity,那就繼續,添加這個window.
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) {
            try {
                willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(a.getActivityToken());
            } catch (RemoteException e) {
            }
        }
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();                 // 獲得在attach()函數中創建出來的window對象。
            View decor = r.window.getDecorView();             // 獲得一個View對象
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();            // 獲得ViewManager對象       
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (a.mVisibleFromClient) {
                a.mWindowAdded = true;
                wm.addView(decor, l); // 添加View對象到WindowManager中。
            }
        } else if (!willBeVisible) { // 如果window已經被添加了,但在resume時啟動另外的activity,這個window將隱藏。
           r.hideForNow = true;
        }

        // Get rid of anything left hanging around.
        cleanUpPendingRemoveWindows(r);
// 如果window添加了,執行到這的時候就可見了。
        if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
            if (r.newConfig != null) {
                 performConfigurationChanged(r.activity, r.newConfig);
                 freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
                 r.newConfig = null;
             }
             WindowManager.LayoutParams l = r.window.getAttributes();
             if ((l.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != forwardBit) {
                 l.softInputMode = (l.softInputMode
                                    & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                                    | forwardBit;
                 if (r.activity.mVisibleFromClient) {
                     ViewManager wm = a.getWindowManager();
                     View decor = r.window.getDecorView();
                     wm.updateViewLayout(decor, l);      // 根據輸入法顯示模式調整winddow layout。
                 }
             }
             r.activity.mVisibleFromServer = true;
             mNumVisibleActivities++;
             if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
             }
        }

        if (!r.onlyLocalRequest) {
             r.nextIdle = mNewActivities;
             mNewActivities = r;
             Looper.myQueue().addIdleHandler(new Idler());
        }
        r.onlyLocalRequest = false;

        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
         }
     }
   } else {
         // If an exception was thrown when trying to resume, then just end this activity.
         // 如果resume過程出現異常,就finish這個activity.
         try {
                ActivityManagerNative.getDefault().finishActivity(token, Activity.RESULT_CANCELED, null);
         } catch (RemoteException ex) {
         }
    }
}

addView()@WindowManagerGlobal.java

public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { ...... ViewRootImpl root; View panelParentView = null; synchronized (mLock) { ...... root = new ViewRootImpl(view.getContext(), display);    // 創建ViewRootImpl對象  view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); } // do this last because it fires off messages to start doing things try { root.setView(view, wparams, panelParentView);          // setView()內調用requestLayout(). 在被加到WindowManager之前調度第一次layout,確保收到系統事件之前重新進行了布局。 } catch (RuntimeException e) { ...... } }

ViewRootImpl及setView()涉及到了UI繪制。啟動相關更多的細節在下一篇中進行分析。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM