Android MVP模式簡單使用和封裝使用

MVP+Retrofit2+RxJava2

本Demo使用MVP+Retrofit2+RxJava2來寫的,如果大家對Retrofit2+RxJava都不會使用進(jìn)行網(wǎng)絡(luò)請求的話,請先查看我之前寫的文章Retrofit2.0+RxJava2.0封裝使用引矩,因?yàn)槲疫@里面網(wǎng)絡(luò)請求是直接使用之前封裝好的粘舟,這里就不再介紹了凉驻。這里只介紹Android MVP的簡單使用和封裝使用贝淤。

Demo地址:https://github.com/pengjunshan/MVPRetrofitRxJava

其它文章

Retrofit2+RxJava2 封裝使用
OkHttp3簡單使用和封裝使用
Android開發(fā) 多語言系羞、指紋登錄郭计、手勢登錄
Android使用IconFont阿里矢量圖標(biāo)
Android Studio 使用SVN 主干和分支合并代碼

主要講解內(nèi)容
  • MVP封裝前簡單使用
  • MVP對Activity封裝使用
  • MVP對Frgment封裝使用
效果圖
MVP介紹

MVP全名Mode View Presenter,Presenter處理邏輯業(yè)務(wù)觉啊,Model提供數(shù)據(jù)拣宏,View更新展示界面。完全隔離界面顯示與業(yè)務(wù)邏輯杠人。

流程圖

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

  • 分離了視圖邏輯和業(yè)務(wù)邏輯勋乾,降低了耦合宋下。
  • 單一職責(zé), Model辑莫, View学歧, Presenter只處理單一邏輯。
  • Model層的修改和View層的修改互不影響各吨。
  • 視圖邏輯和業(yè)務(wù)邏輯分別抽象到了View和Presenter的接口中去枝笨,提高代碼的可閱讀性

缺點(diǎn):

  • 接口類過多,代碼量增加揭蜒。
  • Presenter和View相互持有引用横浑,解除不及時(shí)的話容易出現(xiàn)內(nèi)存泄漏。

說明:

  • 這里對MVP不做過多的解釋屉更,網(wǎng)上對MVP的解釋有一大堆基本說的都差不多徙融。
  • 下面我會講解怎么盡可能的減少代碼量,和避免內(nèi)存泄漏的方法瑰谜。
  • MVP并沒有一個(gè)統(tǒng)一標(biāo)準(zhǔn)模式欺冀,只要遵循View和Model相互分離就行。(按照自己喜歡的模式寫就行)

MVP簡單使用方法

用到的類

Concacts:契約類 將Model萨脑、View隐轩、Presenter 進(jìn)行約束管理,方便后期類的查找渤早、維護(hù)职车。
View:Activity 和Fragment 視為View層,負(fù)責(zé)處理 UI蛛芥。
Model:包含著具體的數(shù)據(jù)請求提鸟,數(shù)據(jù)源军援、本地存儲等等仅淑。
Presenter :為業(yè)務(wù)處理層,既能調(diào)用View邏輯胸哥,又能調(diào)用Model請求數(shù)據(jù)涯竟。

需要的類

EaseConcacts 類

契約類 將Model、View空厌、Presenter 進(jìn)行約束管理庐船。在各自的接口類中定義不同需求的方法。IView接口類中創(chuàng)建一個(gè)接收Data數(shù)據(jù)的回調(diào)方法嘲更;IPresenter接口類中定義一個(gè)IView觸發(fā)網(wǎng)絡(luò)請求的方法筐钟;IModel接口類中定義一個(gè)真正網(wǎng)絡(luò)請求的方法和一個(gè)回調(diào)給IPresenter類的回調(diào)方法;

public class EaseConcacts {

  interface IView {

    /**
     * View層獲取數(shù)據(jù)回調(diào)方法
     */
    void onResultData(String data);
  }

  interface IPresenter {

    /**
     * View層向Presenter發(fā)送請求方法
     */
    void requestData(Context context);
  }

  interface IModel {

    /**
     * Persenter層向Model發(fā)送請求方法
     */
    void getData(Context context, ModelListener modelListener);

    interface ModelListener {

      /**
       * Model層請求接口完成后回調(diào)Persenter層方法
       */
      void onReslutJson(String test);
    }
  }
}

EaseActivity類

IView類中實(shí)現(xiàn)Concacts中的IView接口赋朦,并且初始化Presenter,然后點(diǎn)擊按鈕觸發(fā)Presenter類中的requestData方法篓冲;requestData方法中會觸發(fā)IModel中真正網(wǎng)絡(luò)請求方法李破;然后IView類通過onResultData回調(diào)方法接收數(shù)據(jù);

public class EaseActivity extends AppCompatActivity implements IView {

  private EasePresenter presenter;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_ease);
    presenter = new EasePresenter(this);
    findViewById(R.id.getJSON).setOnClickListener((view) -> presenter.requestData(this));
  }

  @Override
  public void onResultData(String data) {
    Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
  }

}

EasePresenter類

首先要實(shí)現(xiàn)EaseConcacts契約類中的IPresenter接口壹将,并實(shí)現(xiàn)requestData方法,當(dāng)View調(diào)用requestData方法后Presenter會通過Mode進(jìn)行網(wǎng)絡(luò)請求,然后把結(jié)果回調(diào)過來。

public class EasePresenter implements EaseConcacts.IPresenter {

  private EaseConcacts.IView iView;
  private EaseModel iModle;

  public EasePresenter(EaseConcacts.IView view) {
    this.iView = view;
    this.iModle = new EaseModel();
  }

  @Override
  public void requestData(Context context) {
    iModle.getData(context, test -> iView.onResultData(test));
}

EaseModel類

首先要實(shí)現(xiàn)EaseConcacts契約類中IModel接口缰盏,這里寫網(wǎng)絡(luò)業(yè)務(wù)代碼负溪,網(wǎng)絡(luò)請求完成后可以在此可以處理數(shù)據(jù) 增刪改查须尚、本地存儲等等密幔;然后把數(shù)據(jù)通過接口返回給EasePresenter類堪嫂;

public class EaseModel implements EaseConcacts.IModel {

  @Override
  public void getData(Context context, ModelListener modelListener) {
    RetrofitClient.request(context, RetrofitClient.createApi().getJson(),
        new IResponseListener<BannerBean>() {
          @Override
          public void onSuccess(BannerBean data) {
            /**
             * 在此可以處理數(shù)據(jù) 增刪改查、本地存儲等等
             */
            Logout.e("data= "+data.toString());
            modelListener.onReslutJson(data.toString());
          }

          @Override
          public void onFail(OkHttpException failuer) {
            modelListener.onReslutJson("失敗= "+failuer.getEmsg());
          }
        });
  }

}

Model弱化

可以弱化Model的作用,把RetrofitClient網(wǎng)絡(luò)請求當(dāng)做Modle,可以省略Modle接口和類文件

public class EasePresenter implements EaseConcacts.IPresenter {

  private EaseConcacts.IView iView;
  private EaseModel iModle;

  public EasePresenter(EaseConcacts.IView view) {
    this.iView = view;
    this.iModle = new EaseModel();
  }

  @Override
  public void requestData(Context context) {

    /**
     * 方式一:調(diào)用Modle進(jìn)行調(diào)用接口
     */
    //iModle.getData(context, test -> iView.onResultData(test));

    /**
     * 方式二:弱化了Model的作用流纹,這里RetrofitClient網(wǎng)絡(luò)請求就是Modle,可以省略一個(gè)Modle文件
     */
    RetrofitClient.request(context, RetrofitClient.createApi().getJson(),
        new IResponseListener<BannerBean>() {
          @Override
          public void onSuccess(BannerBean data) {
            Logout.e("data= " + data.toString());
            iView.onResultData(data.toString());
          }

          @Override
          public void onFail(OkHttpException failuer) {
            iView.onResultData("失敗= " + failuer.getEmsg());
          }
        });
  }

}

封裝MVP使用

上面說過MVP缺點(diǎn),Presenter和View相互持有引用感论,解除不及時(shí)的話容易出現(xiàn)內(nèi)存泄漏囊陡。下面我們要創(chuàng)建一些Base類來處理一些公共的代碼邏輯和防止內(nèi)存泄漏。

創(chuàng)建Base類

BaseActivity:通過泛型接收View和Presenter,進(jìn)行V和P的綁定和解綁觸發(fā)倚聚。
BaseFragment:通過泛型接收View和Presenter枯跑,進(jìn)行V和P的綁定和解綁觸發(fā)屋确。
BasePresenter:動態(tài)判斷View是否已銷毀刨啸,防止內(nèi)存泄漏离例。
BaseView:為了處理公共View邏輯雕拼。比如在BaseView中寫公共處理UI方法、通過泛型對View進(jìn)行綁定和解綁粘招。


BaseView類

在BaseActivity啥寇、BaseFragment、BasePresenter中都要處理View的邏輯洒扎,都需要用泛型來接收View辑甜,所以所有的IView都要繼承BaseView。

public interface BaseView {
  //添加公共處理UI方法 比如處理接口失敗的UI

}

BasePresenter類

所有的Presenter類都要繼承BasePresenter袍冷,在Base里對View做了統(tǒng)一的綁定和解綁的代碼處理磷醋。還統(tǒng)一對View做了是否已解綁的判斷,防止調(diào)用View中的回調(diào)方法(防止內(nèi)存泄漏)胡诗。

public abstract class BasePresenter<V extends BaseView> {

  private V view;
  private V proxyView;

  public V getView() {
    return proxyView;
  }

  /**
   * 綁定view
   */
  public void attachView(V view) {
    this.view = view;
    //參數(shù)一:類加載器
    ClassLoader classLoader = view.getClass().getClassLoader();
    //參數(shù)二:代理接口
    Class<?>[] interfaces = view.getClass().getInterfaces();
    //參數(shù)三:方法回調(diào)
    BaseViewInvocationHandler handler = new BaseViewInvocationHandler(view);
    proxyView = (V) Proxy.newProxyInstance(classLoader, interfaces, handler);
  }

  /**
   * 解綁view
   */
  public void detachView() {
    this.view = null;
  }

  private class BaseViewInvocationHandler implements InvocationHandler {

    private BaseView view;

    BaseViewInvocationHandler(BaseView view) {
      this.view = view;
    }

    //統(tǒng)一判斷->控制對象訪問權(quán)限
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
      //檢查是不是為null
      if (isViewNull()) {
        //不用回調(diào)
        return null;
      }
      //執(zhí)行回調(diào)
      return method.invoke(view, objects);
    }
  }

  private boolean isViewNull() {
    if (view == null) {
      return true;
    }
    return false;
  }

}

BaseActivity類

通過泛型接收View和Presenter邓线,進(jìn)行V和P的綁定和解綁觸發(fā)。還有提供創(chuàng)建Presenter類的抽象方法煌恢,和獲取Presenter類的構(gòu)造方法骇陈。

public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V>> extends
    Activity implements BaseView {

  private P presenter;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (presenter == null) {
      presenter = createPresenter();
    }
    /**
     * 綁定view
     */
    if (presenter != null) {
      presenter.attachView((V) this);
    }

  }

  /**
   * 得到當(dāng)前的Presenter類
   */
  public P getPresenter() {
    return presenter;
  }

  /**
   * 創(chuàng)建Presenter類
   */
  public abstract P createPresenter();

  @Override
  protected void onDestroy() {
    super.onDestroy();
    /**
     * 解綁view
     */
    if (presenter != null) {
      presenter.detachView();
    }
  }
}

BaseFragment類

通過泛型接收View和Presenter,進(jìn)行V和P的綁定和解綁觸發(fā)瑰抵。還有提供創(chuàng)建Presenter類的抽象方法你雌,和獲取Presenter類的構(gòu)造方法。和BaseActivity處理方式是一樣的二汛。

public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V>> extends
    Fragment implements BaseView {

  private P presenter;

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (presenter == null) {
      presenter = createPresenter();
    }
    if (presenter != null) {
      presenter.attachView((V) this);
    }
  }

  public P getPresenter() {
    return presenter;
  }

  public abstract P createPresenter();

  @Override
  public void onDestroyView() {
    super.onDestroyView();
    if (presenter != null) {
      presenter.detachView();
    }
  }

}
Activity中使用
Activity使用

LoginConcacts契約類

來統(tǒng)一管理IView婿崭、IPresenter拨拓、IModel接口∶フ唬可以對Model進(jìn)行弱化渣磷,不僅少定義了IModel接口還可以少寫一個(gè)實(shí)現(xiàn)IModel接口類,從而減少了代碼量授瘦。

public class LoginConcacts {

  interface IView extends BaseView {

    /**
     * 校驗(yàn)賬號密碼錯(cuò)誤的提示信息
     */
    void showToast(String msg);

    /**
     * View中獲取接口信息的回調(diào)
     */
    void onResultData(String data);
  }

  interface IPresenter {

    /**
     * 校驗(yàn)賬號密碼
     */
    void checkData(String userName, String userPwd);

    /**
     * 請求數(shù)據(jù)
     */
    void requestData(String userName, String userPwd);
  }

  /**
   * Model可以弱化掉醋界,節(jié)省代碼量
   */
  interface IModel {

    void getData(Context context, String userName, String userPwd, ModelListener modelListener);

    interface ModelListener {

      void onReslutJson(String test);
    }
  }

}

LoginPresenter類

首先要繼承BasePresenter,通過泛型傳入LoginConcacts.IView奥务,再實(shí)現(xiàn)LoginConcacts.IPresenter接口類并實(shí)現(xiàn)里面的方法物独。在LoginPresenter里可以直接進(jìn)行網(wǎng)絡(luò)請求,把Retrofit網(wǎng)絡(luò)請求當(dāng)做Model(把Model弱化)氯葬,也可以調(diào)用LoginModel進(jìn)行網(wǎng)絡(luò)請求挡篓。

public class LoginPresenter extends BasePresenter<LoginConcacts.IView> implements
    LoginConcacts.IPresenter {

  private Context context;
  private LoginModel modle;

  public LoginPresenter(Context context) {
    this.context = context;
    this.modle = new LoginModel();
  }

  @Override
  public void checkData(String userName, String userPwd) {
    if (TextUtils.isEmpty(userName)) {
      getView().showToast("請輸入賬號!");
    } else if (TextUtils.isEmpty(userPwd)) {
      getView().showToast("請輸入密碼帚称!");
    } else {
      requestData(userName, userPwd);
    }
  }

  @Override
  public void requestData(String userName, String userPwd) {

    /**
     * 方式一:調(diào)用Modle進(jìn)行調(diào)用接口
     */
//    modle.getData(context,userName,userPwd, test -> getView().onResultData(test));

    /**
     * 方式二:把Modle弱引用掉官研,這里RetrofitClient網(wǎng)絡(luò)請求就是Modle,可以省略一個(gè)Modle文件
     */
    Map<String, String> map = new HashMap<>();
    map.put("username", userName);
    map.put("password", userPwd);

    RetrofitClient.request(context, RetrofitClient.createApi().postLogin(map),
        new IResponseListener<LoginBean>() {
          @Override
          public void onSuccess(LoginBean data) {
            Logout.e("data= " + data.toString());
            getView().onResultData(data.toString());
          }

          @Override
          public void onFail(OkHttpException failuer) {
            getView().onResultData("失敗= " + failuer.getEmsg());
          }
        });
  }
}

LoginModel類

首先要實(shí)現(xiàn)IModel接口類并實(shí)現(xiàn)方法闯睹,Model中不光是進(jìn)行網(wǎng)絡(luò)請求的戏羽,其它業(yè)務(wù)邏輯都可以處理。這里是進(jìn)行網(wǎng)絡(luò)請求楼吃,然后通過接口返回給Presenter始花。

public class LoginModel implements IModel {

  @Override
  public void getData(Context context, String userName, String userPwd,
      ModelListener modelListener) {
    Map<String, String> map = new HashMap<>();
    map.put("username", userName);
    map.put("password", userPwd);

    RetrofitClient.request(context, RetrofitClient.createApi().postLogin(map),
        new IResponseListener<LoginBean>() {
          @Override
          public void onSuccess(LoginBean data) {
            Logout.e("data= " + data.toString());
            modelListener.onReslutJson(data.toString());
          }

          @Override
          public void onFail(OkHttpException failuer) {
            modelListener.onReslutJson("失敗= " + failuer.getEmsg());
          }
        });
  }

}

LoginActivity類

LoginActivity就是View的實(shí)現(xiàn)類,首先要繼承BaseActivity類并通過泛型傳入View和Presenter孩锡。然后實(shí)現(xiàn)LoginConcacts.IView接口并實(shí)現(xiàn)其中的方法酷宵。

public class LoginActivity extends
    BaseActivity<LoginConcacts.IView, LoginPresenter> implements LoginConcacts.IView {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    findViewById(R.id.getJSON)
        .setOnClickListener((view) -> getPresenter().checkData("賬號", "密碼"));
  }

  @Override
  public LoginPresenter createPresenter() {
    return new LoginPresenter(this);
  }

  @Override
  public void showToast(String msg) {
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
  }

  @Override
  public void onResultData(String data) {
    Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
  }
}
Fragment中使用
Fragment使用

BannerConcacts類

來統(tǒng)一管理IView、IPresenter的接口躬窜,這里我對Model弱化掉了不再提供Model的實(shí)現(xiàn)類了浇垦。

public class BannerConcacts {

  interface IView extends BaseView {

    /**
     * 獲取接口數(shù)據(jù)回調(diào)方法
     */
    void onReslutData(String data);
  }

  interface IPresenter {

    /**
     * 進(jìn)行網(wǎng)絡(luò)業(yè)務(wù)處理
     */
    void requestData(Context context);
  }

}

BannerPresenter類

首先繼承BasePresenter類通過泛型傳入相應(yīng)的IView,然后再實(shí)現(xiàn)BannerConcacts.IPresenter接口并實(shí)現(xiàn)其中的方法荣挨。這里沒有調(diào)用Model來進(jìn)行業(yè)務(wù)處理男韧,對Model弱化了

public class BannerPresenter extends BasePresenter<BannerConcacts.IView> implements
    BannerConcacts.IPresenter {

  @Override
  public void requestData(Context context) {

    RetrofitClient.request(context, RetrofitClient.createApi().getJson(),
        new IResponseListener<BannerBean>() {
          @Override
          public void onSuccess(BannerBean data) {
            Logout.e("Tag", "data= " + data.toString());
            getView().onReslutData(data.toString());
          }

          @Override
          public void onFail(OkHttpException failuer) {
            getView().onReslutData("失敗= " + failuer.getEmsg());
          }
        });
  }
}

BannerFragment類

BannerFragment就是View的實(shí)現(xiàn)類,首先要繼承BaseFragment類并通過泛型傳入View和Presenter默垄。然后實(shí)現(xiàn)BannerConcacts.IView接口并實(shí)現(xiàn)其中的方法此虑。使用方式和Activity一樣。

public class BannerFragment extends BaseFragment<BannerConcacts.IView, BannerPresenter> implements
    BannerConcacts.IView {

  @Nullable
  @Override
  public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
      @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.banner, null);
  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    view.findViewById(R.id.getJSON)
        .setOnClickListener((v) -> getPresenter().requestData(getContext()));
  }

  @Override
  public BannerPresenter createPresenter() {
    return new BannerPresenter();
  }

  @Override
  public void onReslutData(String data) {
    Toast.makeText(getContext(), data, Toast.LENGTH_SHORT).show();
  }

}
我對MVP的理解

有些人說MVP適合大型項(xiàng)目厕倍,我不這么認(rèn)為寡壮。之前我做過某網(wǎng)的項(xiàng)目使用MVC模式,有些Activity代碼行能達(dá)到兩千多行代碼讹弯,查找問題很麻煩况既。我說下我的看法,我認(rèn)為View層業(yè)務(wù)邏輯比較多的話就適合MVP模式组民,業(yè)務(wù)邏輯比較少的話看個(gè)人你可以用MVP也可以用MVC棒仍。還有就是封裝一個(gè)適合自己項(xiàng)目的框架。

Demo地址:https://github.com/pengjunshan/MVPRetrofitRxJava

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末臭胜,一起剝皮案震驚了整個(gè)濱河市莫其,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耸三,老刑警劉巖乱陡,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仪壮,居然都是意外死亡憨颠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門积锅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爽彤,“玉大人,你說我怎么就攤上這事缚陷∈矢荩” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵箫爷,是天一觀的道長嚷节。 經(jīng)常有香客問我,道長虎锚,這世上最難降的妖魔是什么硫痰? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮翁都,結(jié)果婚禮上碍论,老公的妹妹穿的比我還像新娘。我一直安慰自己柄慰,他們只是感情好鳍悠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坐搔,像睡著了一般藏研。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上概行,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天蠢挡,我揣著相機(jī)與錄音,去河邊找鬼。 笑死业踏,一個(gè)胖子當(dāng)著我的面吹牛禽炬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勤家,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼腹尖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伐脖?” 一聲冷哼從身側(cè)響起热幔,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎讼庇,沒想到半個(gè)月后绎巨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蠕啄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年场勤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片介汹。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡却嗡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嘹承,到底是詐尸還是另有隱情窗价,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布叹卷,位于F島的核電站撼港,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏骤竹。R本人自食惡果不足惜帝牡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蒙揣。 院中可真熱鬧靶溜,春花似錦、人聲如沸懒震。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽个扰。三九已至瓷炮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間递宅,已是汗流浹背娘香。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工苍狰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烘绽。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓淋昭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親诀姚。 傳聞我的和親對象是個(gè)殘疾皇子响牛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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