Activity啟動(dòng)流程學(xué)習(xí)筆記

Zygote是什么?有什么作用?

Android系統(tǒng)底層基于Linux Kernel, 當(dāng)Kernel啟動(dòng)過程會(huì)創(chuàng)建init進(jìn)程, 該進(jìn)程是所有用戶空間的鼻祖, init進(jìn)程會(huì)啟動(dòng)ServiceManager(Binder服務(wù)管家)、 Zygote進(jìn)程(Java進(jìn)程的鼻祖)。Zygote進(jìn)程會(huì)創(chuàng)建 system_server進(jìn)程以及各種App進(jìn)程。

Zygote進(jìn)程:是Android系統(tǒng)的首個(gè)Java進(jìn)程,Zygote是所有Java進(jìn)程的父進(jìn)程,包括 system_server進(jìn)程以及所有的App進(jìn)程都是Zygote的子進(jìn)程,注意這里說的是子進(jìn)程,而非子線程。

我們都知道,每一個(gè)App其實(shí)都是

  • 一個(gè)單獨(dú)的Dalvik虛擬機(jī)
  • 一個(gè)單獨(dú)的進(jìn)程

所以當(dāng)系統(tǒng)里面的第一個(gè)Zygote進(jìn)程運(yùn)行之后,在這之后再開啟App,就相當(dāng)于開啟一個(gè)新的進(jìn)程。而為了實(shí)現(xiàn)資源共用和更快的啟動(dòng)速度,Android系統(tǒng)開啟新進(jìn)程的方式,是通過fork第一個(gè)Zygote進(jìn)程實(shí)現(xiàn)的。所以說,除了第一個(gè)Zygote進(jìn)程,其他應(yīng)用所在的進(jìn)程都是Zygote的子進(jìn)程,這下你明白為什么這個(gè)進(jìn)程叫“受精卵”了吧?因?yàn)榫拖袷且粋€(gè)受精卵一樣,它能快速的分裂,并且產(chǎn)生遺傳物質(zhì)一樣的細(xì)胞!

SystemServer是什么?有什么作用?它與zygote的關(guān)系是什么?

首先我要告訴你的是,SystemServer也是一個(gè)進(jìn)程,而且是由zygote進(jìn)程fork出來的。

知道了SystemServer的本質(zhì),我們對(duì)它就不算太陌生了,這個(gè)進(jìn)程是Android Framework里面兩大非常重要的進(jìn)程之一—另外一個(gè)進(jìn)程就是上面的zygote進(jìn)程。

為什么說SystemServer非常重要呢?因?yàn)橄到y(tǒng)里面重要的服務(wù)都是在這個(gè)進(jìn)程里面開啟的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看著是不是都挺眼熟的?

那么這些系統(tǒng)服務(wù)是怎么開啟起來的呢?

在zygote開啟的時(shí)候,會(huì)調(diào)用ZygoteInit.main()進(jìn)行初始化

public static void main(String argv[]) {

     ...ignore some code...

    //在加載首個(gè)zygote的時(shí)候,會(huì)傳入初始化參數(shù),使得startSystemServer = true
     boolean startSystemServer = false;
     for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            ...ignore some code...

         //開始fork我們的SystemServer進(jìn)程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }

     ...ignore some code...

}

ActivityManagerService是什么?什么時(shí)候初始化的?有什么作用?

ActivityManagerService,簡稱AMS,服務(wù)端對(duì)象,負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。

ActivityManagerService進(jìn)行初始化的時(shí)機(jī)很明確,就是在SystemServer進(jìn)程開啟的時(shí)候,就會(huì)初始化ActivityManagerService。從下面的代碼中可以看到

public final class SystemServer {

    //zygote的主入口
    public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }

    private void run() {

        ...ignore some code...

        //加載本地系統(tǒng)服務(wù)庫,并進(jìn)行初始化 
        System.loadLibrary("android_servers");
        nativeInit();

        // 創(chuàng)建系統(tǒng)上下文
        createSystemContext();

        //初始化SystemServiceManager對(duì)象,下面的系統(tǒng)服務(wù)開啟都需要調(diào)用SystemServiceManager.startService(Class<T>),這個(gè)方法通過反射來啟動(dòng)對(duì)應(yīng)的服務(wù)
        mSystemServiceManager = new SystemServiceManager(mSystemContext);

        //開啟服務(wù)
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        ...ignore some code...

    }

    //初始化系統(tǒng)上下文對(duì)象mSystemContext,并設(shè)置默認(rèn)的主題,mSystemContext實(shí)際上是一個(gè)ContextImpl對(duì)象。調(diào)用ActivityThread.systemMain()的時(shí)候,會(huì)調(diào)用ActivityThread.attach(true),而在attach()里面,則創(chuàng)建了Application對(duì)象,并調(diào)用了Application.onCreate()。
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

    //在這里開啟了幾個(gè)核心的服務(wù),因?yàn)檫@些服務(wù)之間相互依賴,所以都放在了這個(gè)方法里面。
    private void startBootstrapServices() {

        ...ignore some code...

        //初始化ActivityManagerService
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

        //初始化PowerManagerService,因?yàn)槠渌?wù)需要依賴這個(gè)Service,因此需要盡快的初始化
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // 現(xiàn)在電源管理已經(jīng)開啟,ActivityManagerService負(fù)責(zé)電源管理功能
        mActivityManagerService.initPowerManagement();

        // 初始化DisplayManagerService
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    //初始化PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
       mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

    ...ignore some code...

    }

}

經(jīng)過上面這些步驟,我們的ActivityManagerService對(duì)象已經(jīng)創(chuàng)建好了,并且完成了成員變量初始化。而且在這之前,調(diào)用createSystemContext()創(chuàng)建系統(tǒng)上下文的時(shí)候,也已經(jīng)完成了mSystemContext和ActivityThread的創(chuàng)建。注意,這是系統(tǒng)進(jìn)程開啟時(shí)的流程,在這之后,會(huì)開啟系統(tǒng)的Launcher程序,完成系統(tǒng)界面的加載與顯示。

你是否會(huì)好奇,我為什么說AMS是服務(wù)端對(duì)象?下面我給你介紹下Android系統(tǒng)里面的服務(wù)器和客戶端的概念。

其實(shí)服務(wù)器客戶端的概念不僅僅存在于Web開發(fā)中,在Android的框架設(shè)計(jì)中,使用的也是這一種模式。服務(wù)器端指的就是所有App共用的系統(tǒng)服務(wù),比如我們這里提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,這些基礎(chǔ)的系統(tǒng)服務(wù)是被所有的App公用的,當(dāng)某個(gè)App想實(shí)現(xiàn)某個(gè)操作的時(shí)候,要告訴這些系統(tǒng)服務(wù),比如你想打開一個(gè)App,那么我們知道了包名和MainActivity類名之后就可以打開

Intent intent = new Intent(Intent.ACTION_MAIN);  
intent.addCategory(Intent.CATEGORY_LAUNCHER);              
ComponentName cn = new ComponentName(packageName, className);              
intent.setComponent(cn);  
startActivity(intent); 

但是,我們的App通過調(diào)用startActivity()并不能直接打開另外一個(gè)App,這個(gè)方法會(huì)通過一系列的調(diào)用,最后還是告訴AMS說:“我要打開這個(gè)App,我知道他的住址和名字,你幫我打開吧!”所以是AMS來通知zygote進(jìn)程來fork一個(gè)新進(jìn)程,來開啟我們的目標(biāo)App的。這就像是瀏覽器想要打開一個(gè)超鏈接一樣,瀏覽器把網(wǎng)頁地址發(fā)送給服務(wù)器,然后還是服務(wù)器把需要的資源文件發(fā)送給客戶端的。

知道了Android Framework的客戶端服務(wù)器架構(gòu)之后,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進(jìn)程)還有zygote進(jìn)程分屬于三個(gè)獨(dú)立的進(jìn)程,他們之間如何通信呢?

App與AMS通過Binder進(jìn)行IPC通信,AMS(SystemServer進(jìn)程)與zygote通過Socket進(jìn)行IPC通信。

那么AMS有什么用呢?在前面我們知道了,如果想打開一個(gè)App的話,需要AMS去通知zygote進(jìn)程,除此之外,其實(shí)所有的Activity的開啟、暫停、關(guān)閉都需要AMS來控制,所以我們說,AMS負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。

在Android系統(tǒng)中,任何一個(gè)Activity的啟動(dòng)都是由AMS和應(yīng)用程序進(jìn)程(主要是ActivityThread)相互配合來完成的。AMS服務(wù)統(tǒng)一調(diào)度系統(tǒng)中所有進(jìn)程的Activity啟動(dòng),而每個(gè)Activity的啟動(dòng)過程則由其所屬的進(jìn)程具體來完成。

這樣說你可能還是覺得比較抽象,沒關(guān)系,下面有一部分是專門來介紹AMS與ActivityThread如何一起合作控制Activity的生命周期的。

Launcher是什么?什么時(shí)候啟動(dòng)的?

當(dāng)我們點(diǎn)擊手機(jī)桌面上的圖標(biāo)的時(shí)候,App就由Launcher開始啟動(dòng)了。但是,你有沒有思考過Launcher到底是一個(gè)什么東西?

Launcher本質(zhì)上也是一個(gè)應(yīng)用程序,和我們的App一樣,也是繼承自Activity

packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

public final class Launcher extends Activity
        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
                   View.OnTouchListener {
                   }1234

Launcher實(shí)現(xiàn)了點(diǎn)擊、長按等回調(diào)接口,來接收用戶的輸入。既然是普通的App,那么我們的開發(fā)經(jīng)驗(yàn)在這里就仍然適用,比如,我們點(diǎn)擊圖標(biāo)的時(shí)候,是怎么開啟的應(yīng)用呢?如果讓你,你怎么做這個(gè)功能呢?捕捉圖標(biāo)點(diǎn)擊事件,然后startActivity()發(fā)送對(duì)應(yīng)的Intent請(qǐng)求唄!是的,Launcher也是這么做的,就是這么easy!

那么到底是處理的哪個(gè)對(duì)象的點(diǎn)擊事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件呀,是的,我找到了布局文件launcher.xml


為了方便查看,我刪除了很多代碼,從上面這些我們應(yīng)該可以看出一些東西來:Launcher大量使用標(biāo)簽來實(shí)現(xiàn)界面的復(fù)用,而且定義了很多的自定義控件實(shí)現(xiàn)界面效果,dock_divider從布局的參數(shù)聲明上可以猜出,是底部操作欄和上面圖標(biāo)布局的分割線,而paged_view_indicator則是頁面指示器,和App首次進(jìn)入的引導(dǎo)頁下面的界面引導(dǎo)是一樣的道理。當(dāng)然,我們最關(guān)心的是Workspace這個(gè)布局,因?yàn)樽⑨尷锩嬲f在這里面包含了5個(gè)屏幕的單元格,想必你也猜到了,這個(gè)就是在首頁存放我們圖標(biāo)的那五個(gè)界面(不同的ROM會(huì)做不同的DIY,數(shù)量不固定)。

CellLayout確實(shí)是繼承自ViewGroup。在CellLayout里面,只放了一個(gè)子View,那就是ShortcutAndWidgetContainer。從名字也可以看出來,ShortcutAndWidgetContainer這個(gè)類就是用來存放快捷圖標(biāo)Widget小部件的,那么里面放的是什么對(duì)象呢?

在桌面上的圖標(biāo),使用的是BubbleTextView對(duì)象,這個(gè)對(duì)象在TextView的基礎(chǔ)之上,添加了一些特效,比如你長按移動(dòng)圖標(biāo)的時(shí)候,圖標(biāo)位置會(huì)出現(xiàn)一個(gè)背景(不同版本的效果不同),所以我們找到BubbleTextView對(duì)象的點(diǎn)擊事件,就可以找到Launcher如何開啟一個(gè)App了。

除了在桌面上有圖標(biāo)之外,在程序列表中點(diǎn)擊圖標(biāo),也可以開啟對(duì)應(yīng)的程序。這里的圖標(biāo)使用的不是BubbleTextView對(duì)象,而是PagedViewIcon對(duì)象,我們?nèi)绻业剿狞c(diǎn)擊事件,就也可以找到Launcher如何開啟一個(gè)App。

其實(shí)說這么多,和今天的主題隔著十萬八千里,上面這些東西,你有興趣就看,沒興趣就直接跳過,不知道不影響這篇文章閱讀。

BubbleTextView的點(diǎn)擊事件在哪里呢?我來告訴你:在Launcher.onClick(View v)里面。

public void onClick(View v) {
        ...ignore some code...

        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            // Open shortcut
            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()));
        //開始開啟Activity咯~
            boolean success = startActivitySafely(v, intent, tag);

            if (success && v instanceof BubbleTextView) {
                mWaitingForResume = (BubbleTextView) v;
                mWaitingForResume.setStayPressed(true);
            }
        } else if (tag instanceof FolderInfo) {
            //如果點(diǎn)擊的是圖標(biāo)文件夾,就打開文件夾
            if (v instanceof FolderIcon) {
                FolderIcon fi = (FolderIcon) v;
                handleFolderClick(fi);
            }
        } else if (v == mAllAppsButton) {
        ...ignore some code...
        }
    }

從上面的代碼我們可以看到,在桌面上點(diǎn)擊快捷圖標(biāo)的時(shí)候,會(huì)調(diào)用

startActivitySafely(v, intent, tag);

那么從程序列表界面,點(diǎn)擊圖標(biāo)的時(shí)候會(huì)發(fā)生什么呢?實(shí)際上,程序列表界面使用的是AppsCustomizePagedView對(duì)象,所以我在這個(gè)類里面找到了onClick(View v)。

public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
        View.OnClickListener,View.OnKeyListener,DragSource,PagedViewIcon.PressedCallback, 
        PagedViewWidget.ShortPressListener, LauncherTransitionable {

    @Override
    public void onClick(View v) {
        ...
        
        if (v instanceof PagedViewIcon) {
            mLauncher.updateWallpaperVisibility(true);
            mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
        } else if (v instanceof PagedViewWidget) {
                 ...ignore some code..
        }
    }      
}

可以看到,調(diào)用的是

mLauncher.startActivitySafely(v, appInfo.intent, appInfo);

和上面一樣!這叫什么?這叫殊途同歸!

所以咱們現(xiàn)在又明白了一件事情:不管從哪里點(diǎn)擊圖標(biāo),調(diào)用的都是Launcher.startActivitySafely()。

  • 下面我們就可以一步步的來看一下Launcher.startActivitySafely()到底做了什么事情。
boolean startActivitySafely(View v, Intent intent, Object tag) {
    boolean success = false;
    try {
        success = startActivity(v, intent, tag);
    } catch (ActivityNotFoundException e) {
        Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();           
    }
    return success;
}

調(diào)用了startActivity(v, intent, tag)

boolean startActivity(View v, Intent intent, Object tag) {

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);

            if (useLaunchAnimation) {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    startActivity(intent, opts.toBundle());
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(),
                            opts.toBundle());
                }
            } else {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    startActivity(intent);
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(), null);
                }
            }
            return true;
        } catch (SecurityException e) {
        ...
        }
        return false;
}

這里會(huì)調(diào)用Activity.startActivity(intent, opts.toBundle()),這個(gè)方法熟悉嗎?這就是我們經(jīng)常用到的Activity.startActivity(Intent)的重載函數(shù)。而且由于設(shè)置了

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

所以這個(gè)Activity會(huì)添加到一個(gè)新的Task棧中,而且,startActivity()調(diào)用的其實(shí)是startActivityForResult()這個(gè)方法。

@Override
public void startActivity(Intent intent, @Nullable 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);
        }
}

所以我們現(xiàn)在明確了,Launcher中開啟一個(gè)App,其實(shí)和我們?cè)贏ctivity中直接startActivity()基本一樣,都是調(diào)用了Activity.startActivityForResult()。

Instrumentation是什么?和ActivityThread是什么關(guān)系?

還記得前面說過的Instrumentation對(duì)象嗎?每個(gè)Activity都持有Instrumentation對(duì)象的一個(gè)引用,但是整個(gè)進(jìn)程只會(huì)存在一個(gè)Instrumentation對(duì)象。當(dāng)startActivityForResult()調(diào)用之后,實(shí)際上還是調(diào)用了mInstrumentation.execStartActivity()

public void startActivityForResult(Intent intent, int requestCode, @Nullable 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());
            }
            ...ignore some code...    
        } else {
            if (options != null) {
                 //當(dāng)現(xiàn)在的Activity有父Activity的時(shí)候會(huì)調(diào)用,但是在startActivityFromChild()內(nèi)部實(shí)際還是調(diào)用的mInstrumentation.execStartActivity()
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
         ...ignore some code...    
    }

下面是mInstrumentation.execStartActivity()的實(shí)現(xiàn)

 public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...ignore some code...
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        int result = ActivityManagerNative.getDefault()
                        .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
    }
    return null;
}

所以當(dāng)我們?cè)诔绦蛑姓{(diào)用startActivity()的 時(shí)候,實(shí)際上調(diào)用的是Instrumentation的相關(guān)的方法。

Instrumentation意為“儀器”,我們先看一下這個(gè)類里面包含哪些方法吧


我們可以看到,這個(gè)類里面的方法大多數(shù)和Application和Activity有關(guān),是的,這個(gè)類就是完成對(duì)Application和Activity初始化和生命周期的工具類。比如說,我單獨(dú)挑一個(gè)callActivityOnCreate()讓你看看

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}

對(duì)activity.performCreate(icicle);這一行代碼熟悉嗎?這一行里面就調(diào)用了傳說中的Activity的入口函數(shù)onCreate(),不信?接著往下看Activity.performCreate()

final void performCreate(Bundle icicle) {
    onCreate(icicle);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

沒騙你吧,onCreate在這里調(diào)用了吧。但是有一件事情必須說清楚,那就是這個(gè)Instrumentation類這么重要,為啥我在開發(fā)的過程中,沒有發(fā)現(xiàn)他的蹤跡呢?

是的,Instrumentation這個(gè)類很重要,對(duì)Activity生命周期方法的調(diào)用根本就離不開他,他可以說是一個(gè)大管家,但是,這個(gè)大管家比較害羞,是一個(gè)女的,管內(nèi)不管外,是老板娘~

那么你可能要問了,老板是誰呀?
老板當(dāng)然是大名鼎鼎的ActivityThread了

public final class ActivityThread {//沒有繼承或者實(shí)現(xiàn)其他類。

    final ApplicationThread mAppThread = new ApplicationThread();
    
    public ApplicationThread getApplicationThread(){
        return mAppThread;
    }

    //ActivityThread的內(nèi)部類ApplicationThread 
    private class ApplicationThread extends ApplicationThreadNative {
    ......
    }
}

ApplicationThreadNative就是相當(dāng)于AIDL通訊中的Stub,也就是服務(wù)端,ApplicationThreadProxy即AIDL通訊中的Proxy,也就是客戶端。所以ApplicationThread是通訊的具體實(shí)現(xiàn)類。

ActivityThread你都沒聽說過?那你肯定聽說過傳說中的UI線程吧?是的,這就是UI線程。我們前面說過,App和AMS是通過Binder傳遞信息的,那么ActivityThread就是專門與AMS的外交工作的

AMS說:“ActivityThread,你給我暫停一個(gè)Activity!”
ActivityThread就說:“沒問題!”然后轉(zhuǎn)身和Instrumentation說:“老婆,AMS讓暫停一個(gè)Activity,我這里忙著呢,你快去幫我把這事辦了把~”
于是,Instrumentation就去把事兒搞定了。

所以說,AMS是董事會(huì),負(fù)責(zé)指揮和調(diào)度的,ActivityThread是老板,雖然說家里的事自己說了算,但是需要聽從AMS的指揮,而Instrumentation則是老板娘,負(fù)責(zé)家里的大事小事,但是一般不拋頭露面,聽一家之主ActivityThread的安排

如何理解AMS和ActivityThread之間的Binder通信?

前面我們說到,在調(diào)用startActivity()的時(shí)候,實(shí)際上調(diào)用的是

mInstrumentation.execStartActivity()

但是到這里還沒完呢!里面又調(diào)用了下面的方法

ActivityManagerNative.getDefault().startActivity()

這里的ActivityManagerNative.getDefault返回的就是ActivityManagerService的遠(yuǎn)程接口,即ActivityManagerProxy

怎么知道的呢?往下看

public abstract class ActivityManagerNative extends Binder implements IActivityManager{

    //從類聲明上,可以看到ActivityManagerNative是Binder的一個(gè)子類,而且實(shí)現(xiàn)了IActivityManager接口
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

    //通過單例模式獲取一個(gè)IActivityManager對(duì)象,這個(gè)對(duì)象通過asInterface(b)獲得
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            IActivityManager am = asInterface(b);
            return am;
        }
    };

    //最終返回的還是一個(gè)ActivityManagerProxy對(duì)象
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        
        if (in != null) {
            return in;
        }

     //這里面的Binder類型的obj參數(shù)會(huì)作為ActivityManagerProxy的成員變量保存為mRemote成員變量,負(fù)責(zé)進(jìn)行IPC通信
        return new ActivityManagerProxy(obj);
    }
}
 public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
}

再看ActivityManagerProxy.startActivity(),在這里面做的事情就是IPC通信,利用Binder對(duì)象,調(diào)用transact(),把所有需要的參數(shù)封裝成Parcel對(duì)象,向AMS發(fā)送數(shù)據(jù)進(jìn)行通信

ActivityManagerProxy經(jīng)過Binder IPC,進(jìn)入ActivityManagerNative。接下來程序進(jìn)入了system_servr進(jìn)程,開始繼續(xù)執(zhí)行。接下來程序進(jìn)入了system_servr進(jìn)程,開始繼續(xù)執(zhí)行。

transact方法是一個(gè)本地方法;它的實(shí)現(xiàn)在native層,具體來說在frameworks/base/core/jni/android_util_Binder.cpp文件,里面進(jìn)行了一系列的函數(shù)調(diào)用它最終調(diào)用到了talkWithDriver函數(shù);看這個(gè)函數(shù)的名字就知道,通信過程要交給驅(qū)動(dòng)完成了;這個(gè)函數(shù)最后通過ioctl系統(tǒng)調(diào)用,Client進(jìn)程陷入內(nèi)核態(tài),Client調(diào)用add方法的線程掛起等待返回;驅(qū)動(dòng)完成一系列的操作之后喚醒Server進(jìn)程,調(diào)用了Server進(jìn)程本地對(duì)象的onTransact函數(shù)(實(shí)際上由Server端線程池完成)。Binder本地對(duì)象的onTransact方法(這里就是Stub類里面的此方法)

ActivityManagerService本質(zhì)就是一個(gè)Binder,并且實(shí)體在服務(wù)端。AMS在遠(yuǎn)端操作著Activity的生命周期。這個(gè)進(jìn)程由SystemServer進(jìn)程fork出來。

ActivityThread。大家都知道ActivityThread就是應(yīng)用的UI線程,main方法就是整個(gè)應(yīng)用的入口。ActivityThread本質(zhì)并不是一個(gè)線程,他只是依附著主線程存在。ActivityThread通過和AMS進(jìn)行IPC通信來共同管理Activity的生命周期。在后面我準(zhǔn)備寫一篇關(guān)于Handle的續(xù)篇,里面還會(huì)提到他,因?yàn)橹骶€程里面的Looper就是在這里init的。

ApplicationThread。它是ActivityThread的內(nèi)部類,本質(zhì)上ActivityThread是通過它來進(jìn)行和AMS的IPC通信的。它的本質(zhì)也是一個(gè)Binder!只不過這次他的實(shí)體放在客戶端,AMS通過他的代理類ApplicationThreadProxy來和ApplicationThread通信。

Instrumentation。這個(gè)類我在看完第一遍書的時(shí)候感覺操作調(diào)用鏈里面的最外層。因?yàn)樽詈笠徊紸ctivity實(shí)例對(duì)象的生成和onCreat()方法的調(diào)用最終是來自這個(gè)類的。其實(shí)這個(gè)類是ActivityThread想要進(jìn)行的操作的具體操作類。這個(gè)類是全局的,并且每個(gè)Acitivity里面都擁有一個(gè)它的引用。

對(duì)Binder的理解

Binder本質(zhì)上只是一種底層通信方式,和具體服務(wù)沒有關(guān)系。為了提供具體服務(wù),Server必須提供一套接口函數(shù)以便Client通過遠(yuǎn)程訪問使用各種服務(wù)。這時(shí)通常采用Proxy設(shè)計(jì)模式:將接口函數(shù)定義在一個(gè)抽象類中,Server和Client都會(huì)以該抽象類為基類實(shí)現(xiàn)所有接口函數(shù),所不同的是Server端是真正的功能實(shí)現(xiàn),而Client端是對(duì)這些函數(shù)遠(yuǎn)程調(diào)用請(qǐng)求的包裝

為了更方便的說明客戶端和服務(wù)器之間的Binder通信,下面以ActivityManagerServices和他在客戶端的代理類ActivityManagerProxy為例。

ActivityManagerServices和ActivityManagerProxy都實(shí)現(xiàn)了同一個(gè)接口——IActivityManager。

ActivityManagerNative.getDefault()就是ActivityManagerService的代理類!AMS和代理類本質(zhì)上都是IActivityManager的實(shí)現(xiàn)類。

class ActivityManagerProxy implements IActivityManager{}

public final class ActivityManagerService extends ActivityManagerNative{}

public abstract class ActivityManagerNative extends Binder implements IActivityManager{}

雖然都實(shí)現(xiàn)了同一個(gè)接口,但是代理對(duì)象ActivityManagerProxy并不會(huì)對(duì)這些方法進(jìn)行真正地實(shí)現(xiàn),ActivityManagerProxy只是通過這種方式對(duì)方法的參數(shù)進(jìn)行打包(因?yàn)槎紝?shí)現(xiàn)了相同接口,所以可以保證同一個(gè)方法有相同的參數(shù),即對(duì)要傳輸給服務(wù)器的數(shù)據(jù)進(jìn)行打包),真正實(shí)現(xiàn)的是ActivityManagerService。

但是這個(gè)地方并**不是直接由客戶端傳遞給服務(wù)器,而是通過Binder驅(qū)動(dòng)進(jìn)行中轉(zhuǎn)。其實(shí)我對(duì)Binder驅(qū)動(dòng)并不熟悉,我們就把他當(dāng)做一個(gè)中轉(zhuǎn)站就OK,客戶端調(diào)用ActivityManagerProxy接口里面的方法,把數(shù)據(jù)傳送給Binder驅(qū)動(dòng),然后Binder驅(qū)動(dòng)就會(huì)把這些東西轉(zhuǎn)發(fā)給服務(wù)器的ActivityManagerServices,由ActivityManagerServices去真正的實(shí)施具體的操作。

但是Binder只能傳遞數(shù)據(jù),并不知道是要調(diào)用ActivityManagerServices的哪個(gè)方法,所以在數(shù)據(jù)中會(huì)添加方法的唯一標(biāo)識(shí)碼,比如前面的startActivity()方法:

public int startActivity() throws RemoteException {
    ...
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
}

上面的START_ACTIVITY_TRANSACTION就是方法標(biāo)示,data是要傳輸給Binder驅(qū)動(dòng)的數(shù)據(jù),reply則接受操作的返回值。

客戶端:ActivityManagerProxy =====>Binder驅(qū)動(dòng)=====> ActivityManagerService:服務(wù)器

而且由于繼承了同樣的公共接口類,ActivityManagerProxy提供了與ActivityManagerService一樣的函數(shù)原型,使用戶感覺不出Server是運(yùn)行在本地還是遠(yuǎn)端,從而可以更加方便的調(diào)用這些重要的系統(tǒng)服務(wù)。

但是!這里Binder通信是單方向的,即從ActivityManagerProxy指向ActivityManagerService的,如果AMS想要通知ActivityThread做一些事情,應(yīng)該咋辦呢?

還是通過Binder通信,不過是換了另外一對(duì),換成了ApplicationThread和ApplicationThreadProxy。

客戶端:ApplicationThread <=====Binder驅(qū)動(dòng)<===== ApplicationThreadProxy:服務(wù)器

他們也都實(shí)現(xiàn)了相同的接口IApplicationThread

private class ApplicationThread extends ApplicationThreadNative {}

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}

class ApplicationThreadProxy implements IApplicationThread {}12345

AMS接收到客戶端的請(qǐng)求之后,會(huì)如何開啟一個(gè)Activity?

ActivityStack(AMS中)。很好懂,一個(gè)Activity棧。但是這個(gè)ActivityStack是有兩種類型的,一種叫系統(tǒng)ActivityStack(HomeTask),這一類的ActivityStack包含著Launcher(或者有其他我不知道的),還有一種是普通應(yīng)用的ActivityStack(安卓中Task這個(gè)概念的具體實(shí)現(xiàn)形式),其實(shí)就是一個(gè)Task(任務(wù)棧)。這個(gè)類是由AMS來管理,AMS通過這個(gè)數(shù)據(jù)結(jié)構(gòu)來得知Activity的狀態(tài)。

ActivityStackSuperisor(AMS中)。加了一個(gè)單詞,就是Activity棧的管理者。這個(gè)類的作用就是管理?xiàng)#⑶彝ㄟ^ActivityStack來獲得要啟動(dòng)的activity的信息。

ActivityRecord。這個(gè)就是上面說的服務(wù)端的Actiivty信息的載體類。并且也是服務(wù)端的類~這個(gè)類相當(dāng)?shù)闹匾允贾两K都貫穿在調(diào)用鏈里面,在安卓ActivityStack里面存儲(chǔ)的并不是activity實(shí)例,其實(shí)就是這個(gè)ActivityRecord的實(shí)例。

ActivityClientRecord。這個(gè)和上面區(qū)別就是這個(gè)類是客戶端activity信息的載體類。

TaskRecord。同樣,這個(gè)類就是ActivityTask的信息記錄類而已。

至此,點(diǎn)擊桌面圖標(biāo)調(diào)用startActivity(),終于把數(shù)據(jù)和要開啟Activity的請(qǐng)求發(fā)送到了AMS了。說了這么多,其實(shí)這些都在一瞬間完成了,下面咱們研究下AMS到底做了什么。

AMS收到startActivity的請(qǐng)求之后,會(huì)按照如下的方法鏈進(jìn)行調(diào)用

注意,從這里開始,調(diào)用鏈會(huì)變得很復(fù)雜

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
      //調(diào)用了startActivityAsUser,caller是我們的ApplicaitonThread
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
}

繼續(xù)看這個(gè)startActivityAsUser()方法:

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {

        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,false, ALLOW_FULL_ONLY, "startActivity", null);
        
        // TODO: Switch to user app stacks here. caller是我們的ApplicaitonThread
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, userId, null, null);
}

startActivityAsUser()方法中調(diào)用了ActivityStackSupervisor的startActivityMayWait()方法。這里的目的就是想去通過棧的管理者來通過傳進(jìn)來的數(shù)據(jù)去改變棧,并且拿到被啟動(dòng)Activity的ActivityRecord實(shí)例

startActivityMayWait()里面,主要做了ActivityStack、ActivityInfo、 LaunchMode等等各種信息的初始化工作,然后就又調(diào)用了startActivityLocked()方法, 這個(gè)方法里面又做了一系列的變量初始化,初始啟動(dòng)的錯(cuò)誤判斷, UID檢查之后,又調(diào)用了startActivityUncheckedLocked()方法。這個(gè)方法里面根據(jù)前面一系列的工作,確定了最終的LanuchMode,這個(gè)LaunchMode會(huì)在后面的函數(shù)被拿來進(jìn)行判斷,構(gòu)建了一個(gè)新的Intent、ActivityInfo、ActivityTask。

ActivityStarter

startActivityMayWait方法根據(jù)Intent在系統(tǒng)中找到合適的應(yīng)用的Activity,如果有多個(gè)Activity可選擇,
則會(huì)彈出ResolverActivity讓用戶選擇合適的應(yīng)用。再調(diào)用startActivityLocked方法

在startActivityLocked方法里,對(duì)傳過來的參數(shù)做一些校驗(yàn),然后創(chuàng)建ActivityRecord對(duì)象,再調(diào)用startActivityUnchecked方法啟動(dòng)Activity。

startActivityUnchecked方法負(fù)責(zé)調(diào)度ActivityRecord和Task,理解該方法是理解Actvity啟動(dòng)模式的關(guān)鍵。

startActivityUnchecked方法調(diào)度Task的算法非常復(fù)雜,和當(dāng)前回退棧,要啟動(dòng)的acitivity的啟動(dòng)模式以及taskAffinity屬性,啟動(dòng)activity時(shí)設(shè)置的intent的flag等諸多要素相關(guān),intent的flag就有很多種情況,故此算法非常復(fù)雜,需要閱讀源碼并結(jié)合特定啟動(dòng)情況才能理解。

ActivityStarter的startActivityUnchecked() 方法調(diào)用ActivityStack的startActivityLocked()

//同時(shí)調(diào)用WindowManager準(zhǔn)備App切換相關(guān)的工作

//ActivityStarter
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask){

    //ActivityStack的startActivityLocked,同時(shí)調(diào)用WindowManager準(zhǔn)備App切換相關(guān)的工作
    mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);

    if (mDoResume) {
     final ActivityRecord topTaskActivity =mStartActivity.task.topRunningActivityLocked();
        
        if (!mTargetStack.isFocusable()|| (topTaskActivity != null &&                               topTaskActivity.mTaskOverlay&& mStartActivity != topTaskActivity)) {
            ...
        } else {
            //最終調(diào)用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
            mOptions);
        }
    }
}

ActivityStack

接下來調(diào)用ActivityStack的startActivityLocked將ActivityRecord加入到回退棧里。最終調(diào)用ActivityStackSupervisorresumeFocusedStackTopActivityLocked()方法。

待啟動(dòng)Activity對(duì)應(yīng)的Task為前臺(tái)Task時(shí),調(diào)用該Task對(duì)應(yīng)ActivityStack的resumeTopActivityUncheckedLocked函數(shù)。
接著跟進(jìn)ActivityStack

//ActivityStack
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    return result;
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev,ActivityOptions options){

    //mResumedActivity指向上一次啟動(dòng)的Activity(Launcher)
    if (mResumedActivity != null) {
        ...
        //通知Launcher進(jìn)入pause狀態(tài)
        pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
    }
    
    if (pausing) {//Launcher已經(jīng)暫停了
        ...
        if (next.app != null && next.app.thread != null) {
            //如果app已經(jīng)啟動(dòng)過
            //調(diào)用淘寶(待啟動(dòng))Activity所在進(jìn)程的優(yōu)先級(jí),保證其不被kill
            mService.updateLruProcessLocked(next.app, true, null);
        }

    } 
    
    ...
    if (next.app != null && next.app.thread != null) {
        //如果Intent不為空,調(diào)用NewIntent方法傳入Intent
        next.app.thread.scheduleNewIntent(next.newIntents, next.appToken, false);

        //若淘寶已經(jīng)啟動(dòng),點(diǎn)擊Home鍵返回到Launcher,再次從Launcher啟動(dòng)淘寶(或者第三方啟動(dòng)已開啟的App)
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);
    } else {
        //創(chuàng)建進(jìn)程,冷啟動(dòng)Activity。或者已啟動(dòng)App,重新啟動(dòng)Activity
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    return true;
}

繼續(xù)看resumeTopActivityInnerLocked(prev, options);這個(gè)方法太長了,我分析了一整天,終于所有體會(huì)吧。這個(gè)方法最終的作用是將啟動(dòng)者Activity的生命周期變成paused,這樣之后被啟動(dòng)的Activity的實(shí)例創(chuàng)建了之后才能順利的resumed。

resumeTopActivityInnerLocked函數(shù)非常繁瑣,但整體來講應(yīng)該只有兩個(gè)比較關(guān)鍵的地方:

  1. 判斷是否已有Activity(mResumedActivity)啟動(dòng)(即Launcher,通過Launcher啟動(dòng)淘寶的),有則暫停該Activity
  2. 判斷是否需要重新啟動(dòng)目標(biāo)Activity,即Activity是否已經(jīng)啟動(dòng)過。(例如保存在后臺(tái),應(yīng)用切換)

2.AMS記錄要啟動(dòng)的Activity信息,并且通知Launcher進(jìn)入pause狀態(tài)。
3.Launcher進(jìn)入pause狀態(tài)后,通知AMS已經(jīng)paused了,可以啟動(dòng)淘寶了。

最終在函數(shù)的末尾會(huì)又調(diào)用ActivityStackSupervisor的startSpecificActivityLocked(next, true, true);方法。

創(chuàng)建進(jìn)程

接下來的操作就比較重要了,創(chuàng)建進(jìn)程,啟動(dòng)Activity。

//ActivityStackSupervisor

void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig){

        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {

                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                //目標(biāo)Activity的App已經(jīng)啟動(dòng)(存在ActivityThread),則重啟Activity
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
               ...
            }
        }

        //如果進(jìn)程不存在,則通過zygote創(chuàng)建應(yīng)用進(jìn)程。
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
}

從上面代碼可以了解到startSpecificActivityLocked為啟動(dòng)Activity的兩種不同情況

  • 例如從Launcher冷啟動(dòng)淘寶,則需要?jiǎng)?chuàng)建新進(jìn)程,通過AMS調(diào)用Zygote(孕育天地)孵化應(yīng)用進(jìn)程。
  • 如果淘寶App已經(jīng)啟動(dòng),例如從MainActivity跳轉(zhuǎn)到LoginActivity,則通過realStartActivityLocked啟動(dòng)。

因?yàn)槲覀冮_頭以Launcher啟動(dòng)淘寶為例子,所以我們硬著頭皮繼續(xù)分析AMS創(chuàng)建進(jìn)程以及Activity的綁定過程。
上面分析到mService.startProcessLocked,到了這里我們直接看啟動(dòng)線程的方法,中間的過程實(shí)在是略復(fù)雜。

4.淘寶App未開啟過,所以AMS啟動(dòng)新的進(jìn)程,并且在新進(jìn)程中創(chuàng)建ActivityThread對(duì)象,執(zhí)行其中的main函數(shù)方法。

Zygote進(jìn)程孵化出新的應(yīng)用進(jìn)程后,通過反射執(zhí)行ActivityThread類的main方法。在該方法里會(huì)先準(zhǔn)備好Looper和消息隊(duì)列,然后調(diào)用attach方法將應(yīng)用進(jìn)程綁定到AMS,然后進(jìn)入loop循環(huán),不斷地讀取消息隊(duì)列里的消息,并分發(fā)消息

至此,進(jìn)程創(chuàng)建完畢,并且也有了主線程,剩下的便是啟動(dòng)Activity和關(guān)聯(lián)Context等初始化操作了。

淘寶app主線程啟動(dòng)完畢后通知AMS,并傳入applicationThread以便通訊。

//ActivityThread
public static void main(String[] args) {
    ...
    //準(zhǔn)備主線程的Looper,下篇博文分析Handler,Looper
    Looper.prepareMainLooper();

    //創(chuàng)建當(dāng)前進(jìn)程的ActivityThread
    ActivityThread thread = new ActivityThread();

    //將該進(jìn)程綁定到AMS
    thread.attach(false);

    if (sMainThreadHandler == null) {
    //保存進(jìn)程對(duì)應(yīng)的主線程Handler
        sMainThreadHandler = thread.getHandler();
    }

    ...
    //進(jìn)入主線程的消息循環(huán)
    Looper.loop();
    ...
}

//上面說過,ApplicationThread是ActivityThread用來與AMS通訊的中介
final ApplicationThread mAppThread = new ApplicationThread();

private void attach(boolean system) {
    if (!system) {
        final IActivityManager mgr = ActivityManagerNative.getDefault();

        //調(diào)用AMS的attachApplication方法,將ApplicationThread對(duì)象綁定至ActivityManagerService
        //這樣AMS就可以通過ApplicationThread代理對(duì)象控制應(yīng)用進(jìn)程
        mgr.attachApplication(mAppThread);
    } else {
        ...
    }
}

AMS啟動(dòng)Activity小結(jié)

至此通過下圖總結(jié)一下在AMS啟動(dòng)Activity的大致流程,各個(gè)方法函數(shù)像一臺(tái)機(jī)器上的不同零件,各盡其責(zé),分工明確。
雖然錯(cuò)綜復(fù)雜,但是耦合性低,比如說啟動(dòng)模式需要優(yōu)化,重新完善startActivityUnchecked方法函數(shù)即可。

這里寫圖片描述

AMS.attachApplicationLocked() 關(guān)聯(lián)Activity

在這個(gè)時(shí)候,雖然有了App進(jìn)程和主線程,但是仍是一副空殼。
沒有Activity信息,沒有關(guān)聯(lián)上下文,這時(shí)候就要請(qǐng)出AMS來進(jìn)行指揮。

此時(shí)的App應(yīng)用–>
這里寫圖片描述

因?yàn)橹骶€程main入口通過attach方法將 ApplicationThread 發(fā)送給 AMS ,所以通過applicationThread這個(gè)橋梁來通知ActivityThread創(chuàng)建/關(guān)聯(lián)和啟動(dòng)Activity

//AMS
@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        //獲取applicationThread的進(jìn)程id(也就是淘寶應(yīng)用進(jìn)程)
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

通過Binder獲取proxy(ApplicationThread )方的進(jìn)程id,也就是獲取目標(biāo)(淘寶)進(jìn)程的Pid。

//Binder
public static final native int getCallingPid();

接下來重點(diǎn)分析attachApplicationLocked方法

//AMS
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {

        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }

        //因?yàn)檫M(jìn)程由AMS啟動(dòng),所以在AMS中一定會(huì)有ProcessRecord(進(jìn)程記錄)
        //如果沒有ProcessRecord,則需要?dú)⑺涝撨M(jìn)程并退出
        if (app == null) {
            ...
            return false;
        }

        // If this application record is still attached to a previous
        // process, clean it up now.
        if (app.thread != null) {
            //如果從ProcessRecord中獲取的IApplicationThread不為空,則需要處理該IApplicationThread
            //因?yàn)橛锌赡艽薖id為復(fù)用,舊應(yīng)用進(jìn)程剛釋放,內(nèi)部IApplicationThread尚未清空,
            //同時(shí)新進(jìn)程又剛好使用了此Pid
            handleAppDiedLocked(app, true, true);
        }


        //創(chuàng)建死亡代理(進(jìn)程kill后通知AMS)
        AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);

        //進(jìn)程注冊(cè)成功,移除超時(shí)通知
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        ...
        try {
            //綁定Application
            thread.bindApplication(processName, appInfo, providers,     app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());

            updateLruProcessLocked(app, false, null);
        } catch (Exception e) {
            ...
            //bindApplication失敗后,重啟進(jìn)程
            startProcessLocked(app, "bind fail", processName);
            return false;
        }

        try {
            //啟動(dòng)Activity(啟動(dòng)淘寶MainActivity)
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;//didSomething表示是否有啟動(dòng)四大組件
            }
        } catch (Exception e) {
            badApp = true;
        }

        ...
        //綁定service和Broadcast的Application


        if (badApp) {
            //如果以上組件啟動(dòng)出錯(cuò),則需要?dú)⑺肋M(jìn)程并移除記錄
            app.kill("error during init", true);
            handleAppDiedLocked(app, false, true);
            return false;
        }

        //如果以上沒有啟動(dòng)任何組件,那么didSomething為false
        if (!didSomething) {
            //調(diào)整進(jìn)程的oom_adj值, oom_adj相當(dāng)于一種優(yōu)先級(jí)
            //如果應(yīng)用進(jìn)程沒有運(yùn)行任何組件,那么當(dāng)內(nèi)存出現(xiàn)不足時(shí),該進(jìn)程是最先被系統(tǒng)“殺死”
            updateOomAdjLocked();
        }
        return true;
    }

attachApplicationLocked中有兩個(gè)比較重要的方法函數(shù):

  1. thread.bindApplication(…) : 綁定Application到ActivityThread
  2. mStackSupervisor.attachApplicationLocked(app) : 啟動(dòng)Activity(Android 7.0前為mMainStack.realStartActivityLocked()

ApplicationThread.bindApplication綁定Application到ActivityThread

在上面我們說道,ActivityThread通過ApplicationThread與AMS進(jìn)行通訊,所以上面的thread.bindApplication(...)方法,就應(yīng)該是通過ApplicationThread進(jìn)行傳達(dá)。
ActivityThread的內(nèi)部類ApplicationThread中,我們找到bindApplication方法

//ActivityThread
//內(nèi)部類ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {

    public final void bindApplication(...一大堆參數(shù)...) {
        AppBindData data = new AppBindData();
        //給data設(shè)置參數(shù)...
        ...
        sendMessage(H.BIND_APPLICATION, data);
    }
}

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    Message msg = Message.obtain();
    //給msg設(shè)置參數(shù)
    ...
    mH.sendMessage(msg);
}

發(fā)送消息是通過HHandler類來完成的。

private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        ...
        public static final int RESUME_ACTIVITY         = 107;

        public static final int DESTROY_ACTIVITY        = 109;
        public static final int BIND_APPLICATION        = 110;
        public static final int EXIT_APPLICATION        = 111;
        
        ...

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

                ... 
                //綁定application
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
            }
        }
}

可以看出,這個(gè)H類相當(dāng)于ActivityThreadApplicationThread的中介人,也就是拉皮條的。
ActivityThread通過ApplicationThread與AMS通訊。
ApplicationThread通過HActivityThread通訊,處理Activity事務(wù)。

那么既然HApplicationThread都在ActivityThread類里,為何ApplicationThread還要通過Handler來發(fā)送消息?

  • 便于集中管理,方便打印Log日志等,H就是這其中的大管家。
  • ActivityThread通過ApplicationThread和AMS進(jìn)行進(jìn)程間通信,AMS以進(jìn)程通訊的方式來完成ActivityThread的請(qǐng)求后調(diào)用ApplicationThread中的Binder方法,然后ApplicationThread會(huì)向H發(fā)送消息,H收到消息后會(huì)將ApplicationThread中的邏輯切換到ActivityThread中去執(zhí)行,即切換到主線程中去執(zhí)行,這個(gè)過程就是主線程的消息循環(huán)模型

而且有一點(diǎn)要注意的是,這個(gè)ActivityThread并不是一個(gè)線程Thread,它是final類并且無繼承或者實(shí)現(xiàn)其它類,它的作用就是在main方法內(nèi)消息循環(huán),處理主線程事務(wù)。(還需了解Looper及消息機(jī)制)

言歸正傳,上面ApplicationThreadH發(fā)送BIND_APPLICATION標(biāo)識(shí),在H中,通過handleBindApplication處理Application的綁定事務(wù)。

//ActivityThread
private void handleBindApplication(AppBindData data) {

           ...
          //根據(jù)傳遞過來的ApplicationInfo創(chuàng)建一個(gè)對(duì)應(yīng)的LoadedApk對(duì)象
          data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//獲取LoadedApk

          //禁止在主線程使用網(wǎng)絡(luò)操作
          if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
              StrictMode.enableDeathOnNetwork();
          }
    
           //7.0引入Fileprovide
          if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
              StrictMode.enableDeathOnFileUriExposure();
          }

          ...  
          //創(chuàng)建進(jìn)程對(duì)應(yīng)的Android運(yùn)行環(huán)境ContextImpl
          final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

          if ((InstrumentationInfo)ii != null) {
               ...
          } else {
               //注意Activity的所有生命周期方法都會(huì)被Instrumentation對(duì)象所監(jiān)控,
               //也就說執(zhí)行Activity的生命周期方法前后一定會(huì)調(diào)用Instrumentation對(duì)象的相關(guān)方法
               mInstrumentation = new Instrumentation();
          }

          try {
             ...
             Application app = data.info.makeApplication(data.restrictedBackupMode, null);
             mInitialApplication = app;

             //加載進(jìn)程對(duì)應(yīng)Package中攜帶的ContentProvider
             installContentProviders(app, data.providers);

             ...        
             mInstrumentation.onCreate(data.instrumentationArgs);

             try {
                  //這里會(huì)調(diào)用Application的onCreate方法
                  //故此Applcation對(duì)象的onCreate方法會(huì)比ActivityThread的main方法后調(diào)用
                  //但是會(huì)比這個(gè)應(yīng)用的所有activity先調(diào)用
                  mInstrumentation.callApplicationOnCreate(app);
              } catch (Exception e) {
                  ...
              }
            } finally {
                StrictMode.setThreadPolicy(savedPolicy);
            }
        }

如上文所述,handleBindApplication的目的是讓一個(gè)Java進(jìn)程融入到Android體系中
因此,該函數(shù)中的代碼主要進(jìn)行以下工作:

  1. 按照Android的要求,完成對(duì)進(jìn)程基本參數(shù)的設(shè)置置,包括設(shè)置進(jìn)程名、時(shí)區(qū)、資源及兼容性配置;
    同時(shí)也添加了一些限制,例如主線程不能訪問網(wǎng)絡(luò)等。
  2. 創(chuàng)建進(jìn)程對(duì)應(yīng)的ContextImpl、LoadedApk、Application等對(duì)象,同時(shí)加載Application中的ContentProvider,并初始化Application
  3. 使用Instrumentation監(jiān)控Activity的生命周期。(一個(gè)進(jìn)程對(duì)應(yīng)一個(gè)Instrumentation實(shí)例)

當(dāng)完成上述工作后,新建的進(jìn)程終于加入到了Android體系。

AMS通知淘寶綁定Application并啟動(dòng)MainActivity。

ActivityStackSupervisor.attachApplicationLocked啟動(dòng)Activity

在上述代碼AMS的attachApplicationLocked方法中,我們說道:

attachApplicationLocked中有兩個(gè)比較重要的方法函數(shù),分析到這里我們的文章也要進(jìn)入尾聲了。

  1. thread.bindApplication(…) : 綁定Application到ActivityThread
  2. mStackSupervisor.attachApplicationLocked(app) : 啟動(dòng)Activity

綁定了Application之后,我們就可以啟動(dòng)Activity(淘寶MainActivity)。

//ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    boolean didSomething = false;

    //ActivityStackSupervisor維護(hù)著終端中所有ActivityStack
    //此處通過輪詢,找出前臺(tái)棧頂端的待啟動(dòng)Activity
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = stacks.get(stackNdx);
            if (!isFocusedStack(stack)) {
                continue;
            }

            ActivityRecord hr = stack.topRunningActivityLocked();
            if (hr != null) {
                //前臺(tái)待啟動(dòng)的Activity與當(dāng)前新建的進(jìn)程一致時(shí),啟動(dòng)這個(gè)Activity
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid &&                             processName.equals(hr.processName)) {
                    try {
                        //realStartActivityLocked進(jìn)行實(shí)際的啟動(dòng)工作
                        if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (RemoteException e) {

                    }
                }
            }
        }
    }
    return didSomething;
}

大概系統(tǒng)工程師也覺得這個(gè)啟動(dòng)過程賊雞兒繞了,最終啟動(dòng)的方法命名為realStartActivityLocked,意味著告訴你,大伙兒不要搞暈了,這個(gè)就是最后啟動(dòng)Activity的方法了。realStartActivityLocked()方法通過ApplicaitonThread的scheduleLaunchActivity()調(diào)用客戶端Binder實(shí)體的方法,最后我們直搗黃龍,在ActivityStackSupervisor方法中,我們找到如下代碼

//ActivityStackSupervisor
//通過ApplicaitonThread調(diào)用客戶端Binder實(shí)體的方法。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
public final void scheduleResumeActivity(IBinder token, int processState,
boolean isForward, Bundle resumeArgs) {
    updateProcessState(processState, false);
    sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
}

看到這里想必大伙兒都明白了,AMS最后通過ApplicationThread通知ActivityThread啟動(dòng)Activity,感覺這一切的通訊都像發(fā)電報(bào)一樣,鬼斧神工出神入化,皆出架構(gòu)師之目營心匠。
那么到這里我們就能推算出接下來的老套路了
ApplicationThread—> H—> ActivityThread—> 最終啟動(dòng)Activity的方法。

ActivityThread

//ActivityThread

//內(nèi)部類ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {

    @Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, 
                IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

        updateProcessState(procState, false);

        ActivityClientRecord r = new ActivityClientRecord();
        //設(shè)置參數(shù)
        ...

        //從LAUNCH_ACTIVITY這個(gè)標(biāo)識(shí)我們就可以知道,它就是用來啟動(dòng)Activity
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
}

private class H extends Handler {
    ...
    //用Handler發(fā)送了一個(gè)Message。Handler的處理會(huì)最終調(diào)用handlerLaunchActivity方法
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                //利用ApplicationInfo等信息得到對(duì)應(yīng)的LoadedApk,保存到ActivityClientRecord
                //ActivityClientRecord包含Activity相關(guān)的信息
                r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
                ...  
            }
        }
    }
}

//ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        ...
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ...
    } 
    ...
}

handleLaunchActivity方法里有有兩個(gè)重要的函數(shù)調(diào)用:

  • performLaunchActivity : 會(huì)調(diào)用Activity的onCreate、onStart、onResotreInstanceState方法
  • handleResumeActivity : 會(huì)調(diào)用Activity的onResume方法

從上面的源碼可以看出,performLaunchActivity方法最終完成了Activity對(duì)象的創(chuàng)建和啟動(dòng)過程,并且ActivityThread通過handleResumeActivity方法來調(diào)用被啟動(dòng)Activity的onResume這一生命周期方法。

performLaunchActivity

performLaunchActivity這個(gè)方法主要完成了如下幾件事:

1、從ActivityClientRecord中獲取待啟動(dòng)的Activity的組件信息。

//ActivityThread的performLaunchActivity方法

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            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);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

2、通過Instrumentation的newActivity方法使用類加載器創(chuàng)建Activity對(duì)象。

//ActivityThread的performLaunchActivity方法

Activity activity = null;
try {
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    StrictMode.incrementExpectedActivityCount(activity.getClass());
    r.intent.setExtrasClassLoader(cl);
    r.intent.prepareToEnterProcess();
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }
} catch (Exception e) {
    ...
}

3、通過LoadedApk的makeApplication方法來創(chuàng)建Application對(duì)象。

//ActivityThread的performLaunchActivity方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//r.packageInfo為LoadedApk對(duì)象

其實(shí)在我們上面的bindApplication中,我們就有介紹到通過LoadedApk創(chuàng)建Application,并且創(chuàng)建完畢后,通過InstrumentationcallApplicationOnCreate來調(diào)用Application的onCreate方法

Application app = data.info.makeApplication(data.restrictedBackupMode, null);
...
mInstrumentation.callApplicationOnCreate(app);

所以第三步是為了判斷Application是否為空,而且我們從makeApplication方法中也能看出如果Application已經(jīng)被創(chuàng)建過了,那么就不會(huì)再重復(fù)創(chuàng)建了。

4、創(chuàng)建ContextImpl對(duì)象,并通過Activity的attach方法來完成一些重要數(shù)據(jù)的初始化。

Context appContext = createBaseContextForActivity(r, activity);//創(chuàng)建ContextImpl對(duì)象
Window window = null;

if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
    window = r.mPendingRemoveWindow;
    r.mPendingRemoveWindow = null;
    r.mPendingRemoveWindowManager = null;
}

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, window);

ContextImpl是一個(gè)很重要的數(shù)據(jù)結(jié)構(gòu),它是Context的具體實(shí)現(xiàn),Context中的大部分邏輯都是由ContextImpl來完成的。ContextImpl來完成的。ContextImpl是通過Activity的attach方法來和Activity建立關(guān)聯(lián)的,除此之外,在attach方法中Activity還會(huì)完成Window的創(chuàng)建并建立自己和Window的關(guān)聯(lián),這樣當(dāng)Window接收到外部輸入事件后就可以將事件傳遞給Activity。

5、調(diào)用Activity的onCreate方法

mInstrumentation.callActivityOnCreate(activity, r.state);

由于Activity的onCreate已經(jīng)被調(diào)用,這也意味著Activity已經(jīng)完成了整個(gè)啟動(dòng)過程。

6、調(diào)用Activity的onStart、onResotreInstanceState方法

mInstrumentation.callActivityOnCreate(activity, r.state);
...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}

對(duì)activity.performCreate(icicle);這一行代碼熟悉嗎?這一行里面就調(diào)用了傳說中的Activity的入口函數(shù)onCreate(),不信?接著往下看Activity.performCreate()

final void performCreate(Bundle icicle) {
    onCreate(icicle);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

沒騙你吧,onCreate在這里調(diào)用了吧。

參考文章

【凱子哥帶你學(xué)Framework】Activity啟動(dòng)過程全解析

Android Launcher 啟動(dòng) Activity 的工作過程

Android系統(tǒng)開篇

startActivity啟動(dòng)過程分析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,283評(píng)論 6 530
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 97,947評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,094評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,485評(píng)論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,268評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,817評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,906評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,039評(píng)論 0 285
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,551評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,502評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,662評(píng)論 1 366
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,188評(píng)論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,907評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,304評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,563評(píng)論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,255評(píng)論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,637評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容