ViewModel源碼閱讀(二)SavedStateHandle的基本數(shù)據(jù)緩存原理

前言

閱讀本篇文章前最好先看上篇文章ViewModel源碼閱讀(一)ViewModel的生命周期
在閱讀SavedStateHandle之前钧椰,我們需要搞清上篇文章通過getLastNonConfigurationInstance和onRetainNonConfigurationInstance存儲的數(shù)據(jù)叠纷,與通過onSaveInstanceState和Bundle存儲的數(shù)據(jù)有什么不同
我這里直接就說出結(jié)論了
getLastNonConfigurationInstance是通過NonConfigurationInstances保存狀態(tài)的孵睬,這個狀態(tài)可以獲取的前提是進程沒有被銷毀
onSaveInstanceState中Bundle是通過Parcel保存狀態(tài)的,這種保存的狀態(tài)是非依附于進程的,當前進程被殺死,狀態(tài)也是保留的
詳細可以參考這篇文章,這里就不展開討論了

在上面邏輯基礎(chǔ)上,和上篇文章分析的ViewModel生命周期摊腋,我們可以推測出,ViewModel在進程被系統(tǒng)殺死時嘁傀,再恢復(fù)時兴蒸,是重新創(chuàng)建實例的,所以ViewModel引入了SavedStateHandle细办,來做輕量數(shù)據(jù)狀態(tài)暫存

分析代碼

這塊的代碼我第一次看的時候有點繞橙凳,因為關(guān)聯(lián)類太多了蕾殴,所以這塊代碼單獨獨立出來
下面開始閱讀源碼

  @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
        boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
        Constructor<T> constructor;
//獲取構(gòu)造函數(shù),判斷是否需要傳入SavedStateHandle
        if (isAndroidViewModel && mApplication != null) {
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
        // doesn't need SavedStateHandle
        if (constructor == null) {
            return mFactory.create(modelClass);
        }
//核心方法岛啸,用來創(chuàng)建Handle的關(guān)鍵代碼
//此處傳入了一個mSavedStateRegistry 和mLifecycle 作用暫時未知
//key和mDefaultArgs分別對應(yīng)ViewModel的唯一標識和getIntent中暫存的數(shù)據(jù)
        SavedStateHandleController controller = SavedStateHandleController.create(
                mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
        try {
            T viewmodel;
//下面的代碼就是傳入handle的
            if (isAndroidViewModel && mApplication != null) {
                viewmodel = constructor.newInstance(mApplication, controller.getHandle());
            } else {
                viewmodel = constructor.newInstance(controller.getHandle());
            }
            viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
            return viewmodel;
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Failed to access " + modelClass, e);
        } catch (InstantiationException e) {
            throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("An exception happened in constructor of "
                    + modelClass, e.getCause());
        }
    }

代碼集中在create方法钓觉,我們繼續(xù)研究create里是都創(chuàng)建了什么

    static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
//通過registry獲取Bundle ,此處推測registry應(yīng)該也是一個存儲數(shù)據(jù)的封裝類坚踩,此處代碼應(yīng)該是一個恢復(fù)獲取狀態(tài)的代碼
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
//創(chuàng)建ViewModel中的Handle
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
//創(chuàng)建對外提供的controller
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
//下面這兩段代碼等將SavedStateRegistry研究明白再看
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

上面的代碼大體就是一個SavedStateHandleController創(chuàng)建過程荡灾,涉及到SavedStateRegistry,SavedStateHandleController兩個類和controller.attachToLifecycle瞬铸,tryToAddRecreator兩個方法
先研究SavedStateRegistry
在SavedStateViewModelFactory發(fā)現(xiàn)SavedStateRegistry是SavedStateViewModelFactory構(gòu)造函數(shù)在SavedStateRegistryOwner中獲取的批幌,SavedStateRegistryOwner是在CommponentActivity中實現(xiàn)的,主要是一個getSavedStateRegistry的實現(xiàn)
而getSavedStateRegistry方法設(shè)計到mSavedStateRegistryController變量嗓节。荧缘。。
mSavedStateRegistryController變量在類成員變量中初始化拦宣,代碼如下

ComponentActivity
    final SavedStateRegistryController mSavedStateRegistryController =
            SavedStateRegistryController.create(this);

SavedStateRegistryController的代碼如下胜宇,

public final class SavedStateRegistryController {
    private final SavedStateRegistryOwner mOwner;
    private final SavedStateRegistry mRegistry;
//在構(gòu)造函數(shù)傳入一個Lifecycle的Owner
    private SavedStateRegistryController(SavedStateRegistryOwner owner) {
        mOwner = owner;
//這個玩意整體看了下,應(yīng)該是真正零時緩存數(shù)據(jù)的操作類(google 你來解釋下為啥要套的這么深恢着?沒有更好的方案了嗎?)
        mRegistry = new SavedStateRegistry();
    }

  //提供對外使用的操作存儲類
    @NonNull
    public SavedStateRegistry getSavedStateRegistry() {
        return mRegistry;
    }

//這里是核心代碼财破,一行一行注釋掰派,主要是數(shù)據(jù)使用前封裝
//這里主要是將恢復(fù)后的數(shù)據(jù)拿到,而且通過lifecycle將獲取時機控制在onCreate中
    @MainThread
    public void performRestore(@Nullable Bundle savedState) {
//此處拿到在ComponentActivity實例的SavedStateRegistryOwner
        Lifecycle lifecycle = mOwner.getLifecycle();
//如果Lifecycle.State的狀態(tài)在OnCreate之前會回調(diào)到這里左痢,說明是有問題的靡羡,拋出異常
        if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
            throw new IllegalStateException("Restarter must be created only during "
                    + "owner's initialization stage");
        }
//這里做個一個一次性事件的添加,為啥是一次性俊性?Recreator里面會解答
        lifecycle.addObserver(new Recreator(mOwner));
//將savedState里的Bundle讀出來略步,下面會分析
        mRegistry.performRestore(lifecycle, savedState);
    }

//數(shù)據(jù)保存前封裝 outBundle就是onSaveInstanceState中的Bundle
    @MainThread
    public void performSave(@NonNull Bundle outBundle) {
        mRegistry.performSave(outBundle);
    }

    //提供快捷創(chuàng)建函數(shù)
    @NonNull
    public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
        return new SavedStateRegistryController(owner);
    }
}

上面這段代碼主要有三個工作內(nèi)容
1,將ComponentActivity的lifeCycle拿到
2定页,在創(chuàng)建真正的讀取保存類SavedStateRegistry
3趟薄,控制將恢復(fù)數(shù)據(jù)的時機控制在onCreate,并封裝SavedStateRegistry

最后看SavedStateRegistry幾個關(guān)鍵代碼


//這里savedState 是ComponentActivity里onCreate中的savedInstanceState 通過mSavedStateRegistryController.performRestore傳入
   @MainThread
    void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
        if (mRestored) {
            throw new IllegalStateException("SavedStateRegistry was already restored.");
        }
//這里獲取到恢復(fù)的savedState里面的數(shù)據(jù)在 performSave 中可以看到格式
        if (savedState != null) {
//此處的mRestoredState在SavedStateHandleController中的 registry.consumeRestoredStateForKey會用到
            mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
        }
//做了一個監(jiān)聽典徊,如果執(zhí)行了Lifecycle.Event.ON_STOP 的話杭煎,記錄mAllowingSavingState,用來判斷是否是正常流程
        lifecycle.addObserver(new GenericLifecycleObserver() {
            @Override
            public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_START) {
                    mAllowingSavingState = true;
                } else if (event == Lifecycle.Event.ON_STOP) {
                    mAllowingSavingState = false;
                }
            }
        });
//做了一個是否恢復(fù)的標記卒落,
        mRestored = true;
    }
這里是當onSaveInstanceState執(zhí)行時羡铲,執(zhí)行的代碼
 @MainThread
    void performSave(@NonNull Bundle outBundle) {
//將內(nèi)存中的數(shù)據(jù)全部裝進來
        Bundle components = new Bundle();
        if (mRestoredState != null) {
            components.putAll(mRestoredState);
        }
//遍歷各個生成的handle,保存handle中的數(shù)據(jù)儡毕,后面看handler源碼就會發(fā)現(xiàn)每個handle都會保存一個SavedStateProvider
        for (Iterator<Map.Entry<String, SavedStateProvider>> it =
                mComponents.iteratorWithAdditions(); it.hasNext(); ) {
            Map.Entry<String, SavedStateProvider> entry1 = it.next();
            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
        }
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
    }

上面代碼主要做了一個數(shù)據(jù)讀取和保存也切,和我們平時寫普通的數(shù)據(jù)零時保存一樣,只是做了封裝,mRestoredState作為存儲和讀取的所有數(shù)據(jù)的全局變量
最后看下ComponentActivity

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
       //代碼不多雷恃,沒做代碼省略疆股,這句話執(zhí)行后,相當于就是從恢復(fù)中拿到了數(shù)據(jù)
        mSavedStateRegistryController.performRestore(savedInstanceState);
        mContextAwareHelper.dispatchOnContextAvailable(this);
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }
  @CallSuper
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Lifecycle lifecycle = getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
        }
        super.onSaveInstanceState(outState);
//這句話執(zhí)行后褂萧,將數(shù)據(jù)零時存儲在恢復(fù)區(qū)
        mSavedStateRegistryController.performSave(outState);
    }

所以通過以上代碼的閱讀押桃,我們已經(jīng)發(fā)現(xiàn),SavedStateHandle的核心邏輯就是通過onSaveInstanceState做臨時存儲导犹,數(shù)據(jù)恢復(fù)只是封裝了兩層唱凯,做了很多邏輯判斷
SavedStateRegistryController->SavedStateRegistry->執(zhí)行恢復(fù)存儲。
再回到SavedStateHandleController

static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
//這行代碼谎痢,下面會簡單看下磕昼,主要是為了去哪在系統(tǒng)恢復(fù)Activity時,通過getIntent中的內(nèi)容
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
//這里創(chuàng)建Handle核心代碼
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
//創(chuàng)建controller 主要是綁定registry數(shù)據(jù)和handle中mSavedStateProvider的關(guān)系
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

先簡單看下consumeRestoredStateForKey中的東西

    @MainThread
    @Nullable
    public Bundle consumeRestoredStateForKey(@NonNull String key) {
        if (!mRestored) {
            throw new IllegalStateException("You can consumeRestoredStateForKey "
                    + "only after super.onCreate of corresponding component");
        }
        if (mRestoredState != null) {
            Bundle result = mRestoredState.getBundle(key);
            mRestoredState.remove(key);
            if (mRestoredState.isEmpty()) {
                mRestoredState = null;
            }
            return result;
        }
        return null;
    }

代碼很簡單节猿,主要是通過ViewModel唯一關(guān)鍵字獲取mRestoredState里存儲的Bundle票从,而這個mRestoredState我們前面代碼已經(jīng)知道就是用來做activity銷毀前存儲和activtiy恢復(fù)時讀取的Bundle,所以這里相當于通過Viewmodle的Key獲取在ViewModel中臨時存儲的數(shù)據(jù)
再看createHandle的代碼


    static SavedStateHandle createHandle(@Nullable Bundle restoredState,
            @Nullable Bundle defaultState) {
//如果沒有需要緩存或者恢復(fù)的數(shù)據(jù)滨嘱,直接創(chuàng)建SavedStateHandle
        if (restoredState == null && defaultState == null) {
            return new SavedStateHandle();
        }
        Map<String, Object> state = new HashMap<>();
        if (defaultState != null) {
            for (String key : defaultState.keySet()) {
                state.put(key, defaultState.get(key));
            }
        }
//如果有需要緩存的數(shù)據(jù)創(chuàng)建且沒有恢復(fù)數(shù)據(jù)的情況峰鄙,一個帶緩存數(shù)據(jù)的SavedStateHandle

        if (restoredState == null) {
            return new SavedStateHandle(state);
        }

        ArrayList keys = restoredState.getParcelableArrayList(KEYS);
        ArrayList values = restoredState.getParcelableArrayList(VALUES);
        if (keys == null || values == null || keys.size() != values.size()) {
            throw new IllegalStateException("Invalid bundle passed as restored state");
        }
        for (int i = 0; i < keys.size(); i++) {
            state.put((String) keys.get(i), values.get(i));
        }
//如果兩個都有,那就兩個都塞進去
        return new SavedStateHandle(state);
    }

這里需要看下handle把數(shù)據(jù)存到哪里了太雨,在構(gòu)造函數(shù)中


    /**
     * Creates a handle with the given initial arguments.
     */
    public SavedStateHandle(@NonNull Map<String, Object> initialState) {
        mRegular = new HashMap<>(initialState);
    }

    /**
     * Creates a handle with the empty state.
     */
    public SavedStateHandle() {
        mRegular = new HashMap<>();
    }

我們發(fā)現(xiàn)剛剛的數(shù)據(jù)全部塞到mRegular中了
這個mRegular就是一個Map吟榴,并且提供給外部使用


    /**
     * Returns a value associated with the given key.
     */
    @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
    @MainThread
    @Nullable
    public <T> T get(@NonNull String key) {
        return (T) mRegular.get(key);
    }

    /**
     * Associate the given value with the key. The value must have a type that could be stored in
     * {@link android.os.Bundle}
     *
     * @param <T> any type that can be accepted by Bundle.
     */
    @MainThread
    public <T> void set(@NonNull String key, @Nullable T value) {
        validateValue(value);
        @SuppressWarnings("unchecked")
        MutableLiveData<T> mutableLiveData = (MutableLiveData<T>) mLiveDatas.get(key);
        if (mutableLiveData != null) {
            // it will set value;
            mutableLiveData.setValue(value);
        } else {
            mRegular.put(key, value);
        }
    }

也就是說handle主要是提供了一個mRegular的Map提供業(yè)務(wù)層讀取和存儲(甚至提供了一個LiveData,這里就不展開了)囊扳,但是真實存儲的時候吩翻,我們發(fā)現(xiàn)是下面這段代碼(上面已經(jīng)閱讀過,需要重新看下)

 @MainThread
    void performSave(@NonNull Bundle outBundle) {
...
        for (Iterator<Map.Entry<String, SavedStateProvider>> it =
                mComponents.iteratorWithAdditions(); it.hasNext(); ) {
            Map.Entry<String, SavedStateProvider> entry1 = it.next();
            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
        }
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
    }

這里發(fā)現(xiàn)是遍歷的mComponents中的SavedStateProvider锥咸,執(zhí)行的saveState方法狭瞎,在Handle中也存在這樣一段代碼

    private final SavedStateProvider mSavedStateProvider = new SavedStateProvider() {
        @SuppressWarnings("unchecked")
        @NonNull
        @Override
        public Bundle saveState() {
            // Get the saved state from each SavedStateProvider registered with this
            // SavedStateHandle, iterating through a copy to avoid re-entrance
            Map<String, SavedStateProvider> map = new HashMap<>(mSavedStateProviders);
            for (Map.Entry<String, SavedStateProvider> entry : map.entrySet()) {
                Bundle savedState = entry.getValue().saveState();
                set(entry.getKey(), savedState);
            }
            // Convert the Map of current values into a Bundle
            Set<String> keySet = mRegular.keySet();
            ArrayList keys = new ArrayList(keySet.size());
            ArrayList value = new ArrayList(keys.size());
            for (String key : keySet) {
                keys.add(key);
                value.add(mRegular.get(key));
            }

            Bundle res = new Bundle();
            // "parcelable" arraylists - lol
            res.putParcelableArrayList("keys", keys);
            res.putParcelableArrayList("values", value);
            return res;
        }
    };

上面的代碼沒有寫注釋,大體意思就是把mRegular中的數(shù)據(jù)塞到Bundle里搏予,我們可以聯(lián)想熊锭,應(yīng)該是在performSave時,調(diào)用handle中的SavedStateProvider里的saveState方法獲取Bundle并保存的雪侥,那就是handle中的SavedStateProvider會存到SavedStateRegistry的mComponents中球涛。。但是在哪塞入的呢校镐?我們再回到SavedStateHandleController中看下一個方法

  static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
//目前只有下面這兩句可能會將handle里的SavedStateProvider和SavedStateRegistry里的mComponents做數(shù)據(jù)綁定了
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

先看attachToLifecycle

    void attachToLifecycle(SavedStateRegistry registry, Lifecycle lifecycle) {
        if (mIsAttached) {
            throw new IllegalStateException("Already attached to lifecycleOwner");
        }
        mIsAttached = true;
        lifecycle.addObserver(this);
//這句話明顯感覺就是用來綁定數(shù)據(jù)的
        registry.registerSavedStateProvider(mKey, mHandle.savedStateProvider());
    }

再看registerSavedStateProvider

    @MainThread
    public void registerSavedStateProvider(@NonNull String key,
            @NonNull SavedStateProvider provider) {
//這里果然做了數(shù)據(jù)put
        SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
        if (previous != null) {
            throw new IllegalArgumentException("SavedStateProvider with the given key is"
                    + " already registered");
        }
    }

SafeIterableMap mComponents

    public V putIfAbsent(@NonNull K key, @NonNull V v) {
        Entry<K, V> entry = get(key);
        if (entry != null) {
            return entry.mValue;
        }
        put(key, v);
        return null;
    }

看過最后這塊代碼亿扁,我們整個Handle的邏輯就很清晰了,下面說下文字流程

1在通過SavedStateViewModelFactory創(chuàng)建ViewModel時鸟廓,先通過構(gòu)造函數(shù)入?yún)⑴袛嗍欠翊嬖赟avedStateHandle入?yún)⒋幼#绻嬖诰蛨?zhí)行創(chuàng)建SavedStateHandleController
2通過SavedStateHandleController.create創(chuàng)建SavedStateHandleController襟己,在創(chuàng)建SavedStateHandleController時將Activtiy中實現(xiàn)的SavedStateRegistryOwner通過getSavedStateRegistry傳入mSavedStateRegistry
3mSavedStateRegistry在ComponentActivity通過SavedStateRegistryController.create()實例,并且在ComponentActivity中onCreate里執(zhí)行了performRestore方法牍陌,在onSaveInstanceState里執(zhí)行了performSave方法
4在SavedStateHandleController創(chuàng)建時擎浴,先獲取mSavedStateRegistry在ComponentActivity里的onCreate是獲取到的數(shù)據(jù),并且將數(shù)據(jù)塞到創(chuàng)建的SavedStateHandle中的mRegular里
5再將SavedStateHandle封裝到 SavedStateHandleController中毒涧,并將handel里的mSavedStateProvider塞到mSavedStateRegistry中的mComponents中
6當Activity被系統(tǒng)殺死時贮预,執(zhí)行onSaveInstanceState,觸發(fā)mSavedStateRegistry.performSave
7在performSave時契讲,遍歷mComponents仿吞,執(zhí)行mSavedStateProvider的saveState封裝數(shù)據(jù),塞到onSaveInstanceState的Bundle里

最后上自己畫的handle代碼簡易邏輯圖


handle代碼簡易邏輯圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捡偏,一起剝皮案震驚了整個濱河市唤冈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌银伟,老刑警劉巖你虹,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異彤避,居然都是意外死亡傅物,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門琉预,熙熙樓的掌柜王于貴愁眉苦臉地迎上來董饰,“玉大人,你說我怎么就攤上這事模孩。” “怎么了贮缅?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵榨咐,是天一觀的道長。 經(jīng)常有香客問我谴供,道長块茁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任桂肌,我火速辦了婚禮数焊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘崎场。我一直安慰自己佩耳,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布谭跨。 她就那樣靜靜地躺著干厚,像睡著了一般李滴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛮瞄,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天所坯,我揣著相機與錄音,去河邊找鬼挂捅。 笑死芹助,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的闲先。 我是一名探鬼主播状土,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼饵蒂!你這毒婦竟也來了声诸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤退盯,失蹤者是張志新(化名)和其女友劉穎彼乌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渊迁,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡慰照,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了琉朽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毒租。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖箱叁,靈堂內(nèi)的尸體忽然破棺而出墅垮,到底是詐尸還是另有隱情,我是刑警寧澤耕漱,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布算色,位于F島的核電站,受9級特大地震影響螟够,放射性物質(zhì)發(fā)生泄漏灾梦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一妓笙、第九天 我趴在偏房一處隱蔽的房頂上張望若河。 院中可真熱鬧,春花似錦寞宫、人聲如沸萧福。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽统锤。三九已至毛俏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饲窿,已是汗流浹背煌寇。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逾雄,地道東北人阀溶。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像鸦泳,于是被迫代替她去往敵國和親银锻。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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