View的加載過(guò)程

一直對(duì)setContentView這行代碼有些疑惑,為什么調(diào)用這行代碼就可以把xml文件加載到activity中去苇倡,網(wǎng)上有很多的講解捌蚊,但是我感覺(jué)看別人的總歸印象不是很深刻,理解的不到位园担,所以決定自己看一下源碼到底是怎么回事届谈。

觀看的源碼選用的android—27,版本不同弯汰,相關(guān)源碼也會(huì)不同

現(xiàn)在創(chuàng)建activity并不是直接繼承自activity艰山,而是他的子類(lèi)AppCompatActivity,在這里做了使用代理模式做了許多兼容咏闪,和一些新的特性曙搬,我們先不去討論,畢竟再怎么拓展鸽嫂,根還是activity纵装,先看activity類(lèi)中的setContentView

/**
     * Set the activity content from a layout resource.  The resource will be
     * inflated, adding all top-level views to the activity.
     *
     * @param layoutResID Resource ID to be inflated.
     *
     * @see #setContentView(android.view.View)
     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
     */
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

通過(guò)注釋這個(gè)方法的作用是,把資源文件中的xml文件加載activity的頂級(jí)view中去据某。
然后調(diào)用了getWindow();我們看看這個(gè)方法做了什么事情橡娄。

/**
     * Retrieve the current {@link android.view.Window} for the activity.
     * This can be used to directly access parts of the Window API that
     * are not available through Activity/Screen.
     *
     * @return Window The current window, or null if the activity is not
     *         visual.
     */
    public Window getWindow() {
        return mWindow;
    }


/**
 * Abstract base class for a top-level window look and behavior policy.  An
 * instance of this class should be used as the top-level view added to the
 * window manager. It provides standard UI policies such as a background, title
 * area, default key processing, etc.
 *
 * <p>The only existing implementation of this abstract class is
 * android.view.PhoneWindow, which you should instantiate when needing a
 * Window.
 */
public abstract class Window {

這一段的注釋的意思是

用于頂級(jí)窗口外觀和行為策略的抽象基類(lèi)。這個(gè)類(lèi)的實(shí)例應(yīng)該被作為頂層視圖添加到窗口管理器癣籽。它提供了標(biāo)準(zhǔn)的UI策略挽唉,例如背景扳还、標(biāo)題 區(qū)域、默認(rèn)密鑰處理等橱夭。他只有一個(gè)實(shí)現(xiàn)類(lèi):android.view.PhoneWindow氨距。

既然window只有一個(gè)實(shí)現(xiàn)類(lèi),那么setContentView實(shí)際上調(diào)用的是phoneWindow的方法

    @Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

首先是為mContentParent進(jìn)行初始化設(shè)置棘劣,接下來(lái)判斷是否有過(guò)場(chǎng)動(dòng)畫(huà)俏让,
因?yàn)椴还苡羞€是沒(méi)有都會(huì)調(diào)用inflate這個(gè)方法,如果有的話茬暇,會(huì)最終在Scene.enter這個(gè)方法中找到

 /**
     * Enters this scene, which entails changing all values that
     * are specified by this scene. These may be values associated
     * with a layout view group or layout resource file which will
     * now be added to the scene root, or it may be values changed by
     * an {@link #setEnterAction(Runnable)} enter action}, or a
     * combination of the these. No transition will be run when the
     * scene is entered. To get transition behavior in scene changes,
     * use one of the methods in {@link TransitionManager} instead.
     */
    public void enter() {

        // Apply layout change, if any
        if (mLayoutId > 0 || mLayout != null) {
            // empty out parent container before adding to it
            getSceneRoot().removeAllViews();

            if (mLayoutId > 0) {
                LayoutInflater.from(mContext).inflate(mLayoutId, mSceneRoot);
            } else {
                mSceneRoot.addView(mLayout);
            }
        }

        // Notify next scene that it is entering. Subclasses may override to configure scene.
        if (mEnterAction != null) {
            mEnterAction.run();
        }

        setCurrentScene(mSceneRoot, this);
    }

inflate這個(gè)方法會(huì)把xml加載到mContentParent中去首昔,怎么加載的不是本篇的重點(diǎn),重點(diǎn)是mContentParent是什么

 // This is the view in which the window contents are placed. It is either
    // mDecor itself, or a child of mDecor where the contents go.
    ViewGroup mContentParent;

在這我們知道這是一個(gè)放置Window內(nèi)容的View糙俗。它不是mDecor勒奇。它是mDecor的子View。
那它是在哪初始化的呢巧骚,回過(guò)頭來(lái)看這個(gè)installDecor()方法

 private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

        ///...  省略若干代碼
        }
    }

大篇幅的寫(xiě)mDecor赊颠,我們來(lái)看看是什么東東

 // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;

這是window的頂級(jí)view,包含window的裝飾劈彪,具體點(diǎn)進(jìn)去看看
發(fā)現(xiàn)是一個(gè)frameLayout竣蹦,再看看是如何創(chuàng)建出來(lái)的

protected DecorView generateDecor(int featureId) {
        // System process doesn't have application context and in that case we need to directly use
        // the context we have. Otherwise we want the application context, so we don't cling to the
        // activity.
        Context context;
        if (mUseDecorContext) {
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) {
                context = getContext();
            } else {
                context = new DecorContext(applicationContext, getContext().getResources());
                if (mTheme != -1) {
                    context.setTheme(mTheme);
                }
            }
        } else {
            context = getContext();
        }
        return new DecorView(context, featureId, this, getAttributes());
    }

總結(jié)一下PhoneWindow和decorView的關(guān)系痘括,
頂級(jí)窗口的屬性會(huì)在頂級(jí)view中體現(xiàn)出來(lái),因?yàn)閯?chuàng)建decorview的時(shí)候會(huì)將window傳入進(jìn)去纲菌,根據(jù)window的一些屬性初始化decorview的屬性疮绷,所以window的一些裝飾會(huì)體現(xiàn)在decorview上

分析過(guò)了decorview的初始化,接下來(lái)分析下mContentParent的初始化

protected ViewGroup generateLayout(DecorView decor) {
        // Apply data from current theme.

        TypedArray a = getWindowStyle();
}
/**
     * Return the {@link android.R.styleable#Window} attributes from this
     * window's theme.
     */
    public final TypedArray getWindowStyle() {
        synchronized (this) {
            if (mWindowStyle == null) {
                mWindowStyle = mContext.obtainStyledAttributes(
                        com.android.internal.R.styleable.Window);
            }
            return mWindowStyle;
        }
    }

可以看到第一件事去獲取window所在的主題下的屬性灶芝,屬性用來(lái)給變量賦值

mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
        int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
                & (~getForcedWindowFlags());
        if (mIsFloating) {
            setLayout(WRAP_CONTENT, WRAP_CONTENT);
            setFlags(0, flagsToUpdate);
        } else {
            setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
        }

        if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
            requestFeature(FEATURE_NO_TITLE);
        } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
            // Don't allow an action bar if there is no title.
            requestFeature(FEATURE_ACTION_BAR);
        }

        if (a.getBoolean(R.styleable.Window_windowActionBarOverlay, false)) {
            requestFeature(FEATURE_ACTION_BAR_OVERLAY);
        }

        if (a.getBoolean(R.styleable.Window_windowActionModeOverlay, false)) {
            requestFeature(FEATURE_ACTION_MODE_OVERLAY);
        }

        if (a.getBoolean(R.styleable.Window_windowSwipeToDismiss, false)) {
            requestFeature(FEATURE_SWIPE_TO_DISMISS);
        }

        if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {
            setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
        }

        if (a.getBoolean(R.styleable.Window_windowTranslucentStatus,
                false)) {
            setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS
                    & (~getForcedWindowFlags()));
        }

        if (a.getBoolean(R.styleable.Window_windowTranslucentNavigation,
                false)) {
            setFlags(FLAG_TRANSLUCENT_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION
                    & (~getForcedWindowFlags()));
        }

        if (a.getBoolean(R.styleable.Window_windowOverscan, false)) {
            setFlags(FLAG_LAYOUT_IN_OVERSCAN, FLAG_LAYOUT_IN_OVERSCAN&(~getForcedWindowFlags()));
        }

        if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
            setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));
        }

        if (a.getBoolean(R.styleable.Window_windowEnableSplitTouch,
                getContext().getApplicationInfo().targetSdkVersion
                        >= android.os.Build.VERSION_CODES.HONEYCOMB)) {
            setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));
        }

        a.getValue(R.styleable.Window_windowMinWidthMajor, mMinWidthMajor);
        a.getValue(R.styleable.Window_windowMinWidthMinor, mMinWidthMinor);
        if (DEBUG) Log.d(TAG, "Min width minor: " + mMinWidthMinor.coerceToString()
                + ", major: " + mMinWidthMajor.coerceToString());
        if (a.hasValue(R.styleable.Window_windowFixedWidthMajor)) {
            if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();
            a.getValue(R.styleable.Window_windowFixedWidthMajor,
                    mFixedWidthMajor);
        }
        if (a.hasValue(R.styleable.Window_windowFixedWidthMinor)) {
            if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();
            a.getValue(R.styleable.Window_windowFixedWidthMinor,
                    mFixedWidthMinor);
        }
        if (a.hasValue(R.styleable.Window_windowFixedHeightMajor)) {
            if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();
            a.getValue(R.styleable.Window_windowFixedHeightMajor,
                    mFixedHeightMajor);
        }
        if (a.hasValue(R.styleable.Window_windowFixedHeightMinor)) {
            if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();
            a.getValue(R.styleable.Window_windowFixedHeightMinor,
                    mFixedHeightMinor);
        }
        if (a.getBoolean(R.styleable.Window_windowContentTransitions, false)) {
            requestFeature(FEATURE_CONTENT_TRANSITIONS);
        }
        if (a.getBoolean(R.styleable.Window_windowActivityTransitions, false)) {
            requestFeature(FEATURE_ACTIVITY_TRANSITIONS);
        }

接下來(lái)根據(jù)獲取到的屬性夜涕,進(jìn)行判斷,這里有很多我們熟悉的属愤,是否懸浮的女器,是否有標(biāo)題,是否全屏住诸,是否透明等驾胆,并賦值給phoneWindow的成員變量

int layoutResource;
        int features = getLocalFeatures();
        // System.out.println("Features: 0x" + Integer.toHexString(features));
        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
            layoutResource = R.layout.screen_swipe_dismiss;
            setCloseOnSwipeEnabled(true);
        } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
            if (mIsFloating) {
                TypedValue res = new TypedValue();
                getContext().getTheme().resolveAttribute(
                        R.attr.dialogTitleIconsDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else {
                layoutResource = R.layout.screen_title_icons;
            }
            // XXX Remove this once action bar supports these features.
            removeFeature(FEATURE_ACTION_BAR);
            // System.out.println("Title Icons!");
        } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
                && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
            // Special case for a window with only a progress bar (and title).
            // XXX Need to have a no-title version of embedded windows.
            layoutResource = R.layout.screen_progress;
            // System.out.println("Progress!");
        } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
            // Special case for a window with a custom title.
            // If the window is floating, we need a dialog layout
            if (mIsFloating) {
                TypedValue res = new TypedValue();
                getContext().getTheme().resolveAttribute(
                        R.attr.dialogCustomTitleDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else {
                layoutResource = R.layout.screen_custom_title;
            }
            // XXX Remove this once action bar supports these features.
            removeFeature(FEATURE_ACTION_BAR);
        } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
            // If no other features and not embedded, only need a title.
            // If the window is floating, we need a dialog layout
            if (mIsFloating) {
                TypedValue res = new TypedValue();
                getContext().getTheme().resolveAttribute(
                        R.attr.dialogTitleDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
                layoutResource = a.getResourceId(
                        R.styleable.Window_windowActionBarFullscreenDecorLayout,
                        R.layout.screen_action_bar);
            } else {
                layoutResource = R.layout.screen_title;
            }
            // System.out.println("Title!");
        } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
            layoutResource = R.layout.screen_simple_overlay_action_mode;
        } else {
            // Embedded, so no decoration is needed.
            layoutResource = R.layout.screen_simple;
            // System.out.println("Simple!");
        }

        mDecor.startChanging();
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);

獲取到features根據(jù)不同的值加載不同的布局文件涣澡,最后將布局文件的id賦值給decorview,雖然是初始化mContentParent但是依然是為decorview賦值丧诺,我們看看這個(gè)值是怎么賦的

void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
        mStackId = getStackId();

        if (mBackdropFrameRenderer != null) {
            loadBackgroundDrawablesIfNeeded();
            mBackdropFrameRenderer.onResourcesLoaded(
                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
                    getCurrentColor(mNavigationColorViewState));
        }

        mDecorCaptionView = createDecorCaptionView(inflater);
        final View root = inflater.inflate(layoutResource, null);
        if (mDecorCaptionView != null) {
            if (mDecorCaptionView.getParent() == null) {
                addView(mDecorCaptionView,
                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
            }
            mDecorCaptionView.addView(root,
                    new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
        } else {

            // Put it below the color views.
            addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        }
        mContentRoot = (ViewGroup) root;
        initializeElevation();
    }

在這里創(chuàng)建一個(gè)布局入桂,把之前的資源xml加載成一個(gè)view,然后把view加載到布局中驳阎,至于這是個(gè)什么布局抗愁,注釋上寫(xiě)的是一個(gè)懸浮的帶標(biāo)題的view,不重要

  ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        if (contentParent == null) {
            throw new RuntimeException("Window couldn't find content container view");
        }

        if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
            ProgressBar progress = getCircularProgressBar(false);
            if (progress != null) {
                progress.setIndeterminate(true);
            }
        }

        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
            registerSwipeCallbacks(contentParent);
        }

        // Remaining setup -- of background and title -- that only applies
        // to top-level windows.
        if (getContainer() == null) {
            final Drawable background;
            if (mBackgroundResource != 0) {
                background = getContext().getDrawable(mBackgroundResource);
            } else {
                background = mBackgroundDrawable;
            }
            mDecor.setWindowBackground(background);

            final Drawable frame;
            if (mFrameResource != 0) {
                frame = getContext().getDrawable(mFrameResource);
            } else {
                frame = null;
            }
            mDecor.setWindowFrame(frame);

            mDecor.setElevation(mElevation);
            mDecor.setClipToOutline(mClipToOutline);

            if (mTitle != null) {
                setTitle(mTitle);
            }

            if (mTitleColor == 0) {
                mTitleColor = mTextColor;
            }
            setTitleColor(mTitleColor);
        }

        mDecor.finishChanging();

        return contentParent;

在這獲取到ID_ANDROID_CONTENT這個(gè)布局呵晚,然后獲取到一個(gè)viewGroup蜘腌,這個(gè)viewgroup就是我們初始化的mContentParent

小結(jié):可以看到在setContentView 中的installDecor進(jìn)行了大量的工作
初始化根布局decorView,并添加各種修飾,其本身是一個(gè)frameLayout饵隙,然后初始化了mContentparent撮珠,在初始化的時(shí)候獲取到window的屬性,賦值給phoneWindow金矛,根據(jù)屬性選取布局文件芯急,通過(guò)inflate轉(zhuǎn)化成view,并加入到decorview中去

 @Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

可以看到最后根據(jù)是否有過(guò)場(chǎng)動(dòng)畫(huà)把xml加載到mContentParent中去

接下來(lái)绷柒,讓我們捋一捋整個(gè)view的流程:
1.初始化decorview志于,這是一個(gè)根布局
2.在decorview中我們看到mDecorCaptionView這個(gè)view 加載了一個(gè)view涮因,那個(gè)view的layoutResource = R.layout.screen_simple
這個(gè)是個(gè)linearLayout,內(nèi)部包含content的frameLayout
3.接下來(lái),frameLayout就是mContentParent了慈迈,內(nèi)部加載我們想要加載的xml
盜一張網(wǎng)上的圖:

繼承自activity的結(jié)構(gòu)圖

對(duì)于AppCompatActivity的加載過(guò)程:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末迄损,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子澜掩,更是在濱河造成了極大的恐慌,老刑警劉巖刚陡,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筐乳,死亡現(xiàn)場(chǎng)離奇詭異蝙云,居然都是意外死亡勃刨,警方通過(guò)查閱死者的電腦和手機(jī)身隐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)躲因,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)大脉,“玉大人水孩,你說(shuō)我怎么就攤上這事俘种≈媪酰” “怎么了悬包?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵布近,是天一觀的道長(zhǎng)撑瞧。 經(jīng)常有香客問(wèn)我预伺,道長(zhǎng)酬诀,這世上最難降的妖魔是什么料滥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮高每,結(jié)果婚禮上鲸匿,老公的妹妹穿的比我還像新娘。我一直安慰自己运授,他們只是感情好吁朦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布逗宜。 她就那樣靜靜地躺著空骚,像睡著了一般囤屹。 火紅的嫁衣襯著肌膚如雪肋坚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天粟判,我揣著相機(jī)與錄音,去河邊找鬼吝沫。 笑死惨险,一個(gè)胖子當(dāng)著我的面吹牛脊髓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播恭朗,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼而芥!你這毒婦竟也來(lái)了棍丐?” 一聲冷哼從身側(cè)響起沧踏,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤趋翻,失蹤者是張志新(化名)和其女友劉穎踏烙,沒(méi)想到半個(gè)月后讨惩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寒屯,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡处面,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年魂角,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了野揪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞧栗。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡迹恐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出憎茂,到底是詐尸還是另有隱情唇辨,我是刑警寧澤赏枚,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布饿幅,位于F島的核電站,受9級(jí)特大地震影響透乾,放射性物質(zhì)發(fā)生泄漏磕秤。R本人自食惡果不足惜市咆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一磷瘤、第九天 我趴在偏房一處隱蔽的房頂上張望采缚。 院中可真熱鬧扳抽,春花似錦摔蓝、人聲如沸愉耙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)坚芜。三九已至,卻和暖如春沧竟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闪水。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工朽肥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衡招,地道東北人蚁吝。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像山林,于是被迫代替她去往敵國(guó)和親邢羔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驼抹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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