9. Flutte3.0遙遙領(lǐng)先系列|一文教你完全掌握getX, 手寫getX框架

目錄:
1.優(yōu)點(diǎn)
2.優(yōu)點(diǎn)分析: GetX怎么將邏輯層和界面層解耦的
3.優(yōu)點(diǎn)分析: GetX怎么實(shí)現(xiàn)狀態(tài)管理的? Obx的基本原理是什么献幔? 局部刷新原理? obx和obs?
4.優(yōu)點(diǎn)分析: binding基本原理是什么操刀?
5.優(yōu)點(diǎn)分析: 路由管理基本原理是什么?
6.getx的缺點(diǎn)是啥?
7.手寫getX

1. GetX相關(guān)優(yōu)勢(shì)

1.1 )依賴注入

GetX是通過(guò)依賴注入的方式,存儲(chǔ)相應(yīng)的XxxGetxController似扔;已經(jīng)脫離了InheritedWidget那一套玩法酿愧,自己手動(dòng)去管理這些實(shí)例屯换,使用場(chǎng)景被大大拓展
簡(jiǎn)單的思路驻仅,卻能產(chǎn)生深遠(yuǎn)的影響:優(yōu)雅的跨頁(yè)面功能便是基于這種設(shè)計(jì)而實(shí)現(xiàn)的、獲取實(shí)例無(wú)需BuildContext摆舟、GetBuilder自動(dòng)化的處理及其減少了入?yún)⒌鹊?/p>

1.2 )跨頁(yè)面交互的狀態(tài)管理

這絕對(duì)是GetX的一個(gè)優(yōu)點(diǎn)亥曹!對(duì)于復(fù)雜的生產(chǎn)環(huán)境,跨頁(yè)面交互的場(chǎng)景恨诱,實(shí)在太常見(jiàn)了媳瞪,GetX的跨頁(yè)面交互,實(shí)現(xiàn)的也較為優(yōu)雅

1.3 )路由管理

getx內(nèi)部實(shí)現(xiàn)了路由管理照宝,而且用起來(lái)蛇受,非常簡(jiǎn)單!bloc沒(méi)實(shí)現(xiàn)路由管理厕鹃,我不得不找一個(gè)star量高的路由框架兢仰,就選擇了fluro乍丈,但是不得不吐槽下,fluro用起來(lái)真的很折磨人把将,每次新建一個(gè)頁(yè)面轻专,最讓我抗拒的就是去寫fluro路由代碼,橫跨幾個(gè)文件來(lái)回寫秸弛,頭皮發(fā)麻
GetX實(shí)現(xiàn)了動(dòng)態(tài)路由傳參,也就是說(shuō)直接在命名路由上拼參數(shù)洪碳,然后能拿到這些拼在路由上的參數(shù)递览,也就是說(shuō)用flutter寫H5,直接能通過(guò)Url傳值瞳腌,OMG绞铃!可以無(wú)腦舍棄復(fù)雜的fluro了

1.4 ) 實(shí)現(xiàn)了全局BuildContext
1.5 )國(guó)際化,主題實(shí)現(xiàn)
生命周期

用了Getx的state管理之后, 你再也用不著StatefulWidget了. 僅僅StatelessWidget就夠你用了! 性能自然也提升很多!

2. GetX怎么將邏輯層和界面層解耦的

此處需要?jiǎng)澐秩齻€(gè)結(jié)構(gòu)了:state(狀態(tài)層)嫂侍,logic(邏輯層)儿捧,view(界面層)

為什么寫成這樣三個(gè)模塊,需要把State單獨(dú)提出來(lái)挑宠,為了復(fù)雜的業(yè)務(wù), 顯的更簡(jiǎn)單!

舉例:

之前的寫法

class IdentificationCard extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return IdentificationState();
  }
}

class IdentificationState extends State<IdentificationCard> {
  String date = "555";
  String name = "666";

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
                Text('date : $date'),
                Text('name : $name'), 
                GestureDetector(onTap: () {
                  setState(() {
                    date = "777";
                  });
                }, child: const Text('修改'))],
    );
  }
}

用getx的實(shí)現(xiàn)
新建一個(gè)類, 定義一個(gè)狀態(tài), GetxController
添加一個(gè)Obx就能自動(dòng)監(jiān)聽(tīng)狀態(tài)的改變并且刷新UI了

/// 狀態(tài)
class IdentificationState {
  RxString date = "555".obs;
  RxString name = "666".obs;
}

/// 業(yè)務(wù)邏輯
class IdentificationController extends GetxController {
  IdentificationState state = IdentificationState();
}

/// 展示
class IdentificationCard extends StatelessWidget {
  IdentificationController controller = Get.put(IdentificationController());

  @override
  Widget build(BuildContext context) {
    return Obx(() {
      return Column(
        children: [
          Text('date : ${controller.state.date}'),
          Text('name : ${controller.state.name}'),
          GestureDetector(
              onTap: () {
                controller.state.date.value = "777";
              },
              child: const Text('修改'))
        ],
      );
    });
  }
}

3.GetX實(shí)現(xiàn)狀態(tài)管理

GetX 的刷新方案分為手動(dòng)刷新與自動(dòng)刷新菲盾,GetBuilder 與 Obx ,分別對(duì)應(yīng)范圍刷新與局部刷新

2者的區(qū)別:

Obx 響應(yīng)式狀態(tài)管理

Obx 可以配合響應(yīng)式字段局部的精準(zhǔn)刷新避免父容器無(wú)效重構(gòu)各淀,缺點(diǎn)是字段變?yōu)轫憫?yīng)式的Rx包裝類懒鉴,布局也需要被Obx包裹了,破壞了原生代碼觀賞性碎浇。

GetBuilder 狀態(tài)管理器

GetBuilder 就是指定區(qū)域范圍手動(dòng)去刷新的临谱,可以分區(qū)設(shè)置多個(gè)刷新區(qū)域,可選擇單個(gè)控件或容器奴璃,在一些特定場(chǎng)景下有奇效悉默,但是如果不理解濫用一樣會(huì)導(dǎo)致性能問(wèn)題。

3.1 Obx 的基本原理是什么苟穆?

Obx是配合Rx響應(yīng)式變量使用
這樣一來(lái)我們就明白了Obx實(shí)際上是一個(gè)StatefulWidget抄课,它里面監(jiān)聽(tīng)了一個(gè)GetStream,一旦GetStream有事件通知雳旅,它就會(huì)進(jìn)行setState重新進(jìn)行Widget的構(gòu)造.
GetBuilder 與 Obx 兩者結(jié)合剖膳,一個(gè)指定區(qū)域范圍手動(dòng)刷新,一個(gè)是局部控件點(diǎn)對(duì)點(diǎn)刷新

var build = () => Text(name.value)

Obx(build);

源碼: Obx繼承了一個(gè)抽象ObxWidget類岭辣,將傳遞進(jìn)來(lái)的build方法給了ObxWidget

class Obx extends ObxWidget {
  final WidgetCallback builder;

  const Obx(this.builder);

  @override
  Widget build() => builder();
}

ObxWidget繼承了有狀態(tài)組件吱晒,并且build函數(shù)讓Obx類實(shí)現(xiàn)了

abstract class ObxWidget extends StatefulWidget {
  const ObxWidget({Key? key}) : super(key: key);

  @override
  _ObxState createState() => _ObxState();

  @protected
  Widget build();
}
對(duì)GexX的狀態(tài)管理做一個(gè)簡(jiǎn)單總結(jié),

基于Obx收集依賴狀態(tài), 實(shí)際一個(gè)StatefulWidget沦童,它的State也就是ObxState中監(jiān)聽(tīng)了GetStream事件流仑濒,通過(guò)接收GetStream事件流調(diào)用setState重新構(gòu)建Obx叹话,Rx對(duì)象在改變value的時(shí)候會(huì)向GetStream事件流發(fā)送事件,這樣就會(huì)導(dǎo)致Obx進(jìn)行刷新了.

Rx原理.jpg
3.2 GetBuilder

GetBuilder 是一個(gè) Widget 組件墩瞳, 在 GetX 的狀態(tài)管理中驼壶,GetBuilder 的主要作用是結(jié)合 GetxController 實(shí)現(xiàn)界面數(shù)據(jù)的更新
demo使用

class CounterBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => CounterController());
  }
}


class CounterController extends GetxController {
  int count = 0;
  
  void increase(){
    count += 1;
    update();
  }
}

class CounterPage extends StatelessWidget {

  final controller = Get.find<CounterController>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Counter"),
      ),
      body: Center(
        child: GetBuilder<CounterController>(builder: (logic) {
          return Text("${controller.count}", style: const TextStyle(fontSize: 50),);
        }),
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: controller.increase,
      ),
    );
  }
}

demo調(diào)用總結(jié): 然后調(diào)用 update 方法更新界面數(shù)據(jù),從而實(shí)現(xiàn)計(jì)數(shù)器的功能喉酌。
狀態(tài)管理源碼分析:

class GetBuilder<T extends GetxController> extends StatefulWidget {
  final GetControllerBuilder<T> builder;
  final bool global;
  final Object? id;
  final String? tag;
  final bool autoRemove;
  final bool assignId;
  final Object Function(T value)? filter;
  final void Function(GetBuilderState<T> state)? initState,
      dispose,
      didChangeDependencies;
  final void Function(GetBuilder oldWidget, GetBuilderState<T> state)?
      didUpdateWidget;
  final T? init;

  const GetBuilder({
    Key? key,
    this.init,
    this.global = true,
    required this.builder,
    this.autoRemove = true,
    this.assignId = false,
    this.initState,
    this.filter,
    this.tag,
    this.dispose,
    this.id,
    this.didChangeDependencies,
    this.didUpdateWidget,
  }) : super(key: key);

  @override
  GetBuilderState<T> createState() => GetBuilderState<T>();
}

GetBuilder 是繼承自 StatefulWidget

GetBuilder 就是指定區(qū)域范圍手動(dòng)去刷新的热凹,可以分區(qū)設(shè)置多個(gè)刷新區(qū)域,可選擇單個(gè)控件或容器泪电,在一些特定場(chǎng)景下有奇效般妙,但是如果不理解濫用一樣會(huì)導(dǎo)致性能問(wèn)題。

GetBuilderState

class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>>
    with GetStateUpdaterMixin {
  T? controller;
  bool? _isCreator = false;
  VoidCallback? _remove;
  Object? _filter;

  @override
  void initState() {...}

  void _subscribeToController() {...}

  void _filterUpdate() {...}

  @override
  void dispose() {...}

  @override
  void didChangeDependencies() {...}

  @override
  void didUpdateWidget(GetBuilder oldWidget) {...}

  @override
  Widget build(BuildContext context) {...}
}

方法: build()

@override
Widget build(BuildContext context) {
  return widget.builder(controller!);
}
getbuild.jpg

通過(guò)對(duì) GetBuilder 的源碼分析相速,基本了解了 GetBuilder 各個(gè)參數(shù)的作用和實(shí)現(xiàn)原理碟渺。

GetBuilder 參數(shù)作用總結(jié)如下:

builder: Widget 構(gòu)建器,創(chuàng)建界面顯示的 Widget
init: 初始化 Controller 值突诬,當(dāng) global 為 false 時(shí)使用該值作為 Controller苫拍,當(dāng) global 為 true 時(shí)且 Controller 未注冊(cè)依賴,則將 init 的值注入依賴使用旺隙。
global: 是否全局绒极,作用于 Controller 初始化中,與 init 結(jié)合使用
autoRemove: 是否自動(dòng)移除 Controller 依賴蔬捷,結(jié)合 assignId 一起使用
assignId: 為 true 時(shí)結(jié)合 autoRemove 使用會(huì)自動(dòng)移除 Controller 依賴關(guān)系
filter: 過(guò)濾器集峦,通過(guò)返回值過(guò)濾是否需要刷新,返回值變化時(shí)才會(huì)刷新界面
tag: Controller 依賴注入的 tag抠刺,根據(jù) tag 獲取 Controller 實(shí)例
id: 刷新標(biāo)識(shí)塔淤,結(jié)合 Controller 的 update 使用,可以刷新指定 GetBuilder 控件內(nèi)的 Widget
initState: 回調(diào)函數(shù)速妖,生命周期 initState 方法中調(diào)用
dispose: 回調(diào)函數(shù)高蜂,生命周期 dispose 中調(diào)用
didUpdateWidget: 回調(diào)函數(shù),生命周期 didUpdateWidget 中調(diào)用
didChangeDependencies: 回調(diào)函數(shù)罕容,生命周期 didChangeDependencies 中調(diào)用

4. 依賴管理: Binding:

依賴注入: 就是賦值, 但是很多類給你的類賦值, 這樣就很亂了
Binding的使用: 一般和controller在一起使用
binding模塊需要在getx路由頁(yè)面進(jìn)行綁定备恤;進(jìn)入頁(yè)面的時(shí)候,統(tǒng)一懶注入binding模塊的GetXController

依賴注入.jpg
class _GetImpl extends GetInterface {}

final Get = _GetImpl();

extension Inst on GetInterface {
  S put<S>(S dependency,
          {String? tag,
          bool permanent = false,
          InstanceBuilderCallback<S>? builder}) =>
      GetInstance().put<S>(dependency, tag: tag, permanent: permanent);
}
class GetInstance {
  factory GetInstance() => _getInstance ??= GetInstance._();

  const GetInstance._();

  static GetInstance? _getInstance;

  static final Map<String, _InstanceBuilderFactory> _singl = {};

  S put<S>(
    S dependency, {
    String? tag,
    bool permanent = false,
    @deprecated InstanceBuilderCallback<S>? builder,
  }) {
    _insert(
        isSingleton: true,
        name: tag,
        permanent: permanent,
        builder: builder ?? (() => dependency));
    return find<S>(tag: tag);
  }

  void _insert<S>({
    bool? isSingleton,
    String? name,
    bool permanent = false,
    required InstanceBuilderCallback<S> builder,
    bool fenix = false,
  }) {
    final key = _getKey(S, name);
    _singl.putIfAbsent(
      key,
      () => _InstanceBuilderFactory<S>(
        isSingleton,
        builder,
        permanent,
        false,
        fenix,
        name,
      ),
    );
  }

  String _getKey(Type type, String? name) {
    return name == null ? type.toString() : type.toString() + name;
  }

  S find<S>({String? tag}) {
    final key = _getKey(S, tag);
    if (isRegistered<S>(tag: tag)) {
      if (_singl[key] == null) {
        if (tag == null) {
          throw 'Class "$S" is not registered';
        } else {
          throw 'Class "$S" with tag "$tag" is not registered';
        }
      }
      final i = _initDependencies<S>(name: tag);
      return i ?? _singl[key]!.getDependency() as S;
    } else {
      // ignore: lines_longer_than_80_chars
      throw '"$S" not found. You need to call "Get.put($S())" or "Get.lazyPut(()=>$S())"';
    }
  }
}

5. 路由管理之命名路由

特點(diǎn):封裝了context, 封裝了攔截器!
路由管理之簡(jiǎn)單路由

GetMaterialApp(
    unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
    routingCallback: (routing) {
      if(routing?.current == '/second'){
       ///處理一些業(yè)務(wù)
      }
    },
    initialRoute: '/',
    getPages: [
      GetPage(name: '/first', page: ()=>First()),
      GetPage(name: '/second', page: ()=>Second())
    ],
  )
路由管理.jpg
問(wèn)題: 為何不用Flutter自己的Router系統(tǒng)?

使用時(shí)還需要有一個(gè)context實(shí)例. 但我們并不是隨時(shí)隨地都持有一個(gè)context的, 這也局限了我們的使用場(chǎng)景.

6. GETX的缺點(diǎn):

第一個(gè)缺點(diǎn)

Get.to(widgetObj, bindings)是可以注入binding.

但是Get.toNamed()并不支持binding參數(shù)啊. 我的跳轉(zhuǎn)一般都是用toNamed的, 所以注定了這種方式我用不了.

第二個(gè)缺點(diǎn)

這個(gè)缺點(diǎn)很隱藏, 很容易出問(wèn)題. 以上面的binding為例

HomeBinding中提供了 HomeController, Service 兩個(gè)對(duì)象
DetailsBinding中提供了 DetailsController 對(duì)象 但其實(shí)我們的Details頁(yè)中也會(huì)用到Service對(duì)象.
之所以不出現(xiàn)"details頁(yè)中說(shuō)找不到Service"的crash, 是因?yàn)橛脩粝却蜷_(kāi)的home頁(yè), Home已經(jīng)往Get中寫入了Service對(duì)象了, 所以等之后打開(kāi)detail頁(yè)時(shí), serivce對(duì)象已經(jīng)有了, 能夠Get.find()得到, 所以不會(huì)有NPE錯(cuò)誤.

但要是deep link的場(chǎng)景呢?

: 你直接跳到了Detail頁(yè), 結(jié)果就因?yàn)闆](méi)有經(jīng)過(guò)home頁(yè), 所以Service service = Get.find()找不到service對(duì)象, 應(yīng)用會(huì)crash.

所以現(xiàn)在就明白了, 第二個(gè)缺點(diǎn)就是: 上面兩個(gè)Binding有隱藏的依賴性 DetailsBinding其實(shí)依賴于HomeBinding. HomeBinding不先放好service, 那DetailsBinding提供不了Serivce, 就可能會(huì)讓Detail頁(yè)crash.

第三個(gè)缺點(diǎn): obs會(huì)頻繁刷新锦秒;

7. 手寫getX

3大核心功能
7.1 依賴注入

///依賴注入露泊,外部可將實(shí)例,注入該類中旅择,由該類管理
class Easy {
  ///注入實(shí)例
  static T put<T>(T dependency, {String? tag}) =>
      _EasyInstance().put(dependency, tag: tag);

  ///獲取注入的實(shí)例
  static T find<T>({String? tag, String? key}) =>
      _EasyInstance().find<T>(tag: tag, key: key);

  ///刪除實(shí)例
  static bool delete<T>({String? tag, String? key}) =>
      _EasyInstance().delete<T>(tag: tag, key: key);
}

///具體邏輯
class _EasyInstance {
  factory _EasyInstance() => _instance ??= _EasyInstance._();

  static _EasyInstance? _instance;

  _EasyInstance._();

  static final Map<String, _InstanceInfo> _single = {};

  ///注入實(shí)例
  T put<T>(T dependency, {String? tag}) {
    final key = _getKey(T, tag);
    //只保存第一次注入:針對(duì)自動(dòng)刷新機(jī)制優(yōu)化惭笑,每次熱重載的時(shí)候,數(shù)據(jù)不會(huì)重置
    _single.putIfAbsent(key, () => _InstanceInfo<T>(dependency));
    return find<T>(tag: tag);
  }

  ///獲取注入的實(shí)例
  T find<T>({String? tag, String? key}) {
    final newKey = key ?? _getKey(T, tag);
    var info = _single[newKey];

    if (info?.value != null) {
      return info!.value;
    } else {
      throw '"$T" not found. You need to call "Easy.put($T())""';
    }
  }

  ///刪除實(shí)例
  bool delete<T>({String? tag, String? key}) {
    final newKey = key ?? _getKey(T, tag);
    if (!_single.containsKey(newKey)) {
      print('Instance "$newKey" already removed.');
      return false;
    }

    _single.remove(newKey);
    print('Instance "$newKey" deleted.');
    return true;
  }

  String _getKey(Type type, String? name) {
    return name == null ? type.toString() : type.toString() + name;
  }
}

class _InstanceInfo<T> {
  _InstanceInfo(this.value);

  T value;
}

7.2 狀態(tài)管理

///自定義個(gè)監(jiān)聽(tīng)觸發(fā)類
class EasyXNotifier {
  List<VoidCallback> _listeners = [];

  void addListener(VoidCallback listener) {
    _listeners.add(listener);
  }

  void removeListener(VoidCallback listener) {
    for (final entry in _listeners) {
      if (entry == listener) {
        _listeners.remove(entry);
        return;
      }
    }
  }

  void dispose() {
    _listeners.clear();
  }

  void notify() {
    if (_listeners.isEmpty) return;

    for (final entry in _listeners) {
      try {
        entry.call();
      } catch (e) {
        print(e.toString());
      }
    }
  }
}

7.3 路由管理

///刷新控件,自帶回收機(jī)制
class EasyBuilder<T extends EasyXController> extends StatefulWidget {
  final Widget Function(T logic) builder;

  final String? tag;
  final bool autoRemove;

  const EasyBuilder({
    Key? key,
    required this.builder,
    this.autoRemove = true,
    this.tag,
  }) : super(key: key);

  @override
  _EasyBuilderState<T> createState() => _EasyBuilderState<T>();
}

class _EasyBuilderState<T extends EasyXController>
    extends State<EasyBuilder<T>> {
  late T controller;

  @override
  void initState() {
    super.initState();

    controller = Easy.find<T>(tag: widget.tag);
    controller.xNotifier.addListener(() {
      if (mounted) setState(() {});
    });
  }

  @override
  void dispose() {
    if (widget.autoRemove) {
      Easy.delete<T>(tag: widget.tag);
    }
    controller.xNotifier.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(controller);
  }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市沉噩,隨后出現(xiàn)的幾起案子捺宗,更是在濱河造成了極大的恐慌,老刑警劉巖川蒙,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚜厉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡畜眨,警方通過(guò)查閱死者的電腦和手機(jī)昼牛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)康聂,“玉大人贰健,你說(shuō)我怎么就攤上這事≡缈伲” “怎么了霎烙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵撬讽,是天一觀的道長(zhǎng)蕊连。 經(jīng)常有香客問(wèn)我,道長(zhǎng)游昼,這世上最難降的妖魔是什么甘苍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮烘豌,結(jié)果婚禮上载庭,老公的妹妹穿的比我還像新娘。我一直安慰自己廊佩,他們只是感情好囚聚,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著标锄,像睡著了一般顽铸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上料皇,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天谓松,我揣著相機(jī)與錄音,去河邊找鬼践剂。 笑死鬼譬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的逊脯。 我是一名探鬼主播优质,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了盆赤?” 一聲冷哼從身側(cè)響起贾富,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牺六,沒(méi)想到半個(gè)月后颤枪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡淑际,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年畏纲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片春缕。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盗胀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锄贼,到底是詐尸還是另有隱情票灰,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布宅荤,位于F島的核電站屑迂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏冯键。R本人自食惡果不足惜惹盼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惫确。 院中可真熱鬧手报,春花似錦、人聲如沸改化。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)陈肛。三九已至揍鸟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間燥爷,已是汗流浹背蜈亩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留前翎,地道東北人稚配。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像港华,于是被迫代替她去往敵國(guó)和親道川。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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