Activity啟動(dòng)流程

Activity啟動(dòng)流程


一、執(zhí)行startActivity

  • Activity.startActivity(Intent intent, @Nullable Bundle options)

    @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);
        }
    }
    
  • Activity.startActivityForResult ------requestCode == -1

    mInstrumentation.execStartActivity(
        this, mMainThread.getApplicationThread(), mToken, this,
        intent, requestCode, options);
    

    “Instrumentation是啟動(dòng)Activity的操作類”指蚁,每一個(gè)應(yīng)用程序只有一個(gè)Instrumentation對(duì)象,每個(gè)Activity持有一個(gè)該對(duì)象的引用哎壳。包括了調(diào)用Activity的各生命周期方法的callActivityxxx()。

  • Instrumentation.execStartActivty

    int result = ActivityManagerNative.getDefault()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
    

    getDefault()返回的是:

    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    
        private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            protected IActivityManager create() {
                IBinder b = ServiceManager.getService("activity");
                if (false) {
                    Log.v("ActivityManager", "default service binder = " + b);
                }
                IActivityManager am = asInterface(b);
                if (false) {
                    Log.v("ActivityManager", "default service = " + am);
                }
                return am;
            }
        };
    
    asInterface{
      ....
      return new ActivityManagerProxy(obj);
    }
    

    ActivityManagerNative extends Binder

    接口的實(shí)現(xiàn)關(guān)系:

    ? IInterface->IActivityManager–> ActivityManagerNative/ActivityManagerProxy

    ? ActivityManagerNative作為AMS的客戶端通過(guò)ActivityManagerProxy向AMS發(fā)送啟動(dòng)請(qǐng)求。

    ActivityManagerService extends ActivityManagerNative
    
  • ActivityManagerProxy.startActivity()

    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;
        }
    

    通過(guò)binder向AMS傳輸數(shù)據(jù),AMS調(diào)用startActivity()方法


通過(guò)Binder向AMS發(fā)送啟動(dòng)Activity請(qǐng)求

二、ActivityManagerService接收啟動(dòng)Activity的請(qǐng)求烦租,并控制前臺(tái)Activity調(diào)用onPause

在AMSstartActivity()方法內(nèi)部,繼續(xù)調(diào)用startActivityAsUser()方法:

  • ActivityManagerService.startActivity()
@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());
}
  • ActvityiManagerService.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 bOptions, int userId) {
        ....
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null);
    }
    

    該方法返回時(shí)除盏,調(diào)用了ActivityStarter.startActivityMayWait()方法叉橱。

    • ActivityStarter是一個(gè)專門負(fù)責(zé)Activity啟動(dòng)的控制類,通過(guò)intent和flag決定如何啟動(dòng)一個(gè)Activity者蠕,并關(guān)聯(lián)到Task和Stack窃祝。

    ActivityStarter.startActivityMayWait()方法中,返回值如下:

  • ActivityStarter.startActivityMayWait()

    int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor,
            resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, outRecord, container,
            inTask);
    .....
    return res;
    

    我們可以看到此處調(diào)用了ActivityStarter.startActivityLocked()方法踱侣,該方法關(guān)鍵部分如下:

  • ActivityStarter.startActivityLocked()

    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                    callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                    container, inTask);
    
    ····
    return mLastStartActivityResult;
    

    調(diào)用的startActivity()方法:

    ····
    try {
                mService.mWindowManager.deferSurfaceLayout();
                result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, outActivity);
            }
    ····
    return result;;
    

    這里又調(diào)用了另一個(gè)方法ActivityStarter.startActivityUnchecked()粪小,在該方法中進(jìn)行了大量邏輯操作,這里挑出部分:

  • ActivityStarter.startActivityUnchecked()

    ····
    final ActivityStack topStack = mSupervisor.mFocusedStack;
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
    ····
    

    關(guān)于ActivityStackSupervisor抡句,它用來(lái)保存Activity的棧信息

    • ActivityStackSupervisor
        /** The stack containing the launcher app. Assumed to always be attached to
         * Display.DEFAULT_DISPLAY. */
        ActivityStack mHomeStack;
    
        /** The stack currently receiving input or launching the next activity. */
        ActivityStack mFocusedStack;
    
        /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
         * been resumed. If stacks are changing position this will hold the old stack until the new
         * stack becomes resumed after which it will be set to mFocusedStack. */
        private ActivityStack mLastFocusedStack;
    

    mHomeStack : 只保存了 Launcher 的 Task;

    mLastFocusedStack: 當(dāng)該值等于mFocusedStack探膊,代表當(dāng)前棧頂?shù)腁ctivity完成resume;
    ? 當(dāng)該值等于上一個(gè)舊棧時(shí)待榔,代表activity正在切換逞壁;

mIntent.setFlags(mLaunchFlags);//設(shè)置啟動(dòng)flag
mReusedActivity = getReusableIntentActivity();//決定是否將新的Activity插入到現(xiàn)有的task
····
final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
        if (dontStart) {
            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
            // For paranoia, make sure we have correctly resumed the top activity.
            topStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
          ·····
            return START_DELIVERED_TO_TOP;
        }
·····
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);//啟動(dòng)Activity、是否開啟新task···
····
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);//更新last used stack ID
····
  • ActivityStack.startActivityLocked()

    ····
    TaskRecord rTask = r.task;
    final int taskId = rTask.taskId;
    // mLaunchTaskBehind tasks get placed at the back of the task stack.
    if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
        // Last activity in task had been removed or ActivityManagerService is reusing task.
        // Insert or replace.
        // Might not even be in.
        insertTaskAtTop(rTask, r);
        mWindowManager.moveTaskToTop(taskId);
    }
    TaskRecord task = null;
    if (!newTask) {//如果不是在新的Task中啟動(dòng)锐锣,就找出要運(yùn)行在TaskRecord的對(duì)象
        // If starting in an existing task, find where that is...
        boolean startIt = true;
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            task = mTaskHistory.get(taskNdx);
            if (task.getTopActivity() == null) {
                // All activities in task are finishing.
                continue;
            }
            if (task == r.task) {
                // Here it is!  Now, if this is not yet visible to the
                // user, then just add it without starting; it will
                // get started when the user navigates back to it.
                if (!startIt) {
                    if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
                            + task, new RuntimeException("here").fillInStackTrace());
                    task.addActivityToTop(r);
                    r.putInHistory();
                    addConfigOverride(r, task);
                    if (VALIDATE_TOKENS) {
                        validateAppTokensLocked();
                    }
                    ActivityOptions.abort(options);
                    return;
                }
                break;
            } else if (task.numFullscreen > 0) {
                startIt = false;
            }
        }
    }
    
    // Place a new activity at top of stack, so it is next to interact
    // with the user.
    
    // If we are not placing the new activity frontmost, we do not want
    // to deliver the onUserLeaving callback to the actual frontmost
    // activity
    ······
    
  • ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        }
        return false;
    }
    
  • ActivityStack.resumeTopActivityUncheckedLocked()

    ····
    result = resumeTopActivityInnerLocked(prev, options);
    ····
    return result;
    

    這里主要調(diào)用了mSupervisor.resumeFocusedStackTopActivityLocked()方法腌闯,該方法繼續(xù)調(diào)用targetStack.resumeTopActivityUncheckedLocked(target, targetOptions),在

    resumeTopActivityUncheckedLocked方法中刺下,繼續(xù)調(diào)用resumeTopActivityInnerLocked(prev, options)并返回绑嘹。resumeTopActivityInnerLocked方法關(guān)鍵邏輯如下:

  • ActivityStack.resumeTopActivityInnerLocked()

    ····
     /**
       * Current activity that is resumed, or null if there is none.
       */
      ActivityRecord mResumedActivity = null;
    ····
    //找出還沒(méi)結(jié)束的首個(gè)ActivityRecord
    ActivityRecord next = topRunningActivityLocked(null);
    ····
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next,             dontWaitForPause);  
    ····
    //啟動(dòng)前需要暫停前一個(gè)Activity
    if (mResumedActivity != null) {  
      if (DEBUG_STATES) Slog.d(TAG_STATES,
              "resumeTopActivityLocked: Pausing " + mResumedActivity);
      pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
    }
    

此時(shí),開始進(jìn)入pause階段橘茉,調(diào)用ActivityStack.startPausingLocked()方法芯丧,這里截取主要部分:

  • ActivityStack.startPausingLocked()

    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming, boolean dontWait) {
       if (mPausingActivity != null) {
           completePauseLocked(false);
       }
       
      .....
      ActivityRecord prev = mResumedActivity;
      ·····
       
       if (prev.app != null && prev.app.thread != null) 
         try {
               mService.updateUsageStats(prev, false);
               prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                       userLeaving, prev.configChangeFlags, dontWait);
           } catch (Exception e) {
               mPausingActivity = null;
               mLastPausedActivity = null;
               mLastNoHistoryActivity = null;
           }
       } else {
           mPausingActivity = null;
           mLastPausedActivity = null;
           mLastNoHistoryActivity = null;
       }
       
     .....  
    }
    

    這里映跟,prev.app為記錄啟動(dòng)Lancher進(jìn)程的ProcessRecord,prev.app.thread為L(zhǎng)ancher進(jìn)程的遠(yuǎn)程調(diào)用接口IApplicationThead莹弊,調(diào)用prev.app.thread.schedulePauseActivity蟋恬,在Lancher進(jìn)程中消息傳

    遞翁潘,調(diào)用ActivityThread.handlePauseActivity(),最終調(diào)用ActivityThread.performPauseActivity()暫停指定Activity歼争。

    ActivityThread.schedulePauseActivity()中發(fā)送了一個(gè)Message拜马,方法如下:

  • ActivityThread.schedulePauseActivity()

public final void schedulePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport) {
    int seq = getLifecycleSeq();
    if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
            + " operation received seq: " + seq);
    sendMessage(
            finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
            token,
            (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
            configChanges,
            seq);
}

在handleMessage的PAUSE_ACTIVITY/PAUSE_ACTIVITY_FINISHING case中均調(diào)用了handlePauseActivity方法:

private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
        if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
        if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
            return;
        }
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // Tell the activity manager we have paused.
            if (!dontReport) { //利用ActivityManagerNative通知ActivityThread已經(jīng)完成pause
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

該方法內(nèi)渗勘,調(diào)用了performPauseActivityIfNeeded()方法,在該方法中主要執(zhí)行的是performPauseActivityIfNeeded()方法完成pause俩莽,這里我們看一下performPauseActivityIfNeeded方法的具體實(shí)現(xiàn):

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
    if (r.paused) {
        // You are already paused silly...
        return;
    }

    try {
        r.activity.mCalled = false;
        mInstrumentation.callActivityOnPause(r.activity);
        EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
                r.activity.getComponentName().getClassName(), reason);
        if (!r.activity.mCalled) {
            throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                    + " did not call through to super.onPause()");
        }
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        if (!mInstrumentation.onException(r.activity, e)) {
            throw new RuntimeException("Unable to pause activity "
                    + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
        }
    }
    r.paused = true;
}

該方法中旺坠,主要調(diào)用了mInstrumentation.callActivityOnPause(r.activity) 來(lái)執(zhí)行目標(biāo)Activity的onPause方法。前面已經(jīng)說(shuō)過(guò)扮超,“Instrumentation是啟動(dòng)Activity的操作類”取刃,它的callActivityOnPause()如下,Activity.performPause()方法中我們可以看到的確調(diào)用了onPause()方法出刷。

/**
 * Perform calling of an activity's {@link Activity#onPause} method.  The
 * default implementation simply calls through to that method.
 * 
 * @param activity The activity being paused.
 */
public void callActivityOnPause(Activity activity) {
    activity.performPause();
}
final void performPause() {
    mDoReportFullyDrawn = false;
    mFragments.dispatchPause();
    mCalled = false;
    onPause();
    mResumed = false;
    if (!mCalled && getApplicationInfo().targetSdkVersion
            >= android.os.Build.VERSION_CODES.GINGERBREAD) {
        throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onPause()");
    }
    mResumed = false;
}

以上完成了執(zhí)行onPause的過(guò)程璧疗,然后在handlePauseActivity()方法中,繼續(xù)調(diào)用ActivityManagerNative.getDefault().activityPaused()方法馁龟,向AMS通知onPause過(guò)程已完成崩侠。

ActivityThread中schedulePauseActivity()發(fā)送Message后,處理消息邏輯整理如下:

handlePauseActivity-performPauseActivity-performPauseActivityIfNeeded  //具體執(zhí)行目標(biāo)             |                                                             Activity的onpause方法
ActivityManagerNative
        |
        |—>ActivityMangerProxy—>activityPaused    //ActivityMangerProxy通知ActivityThread
                                    |
                                    |—>AMS

ActivityManagerProxy.activityPaused()

public void activityPaused(IBinder token) throws RemoteException
{
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(token);
    mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
    reply.readException();
    data.recycle();
    reply.recycle();
}

ActivityManagerService接收到應(yīng)用進(jìn)程創(chuàng)建Activity的請(qǐng)求之后會(huì)執(zhí)行初始化操作坷檩,解析啟動(dòng)模式啦膜,處理信息等一系列操作。ActivityManagerService保存完請(qǐng)求信息之后會(huì)將當(dāng)前系統(tǒng)棧頂?shù)腁ctivity執(zhí)行onPause操作淌喻。

AMS.activityPaused

@Override
public final void activityPaused(IBinder token) {
    final long origId = Binder.clearCallingIdentity();
    synchronized(this) {
        ActivityStack stack = ActivityRecord.getStackLocked(token);//獲取的當(dāng)前Activity的task的所在棧
        if (stack != null) {
            stack.activityPausedLocked(token, false);
        }
    }
    Binder.restoreCallingIdentity(origId);
}

ActivityStack.activityPausedLocked

if (mPausingActivity == r) {
    if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
            + (timeout ? " (due to timeout)" : " (pause complete)"));
    completePauseLocked(true, null);
    return;
}
  • Question:

3.任務(wù)棧由誰(shuí)管理僧家,存放在什么地方?

4.啟動(dòng)一個(gè)activity都是在主線程中執(zhí)行的嗎裸删?

5.AMS什么時(shí)候介入工作的八拱?

6.Binder客戶端是怎么和服務(wù)端通信的?

7.asinterface含義是什么涯塔?

8.整個(gè)過(guò)程由哪些成員協(xié)助完成肌稻?

9.他們都起到什么作用?

10.如何圖解全過(guò)程匕荸?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末爹谭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子榛搔,更是在濱河造成了極大的恐慌诺凡,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件践惑,死亡現(xiàn)場(chǎng)離奇詭異腹泌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)尔觉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門凉袱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事专甩≈油遥” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵涤躲,是天一觀的道長(zhǎng)棺耍。 經(jīng)常有香客問(wèn)我,道長(zhǎng)篓叶,這世上最難降的妖魔是什么烈掠? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮缸托,結(jié)果婚禮上左敌,老公的妹妹穿的比我還像新娘。我一直安慰自己俐镐,他們只是感情好矫限,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著佩抹,像睡著了一般叼风。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棍苹,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天无宿,我揣著相機(jī)與錄音,去河邊找鬼枢里。 笑死孽鸡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的栏豺。 我是一名探鬼主播彬碱,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奥洼!你這毒婦竟也來(lái)了巷疼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤灵奖,失蹤者是張志新(化名)和其女友劉穎嚼沿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桑寨,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伏尼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尉尾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡燥透,死狀恐怖沙咏,靈堂內(nèi)的尸體忽然破棺而出辨图,到底是詐尸還是另有隱情,我是刑警寧澤肢藐,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布故河,位于F島的核電站,受9級(jí)特大地震影響吆豹,放射性物質(zhì)發(fā)生泄漏鱼的。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一痘煤、第九天 我趴在偏房一處隱蔽的房頂上張望凑阶。 院中可真熱鬧,春花似錦衷快、人聲如沸宙橱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)师郑。三九已至,卻和暖如春调窍,著一層夾襖步出監(jiān)牢的瞬間宝冕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工邓萨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留地梨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓先誉,卻偏偏與公主長(zhǎng)得像湿刽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子褐耳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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