1. 程式人生 > >Android 四大元件之——Acitivity(三) 深入瞭解Activity的啟動流程

Android 四大元件之——Acitivity(三) 深入瞭解Activity的啟動流程

上圖為整個Activity的啟動流程

接下來我們大概分析

 在我們的Android系統中,應用程式是由Launcher這個應用啟動起來的。當我們安裝好應用程式之後,就會在Launcher的介面上生成一個圖示,我們點選圖示時Launch就會啟動我們的應用程式。

1.點選圖示,launcher呼叫onClick方法

 /**
     * 
     * 
     * @param v      The view representing the clicked shortcut.  1.此處的view是指被點選的桌面圖示
     */
    public void onClick(View v) {
        // Make sure that rogue clicks don't get through while allapps is
        // launching, or after the
        // view has detached (it's possible for this to happen if the view is
        // removed mid touch).
        if (v.getWindowToken() == null) {
            return;
        }

        if (!mWorkspace.isFinishedSwitchingState()) {
            return;
        }

        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            // 開啟快捷方式對應的intent
            final Intent intent = ((ShortcutInfo) tag).intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0]
                    + v.getWidth(), pos[1] + v.getHeight()));

            boolean success = startActivitySafely(v, intent, tag);//2.同時呼叫startActivitySafely
if (success && v instanceof BubbleTextView) { mWaitingForResume = (BubbleTextView) v; mWaitingForResume.setStayPressed(true); } } else if (tag instanceof FolderInfo) { if (v instanceof FolderIcon) { // 開啟資料夾 FolderIcon fi = (FolderIcon) v; handleFolderClick(fi); } } else if (v == mAllAppsButton) { // 顯示或者不顯示“全部程式”介面 if (isAllAppsVisible()) { showWorkspace(true); } else { onClickAllAppsButton(v); } } }


2.在launcher的onClick方法裡呼叫了startActivitySafely()方法,見上述程式碼

boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        try {
            success = startActivity(v, intent, tag);  由此可見StartActivitySafely(),最終是呼叫startActivity()方法
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found,
                    Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
        }
        return success;
    }
 boolean startActivity(View v, Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        try {
            // Only launch using the new animation if the shortcut has not opted
            // out (this is a
            // private contract between launcher and may be ignored in the
            // future).
            boolean useLaunchAnimation = (v != null)
                    && !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
            if (useLaunchAnimation) {
                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v,
                        0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

                startActivity(intent, opts.toBundle());
            } else {
                startActivity(intent);
            }
            return true;
        } catch (SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found,
                    Toast.LENGTH_SHORT).show();
            Log.e(TAG,
                    "Launcher does not have the permission to launch "
                            + intent
                            + ". Make sure to create a MAIN intent-filter for the corresponding activity "
                            + "or use the exported attribute for this activity. "
                            + "tag=" + tag + " intent=" + intent, e);
        }
        return false;
    }
3.在startActivity()方法中,intent 添加了flag FLAG_ACTIVITY_NEW_TASK , 此標誌為建立新的任務棧,在建立目標 任務棧之前,首先會呼叫ActivityThread類啟動launcher的程序,然後啟動目標應用的任務棧,啟動完成之後,目標應用的任務棧會通知 ActivityThread呼叫launcher的onPause方法。此時,ActivityThread啟動新的應用程序(也就是目標應用的程序)。
4.目標應用的程序通過loadClass載入MainActivity,然後通過H(handler)來控制MainActivity的生命週期