Android-Activity 啟動流程分析一

本文基于 api 28 分析
提問:從桌面點擊圖標開始 app 干了什么铛楣?

分析前先了解以下類:

Instrumentation: 在應用代碼之前實例化棘催,每個進程都有一個Instrumentation馅笙。監(jiān)控應用與所有系統(tǒng)的交互昭躺,每個 Activity 持有它的引用缀台,ActivityThread 要創(chuàng)建或暫停 Activity 時岳掐,都是通過 Instrumentation 進行操作凭疮。

ApplicationThread: 繼承 IApplicationThread.Stub,ActivityThread 的內(nèi)部類串述,是 ActivityManagerService 向 ActivityThread 通信的橋梁执解。

ActivityThread:繼承 ClientTransactionHandler ,APP的主線程纲酗,main 函數(shù)衰腌。

ActivityRecord:每個 ActivityRecord 在 AMS 中對應一個 Activity,記錄 Acitivty 信息桶唐。(一個 Activity 對應多個 ActivityRecord,因為同一個 Activity 可以被啟動多次尤泽?此條待確定)

ActivityStarter:收集 intent、task坯约、flag 等信息莫鸭,生成 ActivityRecord。

TaskRecord:任務棧被因,先進后出,存儲 ActivityRecord梨与。一個 TaskRecord 由一個或者多個 ActivityRecord 組成堕花。

ActivityStack:管理 TaskRecord,包含了多個TaskRecord粥鞋,由 ActivityStackSupervisor 創(chuàng)建缘挽。

ActivityStackSupervisor:AMS 通過 ActivityStackSupervisor 操作 ActivityStack。

ActivityManagerService:(:IActivityManager:SystemServer) 系統(tǒng)中啟動的獨立進程,負責管理四大組件壕曼,可以利用 Binder 跟它通信苏研。

ClientLifecycleManager:調(diào)用 ClientTransaction,讓 AMS 切換到 APP 進程執(zhí)行生命周期腮郊。

Activity 啟動流程涉及到進程摹蘑、線程間通信:
1、startActivity 時所在進程伴榔。
2纹蝴、AMS 進程,通過 ApplicationThread 實現(xiàn) AMS 與 ActivityThread 的進程間通信踪少。

在 ActivityManagerService 中生成 ApplicationThread 代理
ActivityThread.attach()方法:
            //實例化 ApplicationThread塘安、ActivityManagerService 本地代理
            final IActivityManager mgr = ActivityManager.getService();
            //將 ApplicationThread 綁定在 ActivityManagerService(通過 ProcessRecord) 中
            mgr.attachApplication(mAppThread, startSeq);
            mgr.attachApplicationLocked(thread)
            new ProcessRecord().makeActive(thread) 將 applicationThread 綁定在 ProcessRecord 中
            activityManagerServiec attach applicationThread

3、目標 Activity 進程援奢,ActivityThread 中 Handler 線程間通信兼犯。

startActivity.png

圖片來源:基于Android-28 的源碼 Activity 啟動流程分析

第一階段:startActivity

1.1 第一種啟動方式,桌面圖標啟動 startActivity集漾,實現(xiàn)類是 ContextImpl切黔。

class ContextImpl extends Context {
    public void startActivity(Intent intent) {
        ...
        startActivity(intent, null);
    }

    @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        ...
        //mMainThread 是 ActivityThread。mMainThread.getApplicationThread() 是獲取 ActivityThread 的內(nèi)部類ApplicationThread,它是一個 IBinder具篇,主要用于 ActivityThread 與 AMS 的通信纬霞。
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
}

1.2 第二種啟動方式,應用內(nèi)打開 activity驱显,實現(xiàn)類 Activity.

public class Activity extends ContextThemeWrapper{
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
             ...
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
             ...
}

由此可見 ContextImpl 與 Activity 最終都是通過 Instrumentation 的 execStartActivity() 啟動 Activity诗芜。

public class Instrumentation {
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        ...
    }
}

public class ActivityManager {
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
}

ActivityManager.getService() 獲取得到的是 IActivityManager 的接口伏恐,是 ActivityManagerService(AMS) 遠程代理類翠桦。AMS 運行在另外一個進程销凑,繼承了 IBinder斗幼,是 binder 通信的 Server 端孟岛。通過 IActivityManager 就可以跟 AMS 實現(xiàn) Binder 通信督勺。

第二階段:AMS 進程
public class ActivityManagerService extends IActivityManager.Stub {
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        //mActivityStartController.obtainStarter 獲取到 ActivityStarter
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }
}

ActivityStarter 收集 intent次询、選擇啟動的 task屯吊、flag 等信息盒卸,復用Activity等邏輯蔽介,生成 ActivityRecord虹蓄。

class ActivityStarter {
    int execute() {
        ...
        startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup);
            }
    }

    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
        ...
        //構(gòu)造當前的 Actiivty 的 ActivityRecord
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        ...
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);
    }

    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
            ...
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        ...
        return result;
    }

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
          ...
          //mSupervisor 是 ActivityStackSupervisor
          mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
          ...
    }
}

ActivityStarter 構(gòu)造了ActivityRecord,選擇ActivityStack等等律胀。
startActivityUnchecked 做了決定任務棧累铅,根據(jù)啟動模式娃兽,是否調(diào)用deliverNewIntent投储,復用Activity 等動作阔馋。

public class ActivityStackSupervisor extends ConfigurationContainer {
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
            ...
            //targetStack 是 ActivityStack
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            ...
    }
}
class ActivityStack<T extends StackWindowController> extends ConfigurationContainer {
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            ...//1
            result = resumeTopActivityInnerLocked(prev, options);
            ...
    }

    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        ...//2
        if (mResumedActivity != null) {
            //構(gòu)造 PauseActivityItem 執(zhí)行 pause 方法勋眯,暫停當前的 Activity
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        if (pausing && !resumeWhilePausing) {
            ...
            return true;
        }
        ...
        if (next.app != null && next.app.thread != null) {
                        ...
                        //如果 Activity 已存在客蹋,執(zhí)行 resume
                        mStackSupervisor.scheduleResumeTopActivities();
        } else {
            ...//3
            //創(chuàng)建進程讶坯,冷啟動并創(chuàng)建 Activity∈欤或者已啟動 App娩井,重新啟動 Activity
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
}

resumeTopActivityInnerLocked() 主要負責暫停當前 Activity 和啟動新的 Activity撞牢。

先來看 startPausingLocked 暫停 Activity 方法叔营,再看 startSpecificActivityLocked 啟動 Activity 方法


    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {
                ...
                //mService.getLifecycleManager() 是獲取到 ClientLifecycleManager绒尊, 這個類負責執(zhí)行 ActivityLifecycleItem婴谱,就是生命周期的任務谭羔,如 PauseActivityItem 瘟裸、ResumeActivtyItem
                mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                        PauseActivityItem.obtain(prev.finishing, userLeaving,
                                prev.configChangeFlags, pauseImmediately));
        }
    }

public class ActivityStackSupervisor extends ConfigurationContainer  {
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
         ...
        //如果 app 進程存在
        if (app != null && app.thread != null) {
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            }
        //如果 app 進程不存在
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);                ...
    }

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
                ...
                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                        r.appToken);
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                        profilerInfo));

                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {//andResume 為 true
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                //lifecycleItem 是 ResumeActivtyItem
                clientTransaction.setLifecycleStateRequest(lifecycleItem);
                //mService.getLifecycleManager() ClientLifecycleManager
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                ...
    }

}

這里分兩種情況兼搏,一是 app 進程存在執(zhí)行 realeStartActivityLocked() 佛呻,另一個是 app 進程不存在吓著,執(zhí)行 AMS 的 startProcessLocked() ,Zygote 進程 fork 子進程泛范,啟動進程執(zhí)行 ActivityThread 的 main 方法紊撕。

class ClientLifecycleManager {
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        //執(zhí)行 ClientTransaction 的 schedule() 方法
        transaction.schedule();
        ...
    }
}
public class ClientTransaction {
    public void schedule() throws RemoteException {
        //mClient  為 IApplicationThread对扶,實際是 ActivityThread 中的 ApplicationThread
        mClient.scheduleTransaction(this);
    }
}

ClientTransaction 中包裝了 ActivityLifecycleItem浪南,就是生命周期的任務络凿,如 PauseActivityItem 絮记、ResumeActivtyItem怨愤。

IApplicationThread 是 ActivityThread 內(nèi)部類 ApplicationThread撰洗,是 Binder 對象腐芍,IApplicationThread 是它遠程接口猪勇。
當執(zhí)行 ApplicationThread. scheduleTransaction() 會從 AMS 進程回到目標 Activity 進程泣刹。

接下來看 ApplicationThread

目標 Activity 進程,ActivityThread 中 Handler 線程間通信貌笨。
public final class ActivityThread extends ClientTransactionHandler {
    private class ApplicationThread extends IApplicationThread.Stub {
        //ApplicationThread 是 Binder 對象锥惋,IApplicationThread 是它遠程接口。
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            //1
            ActivityThread.this.scheduleTransaction(transaction);
        }
    }

    //ActivityThread 繼承自 ClientTransactionHandler遭商,scheduleTransaction 是 ClientTransactionHandler 中方法
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        //2 發(fā)送消息 EXECUTE_TRANSACTION 
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        ...
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        //3劫流,mH 是 Handler,將異步 msg 發(fā)送給 Handler 同步處理
        mH.sendMessage(msg);
    }

    class H extends Handler {
                ...
                //回到主線程可很,處理 EXECUTE_TRANSACTION 消息
                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    //4我抠、mTransactionExecutor 是 TransactionExecutor
                    mTransactionExecutor.execute(transaction);
                    break;
            }
        }
    }
}
public class TransactionExecutor {
    public void execute(ClientTransaction transaction) {
        ...
        //5菜拓、
        executeCallbacks(transaction);
        //6尘惧、
        executeLifecycleState(transaction);
    }

    @VisibleForTesting
    public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
        ...
        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
            ...
            //5.1  
            if (closestPreExecutionState != UNDEFINED) {
                //預初始化狀態(tài) ON_CREATE/ON_START 等 
                cycleToPath(r, closestPreExecutionState);
            }
            //5.2 item 為 PauseActivityItem/ResumeActivityItem 等 ClientTransactionItem 類
            item.execute(mTransactionHandler, token, mPendingActions);
            //5.3
            item.postExecute(mTransactionHandler, token, mPendingActions);
        }
    }

    private void cycleToPath(ActivityClientRecord r, int finish,
            boolean excludeLastState) {
        ...
        performLifecycleSequence(r, path);
    }

    /** mTransactionHandler 是 ActivityThread喷橙,最終調(diào)用 ActivityThread 方法 */
    private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            log("Transitioning to state: " + state);
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                            r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                    break;
                case ON_PAUSE:
                    mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                            false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                            "LIFECYCLER_PAUSE_ACTIVITY");
                    break;
                case ON_STOP:
                    mTransactionHandler.handleStopActivity(r.token, false /* show */,
                            0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
                            "LIFECYCLER_STOP_ACTIVITY");
                    break;
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                            0 /* configChanges */, false /* getNonConfigInstance */,
                            "performLifecycleSequence. cycling to:" + path.get(size - 1));
                    break;
                case ON_RESTART:
                    mTransactionHandler.performRestartActivity(r.token, false /* start */);
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
            }
        }
    }

}

至此贰逾,這一段講了 ActivityLifecycleItem 通過 ClientLifecycleManager 走到 ActivityThread疙剑,并切換到主線程執(zhí)行 execute()

參考:
基于Android-28 的源碼 Activity 啟動流程分析
ActivityRecord言缤、TaskRecord管挟、ActivityStack以及Activity啟動模式詳解
Activity生命周期回調(diào)是如何被回調(diào)的?
ActivityRecord僻孝、TaskRecord、ActivityStack以及Activity啟動模式詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末您单,一起剝皮案震驚了整個濱河市荞雏,隨后出現(xiàn)的幾起案子凤优,更是在濱河造成了極大的恐慌别洪,老刑警劉巖挖垛,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痢毒,死亡現(xiàn)場離奇詭異哪替,居然都是意外死亡躺彬,警方通過查閱死者的電腦和手機爱沟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來身冀,“玉大人搂根,你說我怎么就攤上這事铃辖〗空叮” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵五督,是天一觀的道長充包。 經(jīng)常有香客問我基矮,道長,這世上最難降的妖魔是什么家浇? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任点额,我火速辦了婚禮莺琳,結(jié)果婚禮上惭等,老公的妹妹穿的比我還像新娘辞做。我一直安慰自己,他們只是感情好焙蹭,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布孔厉。 她就那樣靜靜地躺著撰豺,像睡著了一般污桦。 火紅的嫁衣襯著肌膚如雪凡橱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天顾稀,我揣著相機與錄音静秆,去河邊找鬼抚笔。 笑死侨拦,一個胖子當著我的面吹牛狱从,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鸽疾,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼递沪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起款慨,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎附帽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體整胃,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡屁使,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年蔽午,在試婚紗的時候發(fā)現(xiàn)自己被綠了共郭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祠丝。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖除嘹,靈堂內(nèi)的尸體忽然破棺而出写半,到底是詐尸還是另有隱情,我是刑警寧澤尉咕,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布叠蝇,位于F島的核電站,受9級特大地震影響年缎,放射性物質(zhì)發(fā)生泄漏悔捶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一单芜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦绢淀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至数初,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背眼俊。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工澎灸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人糜颠。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓饭聚,卻偏偏與公主長得像箕速,于是被迫代替她去往敵國和親兴垦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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