Android學(xué)習(xí)筆記之MVP框架模式

前言

在學(xué)習(xí)了 MVC 架構(gòu)之后,發(fā)現(xiàn) Activity 和 Fragment 和 XML 界面的開(kāi)發(fā)就是典型的 MVC 架構(gòu)模式,在 Activity 中不僅要處理 UI 操作奠伪,還要處理請(qǐng)求數(shù)據(jù)的操作。

然而在我接觸到的開(kāi)發(fā)項(xiàng)目中合溺,看到一個(gè) Activity 中的代碼行數(shù)接近上千行是常態(tài)。在修改的過(guò)程中經(jīng)常要在類里面不斷的翻上翻下的,修改起來(lái)也非常費(fèi)勁芦缰。

這樣就導(dǎo)致了 MVC 架構(gòu)模式耦合度太高、職責(zé)不明確枫慷,不易于維護(hù)的原因让蕾,這次就來(lái)學(xué)習(xí) MVC 的演變出來(lái)的 MVP 架構(gòu)模式。

MVC 的工作原理: MVC 即 Model View Controller流礁,簡(jiǎn)單來(lái)說(shuō)就是通過(guò) Controller 的控制去操作 Model 層的數(shù)據(jù)涕俗,并且返回給 View 層展示。當(dāng)用戶觸發(fā)事件的時(shí)候神帅,View 層會(huì)發(fā)送指令到 Controller 層再姑,接著 Controller 去通知 Model 層更新數(shù)據(jù),Model 層更新完數(shù)據(jù)以后直接顯示在 View 層上找御,這就是 MVC 的工作原理元镀。

MVP是什么

MVP 的全稱是 Model-View-Presenter,MVP 是 MVC 的一種演進(jìn)版本霎桅,將 MVC 中的 Controller 改為了 Presenter栖疑,View 通過(guò)接口與 Presenter 進(jìn)行交互,有效降低 View(Activity / Fragment) 的復(fù)雜性滔驶,避免業(yè)務(wù)邏輯被塞進(jìn) View 中遇革,使得 View 變得臃腫。

另外揭糕,MVP 模式會(huì)解除 View 與 Model 的耦合萝快,同時(shí)又帶來(lái)了良好的可擴(kuò)展性、可測(cè)試性著角,保證了系統(tǒng)的整潔性揪漩、靈活性。雖然在簡(jiǎn)單的應(yīng)用中可能會(huì)因?yàn)楦鞣N接口變得復(fù)雜吏口,但在稍有規(guī)模的應(yīng)用中奄容,依然能保持結(jié)構(gòu)的整潔和靈活。

MVP的結(jié)構(gòu)

  • Model 主要是提供數(shù)據(jù)的存取功能产徊,Presenter 需要通過(guò) Model 層存儲(chǔ)和獲取數(shù)據(jù)昂勒,Model 就像一個(gè)數(shù)據(jù)倉(cāng)庫(kù)。Model 是管理數(shù)據(jù)庫(kù)和網(wǎng)絡(luò)獲取數(shù)據(jù)的角色舟铜。

  • View 一般是指 Activity 和 Fragmen t等叁怪,它含有一個(gè) Presenter 成員變量。通常 View 需要實(shí)現(xiàn)一個(gè)邏輯接口深滚,將 View 上的操作轉(zhuǎn)交給 Presenter 進(jìn)行實(shí)現(xiàn)奕谭,最后 Presenter 調(diào)用 View 的邏輯接口將結(jié)果返回給 View 元素涣觉。

  • Presenter 作為 View 與 Model 交互的中間紐帶,處理與用戶交互的負(fù)責(zé)邏輯血柳。它從 Model 層檢索數(shù)據(jù)后官册,返回給 View 層,使得 View 和 Model 之間沒(méi)有耦合难捌,也將業(yè)務(wù)邏輯從View角色上抽離出來(lái)膝宁。

mvp.jpg

在通常開(kāi)發(fā)中,View是指 Activity / Fragment根吁,不過(guò)员淫,Presenter 和 Activity 通過(guò)定義一個(gè) view 接口進(jìn)行關(guān)聯(lián),而 Presenter 和 Model 是通過(guò) Callback 接口進(jìn)行關(guān)聯(lián)击敌。

  • View接口:顯示提示框介返、數(shù)據(jù)更新;
  • Callback接口:請(qǐng)求數(shù)據(jù)時(shí)反饋狀態(tài)(成功沃斤、失敗和異常等等)圣蝎;
mvp.png

MVP的優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  1. 分離了視圖邏輯和業(yè)務(wù)邏輯,降低了耦合衡瓶。

  2. Activity 只處理生命周期的任務(wù)徘公,代碼變得更加簡(jiǎn)潔

  3. 視圖邏輯和業(yè)務(wù)邏輯分別抽象到了 View 和 Presenter 的接口中去哮针,提高代碼的可閱讀性关面。

  4. Presenter 被抽象成接口,可以有多種具體的實(shí)現(xiàn)十厢,所以方便進(jìn)行單元測(cè)試等太。

  5. 把業(yè)務(wù)邏輯抽到 Presenter 中去,避免后臺(tái)線程引用著 Activity 導(dǎo)致 Activity 的資源無(wú)法被系統(tǒng)回收從而引起內(nèi)存泄露寿烟。

  6. Presenter 代碼可復(fù)用澈驼,一個(gè) Presenter 可以用于多個(gè) View辛燥,而不需要更改 Presenter 的邏輯筛武。

缺點(diǎn)

  1. Presenter 中除了應(yīng)用邏輯以外,還有大量的 View->Model挎塌,Model->View 的手動(dòng)同步邏輯徘六,造成 Presenter 比較笨重,維護(hù)起來(lái)會(huì)比較困難榴都。

  2. 由于對(duì)視圖的渲染放在了 Presenter 中待锈,所以視圖和 Presenter 的交互會(huì)過(guò)于頻繁。

  3. 如果 Presenter 過(guò)多地渲染了視圖嘴高,往往會(huì)使得它與特定的視圖的聯(lián)系過(guò)于緊密竿音。一旦視圖需要變更和屎,那么 Presenter 也需要變更了。

  4. 額外的代碼復(fù)雜度及學(xué)習(xí)成本春瞬。

MVP 和 MVC 的區(qū)別

  • MVP 是基于 MVC 模式上演變過(guò)來(lái)柴信,與 MVC 有一定的相似性,Controller 和 Presenter 負(fù)責(zé)邏輯的處理宽气,Model 提供數(shù)據(jù)随常,View 負(fù)責(zé)顯示。

  • 在 MVC 中萄涯,當(dāng) Model 被 Controller 更新后绪氛,Model 會(huì)直接通知 View 并更新顯示。而在 MVP 中涝影,Model 與 View 不存在直接關(guān)系枣察,這兩者之間間隔著的是 Presenter 層,其負(fù)責(zé)調(diào)控 View 與 Model 之間的間接交互袄琳,這也是 MVP 和 MVC 兩者之間最大的區(qū)別询件。

  • 此外 Presenter 與 View、Model 的交互使用接口定義交互操作可以降低耦合唆樊、簡(jiǎn)化代碼宛琅。

MVP 與 Activity、Fragment 的生命周期

  • 問(wèn)題原因:由于 Model 在進(jìn)行異步操作逗旁,例如請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)嘿辟,Presenter 持有 Activity 的強(qiáng)引用,如果在請(qǐng)求結(jié)束之前使得 Activity 被銷毀了片效,那么由于網(wǎng)絡(luò)請(qǐng)求還沒(méi)有返回红伦,導(dǎo)致 Presenter 持有 Activity 對(duì)象,使得 Activity 無(wú)法被回收淀衣,此時(shí)就會(huì)發(fā)生內(nèi)存泄露昙读。(也許應(yīng)用中出現(xiàn)一次兩次內(nèi)存泄漏不會(huì)造成多大的影響,但應(yīng)用在長(zhǎng)時(shí)間使用后膨桥,若這些占據(jù)系統(tǒng)的大量?jī)?nèi)存的 Activity 得不到 GC 回收的話蛮浑,最終會(huì)導(dǎo)致 OOM 的出現(xiàn),就會(huì)直接 Crash 應(yīng)用只嚣。)
  • 解決辦法:通過(guò)弱引用和 Activity沮稚、Fragment 的生命周期來(lái)綁定/解綁 View 解決這個(gè)問(wèn)題,建立 BasePresenter册舞,是一個(gè)泛型類 蕴掏,泛型類型為 View 角色要實(shí)現(xiàn)的接口類型 。
  • 好處:Presenter 不需要在構(gòu)造函數(shù)中傳入 View 對(duì)象,而是在 View 中自由地通過(guò)Presenter 的 attachView 方法和 detachView 方法綁定和解綁 View 對(duì)象盛杰,除了 attachViewdetachView挽荡,我們還可以另外聲明 onResume 和 onStop 方法。

Model層的單獨(dú)優(yōu)化

前面講了 View 和 Presenter 兩個(gè)層次即供,而 Model 層比較特殊徐伐,相對(duì)比較獨(dú)立的存在,幫上層拿數(shù)據(jù)募狂,這是因?yàn)?MVP 模式的理念就是讓業(yè)務(wù)邏輯相互獨(dú)立办素。但如果每個(gè)網(wǎng)絡(luò)請(qǐng)求也獨(dú)立成單個(gè) Model 的話,代碼操作起來(lái)也會(huì)非常麻煩祸穷,比如:

  1. 無(wú)法對(duì)所有 Model 統(tǒng)一管理性穿;
  2. 每個(gè) Model 對(duì)外提供的獲取數(shù)據(jù)方法不一樣,上層請(qǐng)求數(shù)據(jù)沒(méi)有規(guī)范雷滚;
  3. 代碼冗余需曾,重復(fù)性代碼多;
  4. 對(duì)已存在的 Model 進(jìn)行修改繁瑣祈远;

那么就需要對(duì) Model 進(jìn)行封裝優(yōu)化呆万,使得 Model 層變成一個(gè)龐大且獨(dú)立單一的模塊,請(qǐng)求方式規(guī)范化车份,管理直觀化:

  1. 數(shù)據(jù)請(qǐng)求能夠單獨(dú)編寫和測(cè)試谋减,無(wú)需配合上層界面測(cè)試;
  2. 統(tǒng)一以 DataModel 類作為數(shù)據(jù)請(qǐng)求層的入口扫沼,通過(guò)反射機(jī)制獲取對(duì)應(yīng)的 Model出爹;
  3. 無(wú)縫切換不同的數(shù)據(jù)源(網(wǎng)絡(luò)請(qǐng)求庫(kù)、緩存缎除、數(shù)據(jù)庫(kù))严就;

MVP結(jié)構(gòu)圖

MVP模式詳細(xì)結(jié)構(gòu)圖

示例代碼

  • IBaseView:View接口中定義Activity的UI邏輯

    public interface IBaseView {
        void showLoading();
        void hideLoading();
        void showToast(String msg);
        void showErr();
        Context getContext();
    }
    
  • BaseActivity:主要是負(fù)責(zé)實(shí)現(xiàn) BaseView 中通用的UI邏輯方法,如此這些通用的方法就不用每個(gè)Activity都要去實(shí)現(xiàn)一遍了器罐。

    public abstract class BaseActivity extends AppCompatActivity implements IBaseView {
        // 加載條
        private ProgressDialog mProgressDialog;
    
        // 獲取Presenter實(shí)例梢为,子類實(shí)現(xiàn)
        public abstract BasePresenter getPresenter();
        // 初始化Presenter的實(shí)例,子類實(shí)現(xiàn)
        public abstract void initPresenter();
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 初始化Presenter
            initPresenter();
            if (getPresenter()!=null){
                getPresenter().attachView(this);
            }
            // 初始化進(jìn)度條
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setCancelable(false);
        }
        @Override
        public void showLoading() {
            if (!mProgressDialog.isShowing()) {
                mProgressDialog.show();
            }
        }
        @Override
        public void hideLoading() {
            if (mProgressDialog.isShowing()) {
                mProgressDialog.dismiss();
            }
        }
        @Override
        public void showToast(String msg) {
            Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
        }
        @Override
        public void showErr() {
            showToast("err....");
        }
        @Override
        public Context getContext() {
            return BaseActivity.this;
        }
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (getPresenter() != null){
                getPresenter().detachView();
            }
        }
    }
    
  • MainActivity:繼承了BaseActivity抽象類轰坊,實(shí)現(xiàn)了getPresenter和initPresenter完成P層綁定铸董。實(shí)現(xiàn)IMvpView接口中的showData達(dá)到UI更新操作。

    public class MainActivity extends BaseActivity implements IMvpView {
        TextView mTextView;
        MvpPresenter mvpPresenter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main3);
            mTextView = findViewById(R.id.text);
        }
        @Override
        public BasePresenter getPresenter() {
            return mvpPresenter;
        }
        @Override
        public void initPresenter() {
            mvpPresenter = new MvpPresenter(); //初始化Presenter
            // mvpPresenter.attachView(this);// attachView放在抽象父類中
        }
        // 按鈕1
        public void getData(View view) {
            mvpPresenter.getData("normal");
        }
        // 按鈕2
        public void getDataForFailure(View view) {
            mvpPresenter.getData("failure");
        }
        // 按鈕3
        public void getDataForError(View view) {
            mvpPresenter.getData("error");
        }
        @Override
        public void showData(String data) {
            mTextView.setText(data);
        }
    }
    
  • IMvpView:IMvpView是Activity與Presenter層的中間層衰倦,它的作用是根據(jù)具體業(yè)務(wù)的需要袒炉,為Presenter提供調(diào)用Activity中具體UI邏輯操作的方法旁理。

    /**
     * View接口是Activity與Presenter層的中間層樊零,它的作用是根據(jù)具體業(yè)務(wù)的需要,
     * 為Presenter提供調(diào)用Activity中具體UI邏輯操作的方法。
     */
    public interface IMvpView extends IBaseView {
        /**
         * 當(dāng)數(shù)據(jù)請(qǐng)求成功后驻襟,調(diào)用此接口顯示數(shù)據(jù)
         * @param data 數(shù)據(jù)源
         */
        void showData(String data);
    }
    
  • BasePresenter:處理View的生命周期夺艰;

    public class BasePresenter<V extends IBaseView> {
        // 綁定的view
        private V mView;
        // 綁定view,一般在初始化中調(diào)用該方法
        public void attachView(V mvpView) {
            this.mView = mvpView;
        }
        //  斷開(kāi)view沉衣,一般在onDestroy中調(diào)用
        public void detachView() {
            this.mView = null;
        }
        // 是否與View建立連接郁副,每次請(qǐng)求業(yè)務(wù)之前都要判斷
        public boolean isViewAttached() {
            return mView != null;
        }
        // 獲取當(dāng)前連接的view
        public V getmView() {
            return mView;
        }
    }
    
  • MvpPresenter:該類是具體的邏輯業(yè)務(wù)處理類,負(fù)責(zé)請(qǐng)求數(shù)據(jù)豌习,并對(duì)數(shù)據(jù)請(qǐng)求的反饋進(jìn)行處理存谎。

    public class MvpPresenter extends BasePresenter<IMvpView> {
        /**
         * 獲取網(wǎng)絡(luò)數(shù)據(jù)
         * @param userId
         */
        public void getData(String userId) {
            if (!isViewAttached()) {
                return;
            }
            //顯示進(jìn)度條
            getmView().showLoading();
            DataModel.request1(UserDataModel.class)
                    .params(userId).execute(new MvpCallback() {
                @Override
                public void onSuccess(Object data) {
                    //調(diào)用view接口顯示數(shù)據(jù)
                    if (isViewAttached()) {
                        getmView().showData((String) data);
                    }
                }
                @Override
                public void onFailure(String msg) {
                    if (isViewAttached()) {
                        getmView().showToast(msg);
                    }
                }
                @Override
                public void onError() {
                    if (isViewAttached()) {
                        getmView().showErr();
                    }
                }
                @Override
                public void onComplete() {
                    if (isViewAttached()) {
                        getmView().hideLoading();
                    }
                }
            });
        }
    }
    
  • MvpCallback

    /**
     * Callback 接口是Model層給Presenter層反饋請(qǐng)求信息的傳遞載體,
     * 所以需要在Callback中定義數(shù)據(jù)請(qǐng)求的各種反饋狀態(tài)
     * 除了請(qǐng)求成功的回調(diào)方法肥隆,其他的像請(qǐng)求失敗既荚,請(qǐng)求出錯(cuò)這些方法我們做的事幾乎是一樣的。
     * 后期可以構(gòu)建一個(gè)通用的BaseCallBack去處理請(qǐng)求的異常情況
     */
    public interface MvpCallback<T> {
        /**
         * 數(shù)據(jù)請(qǐng)求成功
         * @param data 請(qǐng)求到的數(shù)據(jù)
         */
        void onSuccess(T data);
        /**
         * 網(wǎng)絡(luò)返回?cái)?shù)據(jù)失敗栋艳,請(qǐng)求成功
         * @param msg 無(wú)法正常返回?cái)?shù)據(jù)的原因
         */
        void onFailure(String msg);
        /**
         * 請(qǐng)求數(shù)據(jù)失敗恰聘、無(wú)法聯(lián)網(wǎng)、缺少權(quán)限吸占、內(nèi)存泄露等等原因
         */
        void onError();
        /**
         * 無(wú)論執(zhí)行上面那個(gè)方法晴叨,最后都會(huì)執(zhí)行此方法,可以在這里設(shè)置隱藏加載框
         */
        void onComplete();
    }
    
  • DataModel:通過(guò)反射機(jī)制獲取對(duì)應(yīng)的model

    public class DataModel {
        public static <T extends BaseModel> T request1(Class<T> cls) {
            // 聲明一個(gè)空的BaseModel
            T model = null;
            try {
                //利用反射機(jī)制獲得對(duì)應(yīng)Model對(duì)象的引用
                model = (T) cls.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return model;
        }
    }
    
  • BaseModel:定義了對(duì)外的請(qǐng)求數(shù)據(jù)規(guī)則矾屯,包括設(shè)置參數(shù)的方法和設(shè)置Callback的方法兼蕊,還可以定義一些通用的數(shù)據(jù)請(qǐng)求方法,比如說(shuō)網(wǎng)絡(luò)請(qǐng)求的Get和Post方法件蚕。
    public abstract class BaseModel<T> {
        //數(shù)據(jù)請(qǐng)求參數(shù)
        protected String[] mParams;
        /**
         * 設(shè)置數(shù)據(jù)請(qǐng)求參數(shù)
         * @param args 參數(shù)數(shù)組
         */
        public BaseModel params(String... args) {
            mParams = args;
            return this;
        }
        // 添加Callback并執(zhí)行數(shù)據(jù)請(qǐng)求
        // 具體的數(shù)據(jù)請(qǐng)求由子類實(shí)現(xiàn)
        public abstract void execute(MvpCallback<T> callback);
        // 執(zhí)行Get網(wǎng)絡(luò)請(qǐng)求遍略,此類看需求由自己選擇寫與不寫
        protected void requestGetAPI(String url, MvpCallback<T> callback) {
            //這里寫具體的網(wǎng)絡(luò)請(qǐng)求
        }
        // 執(zhí)行Post網(wǎng)絡(luò)請(qǐng)求,此類看需求由自己選擇寫與不寫
        protected void requestPostAPI(String url, Map params, MvpCallback<T> callback) {
            //這里寫具體的網(wǎng)絡(luò)請(qǐng)求
        }
    }
    
  • getNetData:實(shí)現(xiàn)具體的Model請(qǐng)求時(shí)必須要重寫B(tài)aseModel的抽象方法execute

    public class UserDataModel extends BaseModel<String> {
        @Override
        public void execute(final MvpCallback<String> callback) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    // mParams 是從父類得到的請(qǐng)求參數(shù)
                    switch (mParams[0]){
                        case "normal":
                            callback.onSuccess("根據(jù)參數(shù)"+mParams[0]+"的請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)成功");
                            break;
                        case "failure":
                            callback.onFailure("請(qǐng)求失斨枳:參數(shù)有誤");
                            break;
                        case "error":
                            callback.onError();
                            break;
                    }
                    callback.onComplete();
                }
            },2000);
        }
    }
    

效果圖

MVP效果圖

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绪杏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纽绍,更是在濱河造成了極大的恐慌蕾久,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拌夏,死亡現(xiàn)場(chǎng)離奇詭異僧著,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)障簿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門盹愚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人站故,你說(shuō)我怎么就攤上這事皆怕∫阌撸” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵愈腾,是天一觀的道長(zhǎng)憋活。 經(jīng)常有香客問(wèn)我,道長(zhǎng)虱黄,這世上最難降的妖魔是什么悦即? 我笑而不...
    開(kāi)封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮橱乱,結(jié)果婚禮上辜梳,老公的妹妹穿的比我還像新娘。我一直安慰自己泳叠,他們只是感情好冗美,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著析二,像睡著了一般粉洼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叶摄,一...
    開(kāi)封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天属韧,我揣著相機(jī)與錄音,去河邊找鬼蛤吓。 笑死宵喂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的会傲。 我是一名探鬼主播锅棕,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼淌山!你這毒婦竟也來(lái)了裸燎?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤泼疑,失蹤者是張志新(化名)和其女友劉穎德绿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體退渗,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡移稳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了会油。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片个粱。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖翻翩,靈堂內(nèi)的尸體忽然破棺而出都许,到底是詐尸還是另有隱情稻薇,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布梭稚,位于F島的核電站,受9級(jí)特大地震影響絮吵,放射性物質(zhì)發(fā)生泄漏弧烤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一蹬敲、第九天 我趴在偏房一處隱蔽的房頂上張望暇昂。 院中可真熱鬧,春花似錦伴嗡、人聲如沸急波。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)澄暮。三九已至,卻和暖如春阱扬,著一層夾襖步出監(jiān)牢的瞬間泣懊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工麻惶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留馍刮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓窃蹋,卻偏偏與公主長(zhǎng)得像卡啰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子警没,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355