重構(gòu)如何改善Flutter應(yīng)用程序的可讀性、可維護(hù)性以及提升性能

原文地址:How refactoring improve readability, maintainability and performance optimization of your Flutter application
原作者:Jonathan Monga
讀后感:
這篇文章是關(guān)于如何組織代碼結(jié)構(gòu)的,如何編寫Flutter代碼,才能使代碼有更好的可讀性、可維護(hù)性,并且?guī)砀玫男阅軈龋耙卜g過一篇相似的文章Flutter Widget瘦身,兩篇文章看完,想必會(huì)給你帶一些收益。

前言

我們都同意widget 樹是你在UI中所獲得的東西,并且同意它完全是關(guān)于Flutter widget的,因此你可以將你的widget相互嵌套。無論你的UI是簡單還是復(fù)雜,當(dāng)你的UI簡單時(shí),即使幾周后回來閱讀你的代碼,它也很容易閱讀,并且性能很好,因?yàn)樗故镜膬?nèi)容很少。但是當(dāng)你的應(yīng)用界面比較復(fù)雜時(shí),這會(huì)促使你嵌套大量的widget,代碼的可讀性、可維護(hù)性降低,程序的效率也會(huì)降低。

我知道,對(duì)于初學(xué)者來說,很容易沒有重構(gòu)代碼的文化,一旦注意力轉(zhuǎn)移到其他事情上,初學(xué)者就會(huì)滿足于widget的嵌套、嵌套、嵌套,這就是產(chǎn)生很深的widget樹的原因。對(duì)于像我這樣的新手Flutter開發(fā)者來說,這是很常見的現(xiàn)象,好吧,既然問題已經(jīng)暴露出來了,我們?cè)趺幢苊猓咳绾我砸环N不陷入非常深的widget樹的方式進(jìn)行編碼吶?

在我之前已經(jīng)有不少人探討過這個(gè)問題了,但我認(rèn)為還是值得在花點(diǎn)時(shí)間再談?wù)撘幌隆_@個(gè)經(jīng)常困擾我們的問題的答案就是代碼重構(gòu)。既然你已經(jīng)得到了答案,那么就不要再拖延重構(gòu)你的代碼啦。下面我將用不同的技術(shù),向你展示如何進(jìn)行代碼重構(gòu)。

在向你展示如何重構(gòu)代碼之前,讓我們使用此UI的代碼:


Weather Stats.png

這個(gè)很漂亮的UI來自于https://github.com/JideGuru/weather_neumorphism_ui,這里并沒有惡意,我不認(rèn)為我比Olusegun Festus Babajide更厲害,以至于我有權(quán)利對(duì)他的代碼做點(diǎn)評(píng)。同樣你如果找到一些我的代碼,我相信,你也會(huì)發(fā)現(xiàn)很多值得抱怨的地方。

不,這不是下流或者傲慢的行為,我將要做的無非只是專業(yè)的評(píng)論,這是我們都應(yīng)該樂于做的事情,當(dāng)完成時(shí),我們應(yīng)該歡迎它。通過這樣發(fā)表評(píng)論,可以促使我們學(xué)習(xí),醫(yī)生這樣做、飛行員這樣做、律師這樣做,我們程序員也應(yīng)該學(xué)習(xí)這樣做。補(bǔ)充一點(diǎn):Olusegun Festus Babajide不僅是一位很好的Flutter開發(fā)人員,并且有勇氣和善意,愿意將他的代碼免費(fèi)提供給整個(gè)社區(qū),他把它提供給所有人看,并邀請(qǐng)公眾使用和監(jiān)督,這樣做很贊。

這是現(xiàn)在的代碼:


class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
              height: 40,
              width: 40,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(10),
                color: Theme.of(context).primaryColor,
                boxShadow: [
                  BoxShadow(
                    offset: Offset(3, 3),
                    color: Colors.black12,
                    blurRadius: 5,
                  ),
                  BoxShadow(
                    offset: Offset(-3, -3),
                    color: Colors.white,
                    blurRadius: 5,
                  )
                ],
              ),
              child: Icon(
                Icons.arrow_back_ios,
                size: 14,
              ),
            ),
          ],
        ),
        centerTitle: true,
        elevation: 0,
        title: Text(
          "${Constants.appName}",
          style: TextStyle(
            fontSize: 25,
            fontWeight: FontWeight.w900,
          ),
        ),
      ),
      body: ListView(
        padding: EdgeInsets.symmetric(horizontal: 20),
        children: <Widget>[
          Container(
            height: 100,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Container(
                  height: 70,
                  width: MediaQuery.of(context).size.width,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    color: Theme.of(context).primaryColor,
                    boxShadow: [
                      BoxShadow(
                        offset: Offset(3, 3),
                        color: Colors.black12,
                        blurRadius: 5,
                      ),
                      BoxShadow(
                        offset: Offset(-3, -3),
                        color: Colors.white,
                        blurRadius: 5,
                      )
                    ],
                  ),
                  child: Padding(
                    padding: EdgeInsets.symmetric(horizontal: 20),
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        Row(
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[
                            Text(
                              "Period",
                              style: TextStyle(
                                fontWeight: FontWeight.bold,
                                color: Theme.of(context).textTheme.caption.color,
                              ),
                            ),

                            SizedBox(width: 30,),
                            Text(
                              "Last 30 days",
                              style: TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: 16,
                              ),
                            ),
                          ],
                        ),

                        Container(
                          height: 40,
                          width: 40,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                            color: Theme.of(context).primaryColor,
                            boxShadow: [
                              BoxShadow(
                                offset: Offset(3, 3),
                                color: Colors.black12,
                                blurRadius: 5,
                              ),
                              BoxShadow(
                                offset: Offset(-3, -3),
                                color: Colors.white,
                                blurRadius: 5,
                              )
                            ],
                          ),
                          child: Icon(
                            Icons.arrow_forward_ios,
                            size: 14,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),

          SizedBox(height: 20,),

          Container(
            height: 300,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Container(
                  height: 280,
                  width: MediaQuery.of(context).size.width,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    color: Theme.of(context).primaryColor,
                    boxShadow: [
                      BoxShadow(
                        offset: Offset(6, 6),
                        color: Colors.black12,
                        blurRadius: 5,
                      ),
                      BoxShadow(
                        offset: Offset(-6, -6),
                        color: Colors.white,
                        blurRadius: 5,
                      )
                    ],
                  ),
                  child: Stack(
                    children: <Widget>[
                      Align(
                        alignment: Alignment.center,
                        child: Icon(
                          Feather.loader,
                          size: 250,
                          color: Theme.of(context).accentColor,
                        ),
                      ),
                      Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: <Widget>[
                          Container(
                            height: 200,
                            width: MediaQuery.of(context).size.width,
                            decoration: BoxDecoration(
                              shape: BoxShape.circle,
                              color: Theme.of(context).primaryColor,
                              boxShadow: [
                                BoxShadow(
                                  offset: Offset(3, 3),
                                  color: Colors.black12,
                                  blurRadius: 5,
                                ),
                                BoxShadow(
                                  offset: Offset(-3, -3),
                                  color: Colors.white,
                                  blurRadius: 5,
                                )
                              ],
                            ),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              crossAxisAlignment: CrossAxisAlignment.center,
                              children: <Widget>[
                                Icon(
                                  Feather.thermometer,
                                  color: Theme.of(context).accentColor,
                                  size: 40,
                                ),
                                SizedBox(height: 20,),
                                Text(
                                  "7°C",
                                  style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    fontSize: 22,
                                    color: Theme.of(context).accentColor,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),

          SizedBox(height: 20,),

          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Container(
                height: 150,
                width: 130,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(10),
                  color: Theme.of(context).primaryColor,
                  boxShadow: [
                    BoxShadow(
                      offset: Offset(3, 3),
                      color: Colors.black12,
                      blurRadius: 5,
                    ),
                    BoxShadow(
                      offset: Offset(-3, -3),
                      color: Colors.white,
                      blurRadius: 5,
                    ),
                  ],
                ),
                child: Padding(
                  padding: EdgeInsets.all(15),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Icon(
                        Feather.cloud_snow,
                        size: 40,
                        color: Theme.of(context).accentColor,
                      ),

                      Text(
                        "Cool",
                        style: TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: 22,
                        ),
                      ),
                    ],
                  ),
                ),
              ),

              Neumorphic(
                height: 150,
                width: 130,
                status: NeumorphicStatus.convex,
                decoration: NeumorphicDecoration(
                  borderRadius: BorderRadius.circular(10),
                ),
                child: Padding(
                  padding: EdgeInsets.all(15),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Icon(
                        Feather.sun,
                        size: 40,
                        color: Colors.deepOrange,
                      ),

                      Text(
                        "Warm",
                        style: TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: 22,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
          SizedBox(height: 20,),

          Neumorphic(
            status: NeumorphicStatus.convex,
            height: 50,
            decoration: NeumorphicDecoration(
              borderRadius: BorderRadius.circular(10),
            ),
            child: Center(
              child: Text(
                "Update Settings",
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 16,
                  color: Theme.of(context).accentColor,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
wow.png

那么讓我們看看如何使這一切井然有序。

1、使用方法重構(gòu)

我想你在某些地方已經(jīng)看到了這種技術(shù)而沒有意識(shí)到。該技術(shù)只是將widget作為方法調(diào)用的返回值,進(jìn)行封裝使用。假設(shè)在Flutter中一切都是widget,那么任何參與組成UI的類都繼承自Widget類,該方法的返回值可能是任何一個(gè)widget類或者一些特定的類,例如容器類container、row、column等。

繼續(xù)往下看,方法中的Widget可以依賴父widget的BuildContext實(shí)例或?qū)ο蟆_@就是問題的來源,記住BuildContext對(duì)象知道widget在widget tree中的位置。既然此方法依賴于主BuildContext,那么當(dāng)父widget重繪時(shí),此方法也將強(qiáng)制重新組裝、重新創(chuàng)建或者重繪其內(nèi)部的widget。或者如果該方法也調(diào)用了其他依賴于父widget的BuildContext的方法,也會(huì)帶來副作用,所有方法繪制他們的widget的次數(shù)將會(huì)和繪制父widget的次數(shù)一樣多。無論哪種情況,這都不是我們重構(gòu)后所期望的行為。

使用這種方法,我們將widget分割開來,這當(dāng)然能夠帶來可讀性及可維護(hù)性的提升,但是對(duì)于性能優(yōu)化,并沒有什么用處。當(dāng)widget數(shù)量增加時(shí),我們UI的性能在配置更改期間將會(huì)下降,例如屏幕旋轉(zhuǎn)。

下面是兩個(gè)方法的示例:

Column _buildLeadingColumn(BuildContext context) {
    return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Container(
            height: 40,
            width: 40,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              color: Theme.of(context).primaryColor,
              boxShadow: [
                BoxShadow(
                  offset: Offset(3, 3),
                  color: Colors.black12,
                  blurRadius: 5,
                ),
                BoxShadow(
                  offset: Offset(-3, -3),
                  color: Colors.white,
                  blurRadius: 5,
                )
              ],
            ),
            child: Icon(
              Icons.arrow_back_ios,
              size: 14,
            ),
          ),
        ],
      );
  }
Widget _buildRow(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Text(
          "Period",
          style: TextStyle(
            fontWeight: FontWeight.bold,
            color: Theme.of(context).textTheme.caption.color,
          ),
        ),
        SizedBox(
          width: 30,
        ),
        Text(
          "Last 30 days",
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 16,
          ),
        ),
      ],
    );
  }

我們使用Visual Studio Code作為代碼編輯器(AS也一樣),并按照以下步驟進(jìn)行重構(gòu):
1.打開任何.dart文件
2.將光標(biāo)放在第一個(gè)widget上,然后右擊,在我的場(chǎng)景中,是在Row、Container或者Column上。
3.選中Refactor >Extract Method
4.在提取方法的彈窗中,輸入_buildRow作為方法名,注意方法前的下劃線,讓Dart知道這是一個(gè)私有方法。
5.Row widget現(xiàn)在替換為了_b方法uildRow(),滾動(dòng)到代碼底部,方法和widget都得到了很好的重構(gòu)。
6.繼續(xù)重構(gòu)其他的Rows、Columns、Containers和Stack Widget。

這種方式增加了代碼的可讀性,widget樹的主要組成部分被分割成了非常簡單的方法,這種方式的好處是純粹和簡單的代碼可讀性和可維護(hù)性,作為回報(bào)失去了優(yōu)化性能,如果你想看更多內(nèi)容,請(qǐng)轉(zhuǎn)到底部的引用部分。

2、使用局部變量重構(gòu)

和第一種重構(gòu)方式有些相識(shí),只不過這里使用局部變量,包括使用final變量初始化widget。在這里一樣是將widget樹的主要部分分割成多個(gè),這增加了代碼的可讀性和可維護(hù)性。
在這種情況下,雖然我們的widget使用final來初始化變量,但是仍然使用的是父widget的BuildContext,當(dāng)框架重繪父widget時(shí),局部變量也將會(huì)被重繪。這增加了可讀性和可維護(hù)性,你的widget樹將會(huì)變淺,但是不會(huì)優(yōu)化性能。

下面是一個(gè)帶有常量的的重構(gòu)代碼示例:

final rowConstant = Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Text(
          "Period",
          style: TextStyle(
            fontWeight: FontWeight.bold,
            color: Theme.of(context).textTheme.caption.color,
          ),
        ),
        SizedBox(
          width: 30,
        ),
        Text(
          "Last 30 days",
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 16,
          ),
        ),
      ],
    );

我們使用Visual Studio Code作為代碼編輯器(AS也一樣),并按照以下步驟進(jìn)行重構(gòu):
1.打開任何.dart文件
2.將光標(biāo)放在第一個(gè)widget上,然后右擊,在我的場(chǎng)景中,是在Row、Container或者Column上。
3.選擇 Refactor > Extract Local Varialble
4.在我們的例子中,將局部變量命名為rowConstant,注意我們使用final進(jìn)行修飾,告訴Dart這是一個(gè)常量。
5.Row widget替換為了rowConstant最終變量。滾動(dòng)帶代碼頂部,局部變量和widget都得到了很好的重構(gòu)。
6.繼續(xù)重構(gòu)其他的Rows、Columns、Containers和Stack Widget。

3、使用widget class重構(gòu)

這種方式允許你使用繼承自StatelessWidget或者StatefullWidget的類,來隔離widget子樹,還允許你創(chuàng)建可重用的widget,并且可以將它們分布在相同或不同的dart文件中,這樣你就可以在程序的任何地方引入或者使用這些文件。警告!這些類的構(gòu)造函數(shù)必須以const關(guān)鍵字開頭,再次感謝Dart,以const開頭聲明的構(gòu)造函數(shù),會(huì)告訴Dart緩存和重用這些widget,與此相反的是其它widget將會(huì)被重繪。

當(dāng)你要?jiǎng)?chuàng)建此類的對(duì)象時(shí),不要忘記使用const關(guān)鍵字。通過這樣做,當(dāng)其他widget在widget樹中更改狀態(tài)時(shí),此widget將不會(huì)被重建。如果遺漏了const關(guān)鍵字,父widget重繪多少次,我們的widget也將會(huì)跟著重繪多少次,因此需要留心。

這樣的widget類依賴它自己的BuildContext,而不是像重構(gòu)成方法或者變量的那樣依賴于父widget的。BuildContext負(fù)責(zé)管理widget在widget樹中的位置。

現(xiàn)在讓我們看看使用這種方式的小例子:

class PaddingWidget extends StatelessWidget {
  const PaddingWidget({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 20),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Text(
                "Period",
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Theme.of(context).textTheme.caption.color,
                ),
              ),
              SizedBox(
                width: 30,
              ),
              Text(
                "Last 30 days",
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 16,
                ),
              ),
            ],
          ),
          Container(
            height: 40,
            width: 40,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              color: Theme.of(context).primaryColor,
              boxShadow: [
                BoxShadow(
                  offset: Offset(3, 3),
                  color: Colors.black12,
                  blurRadius: 5,
                ),
                BoxShadow(
                  offset: Offset(-3, -3),
                  color: Colors.white,
                  blurRadius: 5,
                )
              ],
            ),
            child: Icon(
              Icons.arrow_forward_ios,
              size: 14,
            ),
          ),
        ],
      ),
    );
  }
}

我們使用Visual Studio Code作為代碼編輯器(AS也一樣),并按照以下步驟進(jìn)行重構(gòu):
1.打開任何.dart文件
2.將光標(biāo)放在第一個(gè)widget上,然后右擊,在我的場(chǎng)景中,是在Row、Container或者Column上。
3.選擇 Refactor > Extract Widget
4.在我們的例子中,將類名命名為PaddingWidget
5.Padding widget替換為了PaddingWidget類。滾動(dòng)帶代碼底部,類和widget都得到了很好的重構(gòu)。
6.繼續(xù)并重構(gòu)其他Padding(PaddingWidgets class)、Rows(RowsAndColumnWidget class)widget。

抱歉,有太多內(nèi)容需要消化,我總結(jié)一下:你不僅在可讀性和可維護(hù)性上有所收獲,并且性能也會(huì)有很大提升。因?yàn)楫?dāng)父widget重繪時(shí),并不是所有widget都會(huì)被重繪,他們只構(gòu)建一次。

結(jié)論

在這篇文章中,你了解到了widget樹是widget嵌套的結(jié)果,隨著widget的增加,widget樹會(huì)迅速擴(kuò)展并且降低代碼的可讀性以及可管理性,這被稱之為整個(gè)widget樹。為了提高代碼的可讀性和可管理性,你可以將widget分割成獨(dú)立的widget類,創(chuàng)建一個(gè)淺的widget樹。在每個(gè)程序中,你都應(yīng)該盡量保持widget樹層級(jí)淺。通過使用widget類的重構(gòu)方式,你可以在Flutter子樹的重構(gòu)中獲益,這將會(huì)提升性能。

感謝閱讀我的文章,歡迎進(jìn)行評(píng)論。

引用:
Beginning_Flutter

Refactoring a Flutter Project -- a story about progression and decisions

Refactorings and Code Fixes

JidiGutu/weather_neumorphism_ui

Flutter Community

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評(píng)論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,727評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,411評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,777評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,978評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,216評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,657評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,960評(píng)論 2 373

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