Flutter新人實戰(zhàn)—從0開始開發(fā)一個DIY活動記錄應用(六)數(shù)據(jù)持久化之sqflite

版權聲明:本文為本人原創(chuàng)文章家浇,未經(jīng)本人允許不得轉(zhuǎn)載。

Hello碴裙,大家好這兩天利用空余時間忙著寫統(tǒng)計分析頁面蓝谨,所以隔了兩天來繼續(xù)更新。
第五篇為止我們基本把要展現(xiàn)的頁面和UI都寫完了青团,但是數(shù)據(jù)都是初始化好的譬巫,如何通過用戶自己添加一條數(shù)據(jù)并進行數(shù)據(jù)永久保存呢,有請今天的主角:sqflite督笆,F(xiàn)lutter的嵌入式數(shù)據(jù)庫插件芦昔。
要使用他我們首先要在pubspec.yaml中引入這個包,同時由于數(shù)據(jù)庫操作要用到本地的路徑訪問娃肿,所以我們首先一并添加這些包:

dependencies:
  flutter:
    sdk: flutter
  #數(shù)據(jù)庫
  sqflite: ^0.11.0
  #文件路徑訪問
  path_provider: ^0.4.0

然后我們執(zhí)行get packages咕缎,獲取插件內(nèi)容珠十。下面我們正式開始今天的內(nèi)容。

一凭豪、新建數(shù)據(jù)庫及其增刪改查方法

1焙蹭、修改diy_project.dart,添加如下代碼:

  //根據(jù)項目的屬性內(nèi)容生成一個鍵值對map嫂伞,這個mao的鍵就是后面數(shù)據(jù)庫的字段孔厉,他們是一一對應的。
  Map<String, dynamic> toMap() {
    Map map = <String, dynamic>{
      'name': _name,
      'date': _date,
      'place': _place,
      'contact': _contact,
      'imagePath': _imagePath,
      'singlePrice': _singlePrice,
      'nums': _nums,
      'totalAmount': _totalAmount,
      'itemCost': _itemCost,
      'laborCost': _laborCost,
      'profit': _profit,
      'isCheckOut': _isCheckOut == true ? 1 : 0
    };
    if (_id != null) {
      map['id'] = _id;
    }
    return map;
  }

  //根據(jù)map獲得一個diyProject的實例
  DiyProject.fromMap(Map<String, dynamic> map) {
    _id = map['id'];
    _name = map['name'];
    _date = map['date'];
    _place = map['place'];
    _contact = map['contact'];
    _imagePath = map['imagePath'];
    _singlePrice = map['singlePrice'];
    _nums = map['nums'];
    _totalAmount = map['totalAmount'];
    _itemCost = map['itemCost'];
    _laborCost = map['laborCost'];
    _profit = map['profit'];
    _isCheckOut = map['isCheckOut'] == 1;
  }

以上代碼分別是根據(jù)項目實例轉(zhuǎn)換成map和通過map獲得一個項目實例帖努。注意撰豺,其中map的鍵是和后面數(shù)據(jù)庫字段相對應的。

2拼余、新建數(shù)據(jù)庫

在model目錄下新建data_base.dart 文件污桦,我們將在里面編寫數(shù)據(jù)庫相關的代碼。
首先導入插件的引用:

import 'package:activity_record/model/diy_project.dart'; //項目類匙监,供數(shù)據(jù)庫操作使用
import 'package:sqflite/sqflite.dart'; //數(shù)據(jù)庫
import 'dart:io'; //本地文件使用
import 'dart:async';//異步操作
import 'package:path/path.dart';//本地路徑訪問
import 'package:path_provider/path_provider.dart';//本地路徑訪問

繼續(xù)新建數(shù)據(jù)庫類

class DataBase {
  Database _myDateBase;
  //定義表名
  final String tableName = "diyTable1";
  //定義各個字段名
  final String columnId = "id";
  final String columnName = "name";
  final String columnDate = "date";
  final String columnPlace = "place";
  final String columnContact = "contact";
  final String columnImagePath = "imagePath";
  final String columnSinglePrice = "singlePrice";
  final String columnNums = "nums";
  final String columnTotalAmount = "totalAmount";
  final String columnItemCost = "itemCost";
  final String columnLaborCost = "laborCost";
  final String columnProfit = "profit";
  final String columnIsCheckOut = "isCheckOut";

  //獲取數(shù)據(jù)庫
  Future get db async {
    if (_myDateBase != null) {
      print('數(shù)據(jù)庫已存在');
      return _myDateBase;
    } else
      _myDateBase = await initDb();
      return _myDateBase;
  }

  //初始化數(shù)據(jù)庫凡橱,根據(jù)路徑版本號新建數(shù)據(jù)庫
  initDb() async {
    Directory directory = await getApplicationDocumentsDirectory();
    String path = join(directory.path, "diyDB.db");
    var dataBase = await openDatabase(path, version: 1, onCreate: _onCreate);
    print('數(shù)據(jù)庫創(chuàng)建成功,version: 1');
    return dataBase;
  }

  //新建數(shù)據(jù)庫表
  FutureOr _onCreate(Database db, int version) async {
    await db.execute('''create table $tableName(
    $columnId integer primary key autoincrement,
    $columnName text not null,
    $columnDate text,
    $columnPlace text,
    $columnContact text,
    $columnImagePath integer ,
    $columnSinglePrice integer not null,
    $columnNums integer not null,
    $columnTotalAmount integer not null,
    $columnItemCost integer ,
    $columnLaborCost integer ,
    $columnProfit integer not null,
    $columnIsCheckOut integer not null)''');
    print('Table is created');
  }
}

以上分別說明數(shù)據(jù)庫是如何建立起來的:

1亭姥、定義表明和表的字段名梭纹,因為我這個項目屬性不多就用了一張表,注意這個字段名要和之前的diyProject里的map方法里的鍵要一致致份,因為后面的數(shù)據(jù)操作都要依賴這個变抽。
2、(1)初始化數(shù)據(jù)庫氮块,首先通過getApplicationDocumentsDirectory();獲得一個本地目錄用于存放數(shù)據(jù)庫文件绍载,
(2)然后通過join(directory.path, "diyDB.db")在某個目錄里新建一個數(shù)據(jù)庫文件,其中括號內(nèi)屬性是目錄路徑和數(shù)據(jù)庫名稱滔蝉,同時返回這個數(shù)據(jù)庫文件的路徑击儡。
(3)最后通過這個路徑我們打開數(shù)據(jù)庫并初始化數(shù)據(jù)庫,包括數(shù)據(jù)庫版本和新建數(shù)據(jù)表
3蝠引、獲得這個數(shù)據(jù)庫實例阳谍,首先判斷數(shù)據(jù)庫是否存在,如果不存在則新建螃概,存在則返回矫夯。

回到home_page.dart
添加:

//實例化數(shù)據(jù)庫對象
  DataBase _database = new DataBase();

運行一下程序看看,如果是首次運行應該會在控制臺看到這樣的話:


image.png

當你下次再運行應用的時候就會再控制臺看到提示 ‘數(shù)據(jù)庫已存在’吊洼,除非卸載應用重新安裝训貌,否則數(shù)據(jù)庫文件將一直存在。

3、增加數(shù)據(jù)庫增刪改查方法

數(shù)據(jù)庫已經(jīng)有了递沪,顯然我們是要對數(shù)據(jù)庫進行操作的豺鼻,雖然數(shù)據(jù)庫感覺很復雜的樣子,但是歸納起來無非就是增刪改查款慨,數(shù)據(jù)庫操作會涉及數(shù)據(jù)庫sql語句儒飒,如果這塊沒有基礎的話我建議去了解下sql語句基礎,對普通的增刪改查有個了解檩奠,知道怎么寫即可桩了。
繼續(xù)在數(shù)據(jù)庫類里添加以下代碼:
1、新增數(shù)據(jù)

//插入diyProject
  Future<int> insertDiyProject(DiyProject diy) async {
    //獲取數(shù)據(jù)庫實例
    Database database = await db;
    //diy.toMap()是將diy實例轉(zhuǎn)換成字段名和值對應的map
    var result = database.insert(tableName, diy.toMap());
    print('數(shù)據(jù)已插入');
    return result;
  }

2笆凌、查詢數(shù)據(jù)

//獲取所有diyProject
  Future<List> getDiyProjects() async {
    //獲取數(shù)據(jù)庫實例
    Database database = await db;
    //返回一個 map型的數(shù)組圣猎,其中map是由字段名和值構(gòu)成
    var result = await database
        .rawQuery("select * from $tableName order by $columnId desc");
    print('獲取所有diyProject,當前diyProject有: $result');
    return result;
  }

  //獲取所有未結(jié)賬的diyProject
  Future<List> getUnCheckedDiyProjects() async {
    Database database = await db;
    var result = await database.rawQuery(
        "select * from $tableName where $columnIsCheckOut = 0 order by $columnId desc");
    return result;
  }

  //獲取diyProject總數(shù)
  Future<int> getDiyCount() async {
    Database database = await db;
    var result = await database.rawQuery("select count(*) from $tableName");
    /*查詢結(jié)果返回的是一個map類型的數(shù)組士葫,雖然這里查詢結(jié)果只有一條乞而,但是很多查詢是會返回多條數(shù)據(jù)的,所以是一個數(shù)組類型慢显。
     這里我們?nèi)?shù)組的第一個值爪模,然后再通過鍵來取對應的數(shù)據(jù)
    */
    return result[0]['count(*)'];
  }

  

  //獲取單個diyProject
  Future<DiyProject> getDiyProject(int id) async {
    Database database = await db;
    //根據(jù)id查詢對應的diy項目,并返回一個map類型的數(shù)組
    var result = await database
        .rawQuery("select * from $tableName where $columnId = $id");
    if (result.length == 0) {
      return null;
    } else
      return DiyProject.fromMap(result[0]);
  }

我這里一共寫了4個查詢方法荚藻,注釋里已經(jīng)分別寫了查詢的內(nèi)容屋灌,都是后面會用到的。

注意點:數(shù)據(jù)庫查詢操作返回的都是map類型的數(shù)組应狱,map中的鍵就是查詢對象共郭,值就是查詢的結(jié)果。哪怕查詢結(jié)果只有一條返回的也是一個數(shù)組疾呻。

3除嘹、更新數(shù)據(jù)

//更新diyProject
  Future<int> updateDiyProject(DiyProject diyProject) async {
    Database database = await db;
    var result = database.update(tableName, diyProject.toMap(),
        where: "$columnId = ?", whereArgs: [diyProject.id]);
    print('我是更新數(shù)據(jù)的方法 本次更新的res: $result');
    return result;
  }

4、刪除數(shù)據(jù)

//刪除diyProject
  Future<int> deleteDiyProject(int id) async {
    Database database = await db;
    var result = await database
        .rawDelete("delete from $tableName where $columnId = $id");
    return result;
  }

4岸蜗、添加關閉數(shù)據(jù)庫方法

別忘了當不再使用的時候關閉數(shù)據(jù)庫

//關閉數(shù)據(jù)庫
  Future close() async {
    Database database = await db;
    database.close();
  }

到這里呢尉咕,數(shù)據(jù)庫類我們就完全寫好了,這樣我們就可以通過不同的方法來對數(shù)據(jù)庫進行讀寫數(shù)據(jù)啦璃岳∧甓校看不到效果可不行,當然要去業(yè)務邏輯里實現(xiàn)以下铃慷。

二单芜、實現(xiàn)用戶和數(shù)據(jù)庫的交互

在進行業(yè)務邏輯實現(xiàn)之前,我們先要合并一些文件犁柜。在之前的文章中缓溅,為了給大家演示清楚頁面框架結(jié)構(gòu)和里面控件的關系,我將框架和UI分開了赁温,但是因為在這個應用中頁面UI的內(nèi)容都會根據(jù)用戶輸入而改變坛怪,所以需要將框架和頁面UI放在一個dart文件里淤齐,這樣操作更方便。
我們需要分別合并以下文件:

1袜匿、ui目錄下的diy_add_show.dart 和pages目錄下的diy_add_dialog.dart合并更啄,所謂合并是指將ui文件里的控件內(nèi)容復制到pages頁面文件里的Scaffold所屬的body屬性里。
2居灯、ui目錄下的diy_info_show.dart和pages目錄下的diy_item_info.dart合并
3祭务、ui目錄下的diy_list_show.dart和pages目錄下的home_page.dart合并

要實現(xiàn)用戶新增數(shù)據(jù)到數(shù)據(jù)庫并展現(xiàn)在首頁列表中需要分以下幾個步驟:

1、通過用戶輸入的內(nèi)容獲得一個diyProject實例對象
2怪嫌、當用戶點擊保存按鈕的時候?qū)㈨椖繉嵗龑ο髢?nèi)容插到數(shù)據(jù)庫
3义锥、告訴首頁數(shù)據(jù)庫里新增了一條數(shù)據(jù)需要重繪UI以顯示新增的這條數(shù)據(jù)

通過以上分析我們可以基本得知在新增項目頁面,用戶主要分為兩類操作岩灭,在各個輸入框中填入項目信息和點擊保存拌倍。
那么我們首先在diy_add_dialog.dart中新增點擊保存后的方法:
diy_add_dialog.dart

//點擊保存按鈕進行數(shù)據(jù)保存入庫
  _saveDiyItem(
      String name,
      String date,
      String place,
      String contact,
      String imagePath,
      int singlePrice,
      int nums,
      int totalAmount,
      int itemCost,
      int laborCost,
      int profit,
      bool isCheckOut) async {
    DiyProject newDiyProject = new DiyProject(
        name,
        date,
        place,
        contact,
        imagePath,
        singlePrice,
        nums,
        totalAmount,
        itemCost,
        laborCost,
        profit,
        isCheckOut);
    int savedID = await widget.db.insertDiyProject(newDiyProject);
    print('插入的savedID:$savedID');

以上方法執(zhí)行了兩步操作:
1、根據(jù)參數(shù)實例化一個diyProject實例對象
2噪径、通過調(diào)用數(shù)據(jù)庫的insertDiyProject方法將對象插入數(shù)據(jù)庫

要在這個頁面對數(shù)據(jù)庫進行操作柱恤,所以需要將數(shù)據(jù)庫作為這個類的構(gòu)造函數(shù)的參數(shù),這樣當從首頁進入到這個頁面的時候?qū)?shù)據(jù)庫實例作為參數(shù)傳帶進來找爱。
所以在類的開頭作如下修改:
diy_add_dialog.dart

class DiyAddDialog extends StatefulWidget {
  DiyAddDialog({Key key, this.db,}) : super(key: key);
  var db;

  @override
  DiyAddDialogState createState() => new DiyAddDialogState();
}

保存的方法有了琼梆,剩下的就是在保存按鈕里添加這個方法碰辅,同時點擊后關閉添加頁面爹谭,回到首頁進行展示奏寨。
繼續(xù)修改diy_add_dialog.dart,首先在appbar里添加保存按鈕:
diy_add_dialog.dart

class DiyAddDialogState extends State<DiyAddDialog> {
...
@override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(_title),
        actions: <Widget>[
          new FlatButton(
            child: new Text(
              '保存',
              style: Theme.of(context)
                  .textTheme
                  .subhead
                  .copyWith(color: Colors.white),
            ),
            onPressed: () {},
          )
        ],
      ),
      body:
...

然后在onPressed: () {}的回調(diào)函數(shù)里添加保存數(shù)據(jù)的方法:

          onPressed: () {
              _saveDiyItem(
                  _nameTextEditingController.text,
                  DateFormat.yMd("en_US").format(_selectedDate),
                  _placeTextEditingController.text,
                  _contactTextEditingController.text,
                  _imagePath,
                  int.parse(_singlePriceTextEditingController.text),
                  int.parse(_numsTextEditingController.text),
                  _totalAmountCalculate(),
                  int.parse(_itemCostTextEditingController.text == ''
                      ? '0'
                      : _itemCostTextEditingController.text),
                  int.parse(_laborCostTextEditingController.text == ''
                      ? '0'
                      : _laborCostTextEditingController.text),
                  _profitCalculate(),
                  _isCheckedOut);
              Navigator.of(context).pop();
            },

以上代碼注意:
1吮播、_savedDiyItem()方法里的參數(shù)有通過用戶輸入獲取的变屁,也有通過方法計算得知的,比如_nameTextEditingController.text就是用戶輸入的名字薄料,.text是將監(jiān)聽獲得內(nèi)容轉(zhuǎn)換成文本敞贡。
2、而int.parse(_singlePriceTextEditingController.text),則是將文本輸入的金額轉(zhuǎn)換成int型摄职。
3誊役、像總金額、利潤等值不是通過用戶輸入的谷市,而是通過用戶輸入的內(nèi)容計算而來蛔垢,所以我們要添加兩個計算的方法如下:

//根據(jù)輸入計算總金額
  _totalAmountCalculate() {
    int _totalAmount = int.parse(_singlePriceTextEditingController.text) *
        int.parse(_numsTextEditingController.text);
    return _totalAmount;
  }

  //根據(jù)輸入計算利潤
  _profitCalculate() {
    int totalAmount = _totalAmountCalculate();
    int profit = totalAmount -
        int.parse(_itemCostTextEditingController.text == ''
            ? '0'
            : _itemCostTextEditingController.text) -
        int.parse(_laborCostTextEditingController.text == ''
            ? '0'
            : _laborCostTextEditingController.text);
    return profit;
  }

以上兩段代碼中可能你都發(fā)現(xiàn)了三元運算符int.parse(_laborCostTextEditingController.text == '' ? '0' : _laborCostTextEditingController.text,作用是當用戶沒有輸入的時候給他一個默認值0迫悠,否則插入數(shù)據(jù)庫會報錯鹏漆。
4、在onPressed回調(diào)函數(shù)最后添加Navigator.of(context).pop();表示點擊按鈕后就會將該頁面出棧,回到首頁艺玲。
說了這么多括蝠,是時候自己操作一把了,打開新增頁面饭聚,自己嘗試輸入內(nèi)容忌警,然后點擊保存:

image.png

控制臺會看到如下信息:
image.png

而且也回到首頁了,但是是不是一臉蒙蔽秒梳,因為首頁并沒有展示這條diy項目信息法绵,到底是怎么回事呢,因為我們并沒有告訴首頁展示的數(shù)據(jù)內(nèi)容發(fā)生了變化酪碘。下面我們回到home_page.dart朋譬,讓剛才添加的內(nèi)容展現(xiàn)出來。
修改home_page.dart如下
添加展示內(nèi)容列表

  //實例化diyProjects數(shù)組兴垦,并初始化空徙赢,作為首頁要展示的內(nèi)容列表
  List<DiyProject> _diyProjects = <DiyProject>[];

每次運行程序的時候或者需要刷新的時候,我們需要先從數(shù)據(jù)庫遍歷數(shù)據(jù)滑进,并加到要展示的內(nèi)容列表犀忱,從而進行數(shù)據(jù)展示募谎,用到的就是之前數(shù)據(jù)庫類里的查詢方法:

  //遍歷數(shù)據(jù)庫初始化_diyProjects數(shù)據(jù)
  _getDiyProjects() async {
    print('=========開始讀取數(shù)據(jù)庫全部數(shù)據(jù)=========');
    List result = await _database.getDiyProjects();
    _diyProjects.clear();
    if (result.length != 0) {
      setState(() {
        result.forEach((diy) => _diyProjects.add(DiyProject.fromMap(diy)));
      });
    }
  }

以上代碼首先通過數(shù)據(jù)庫查詢獲得一個map類型的數(shù)組扶关,然后通過diyProject的fromMap方法將這些查詢的結(jié)果轉(zhuǎn)化成一個個diyProject實例,然后添加到_diyProjects數(shù)組中数冬。并通過setState告訴應用要重繪頁面节槐。

查詢數(shù)據(jù)庫并告訴應用進行頁面重繪的方法是有了,那么何時執(zhí)行這個方法呢拐纱?铜异?

其實你想一想應該就知道:
1、每次打開應用的時候秸架,我們需要能看到數(shù)據(jù)庫已有的數(shù)據(jù)揍庄。
在初始化里添加這個遍歷數(shù)據(jù)的方法,這樣每次打開應用就會看到所有數(shù)據(jù)了东抹。

 //數(shù)據(jù)初始化
  @override
  void initState() {
    super.initState();
    _getDiyProjects();
  }

2蚂子、每次點擊新增然后添加完點擊保存的時候我們想看到新的數(shù)據(jù)。
注意這個時間點的描述是這樣的:點擊新增頁面的保存按鈕然后退回到首頁的時候缭黔。我們知道頁面路由的pop是可以返回數(shù)據(jù)的食茎,我們這里雖然不用返回數(shù)據(jù),但是我們就是要在知道返回回來的時候遍歷數(shù)據(jù)庫進行數(shù)據(jù)刷新馏谨。
所以我們需要在點擊新增按鈕的地方使用async異步延遲的方法來進到新頁面從而知曉何時從頁面返回别渔,從而進行數(shù)據(jù)刷新,修改floatingActionButton的onPressed回調(diào)函數(shù),通過異步方式進入新頁面并等待返回時刷新數(shù)據(jù)

floatingActionButton: new FloatingActionButton(
          onPressed: () {
            _addDiyProject();
          },
          child: new Icon(Icons.add),
        ),

//進入新增頁面
  Future _addDiyProject() async {
    await Navigator.of(context).push(new MaterialPageRoute(
        fullscreenDialog: true,
        builder: (context) {
          return new DiyAddDialog(
            db: _database,
            diyProjects: _diyProjects,
          );
        }));
    //返回后哎媚,通過_getDiyProjects()方法重新遍歷數(shù)據(jù)庫并刷新頁面
    _getDiyProjects();
  }

這樣當我們點擊新增按鈕喇伯,通過輸入信息后點擊保存返回首頁就可以看到自己新增的card數(shù)據(jù)了,而且由于數(shù)據(jù)是保存在數(shù)據(jù)庫當中拨与,即使關閉應用重新打開之前添加的數(shù)據(jù)也都會在艘刚,主要不卸載數(shù)據(jù)都不會丟失。

可能你也有這樣的疑慮:能不能通過Navigator.of(context).pop直接返回這個新增的diyProject截珍,然后將接收到的返回的diyProject插入數(shù)組然后刷新頁面呢攀甚?當然是可以的,你嘗試著實現(xiàn)下看看岗喉。

留一個小作業(yè)給大家吧秋度,還記得在上一篇我在首頁添加了一個tabbar,分別進行所有項目和未結(jié)項目的展示钱床,我這里主要是針對所有項目進行了說明荚斯,如何實現(xiàn)未結(jié)項目的展示嘗試著做一下把。

今日總結(jié)

1查牌、數(shù)據(jù)庫sqflite的使用
2事期、通過獲取用戶輸入實例化對象并插入數(shù)據(jù)庫中
3、通過帶async的Navigator.of(context).push纸颜,得知何時返回兽泣,并執(zhí)行相應操作
4、通過setState() 告訴系統(tǒng)狀態(tài)發(fā)生變化胁孙,需要重新繪制頁面UI從而展示新的內(nèi)容

最后附上項目源碼地址:https://gitee.com/xusujun33/activity_record_jia.git
有不明白的或者有出入的可以對照查看唠倦,當然程序一直在更新,所以可能會有內(nèi)容上的出入涮较,但是方法都是相通的稠鼻。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市狂票,隨后出現(xiàn)的幾起案子候齿,更是在濱河造成了極大的恐慌,老刑警劉巖闺属,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慌盯,死亡現(xiàn)場離奇詭異,居然都是意外死亡屋剑,警方通過查閱死者的電腦和手機润匙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唉匾,“玉大人孕讳,你說我怎么就攤上這事匠楚。” “怎么了厂财?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵芋簿,是天一觀的道長。 經(jīng)常有香客問我璃饱,道長与斤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任荚恶,我火速辦了婚禮撩穿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谒撼。我一直安慰自己食寡,他們只是感情好,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布廓潜。 她就那樣靜靜地躺著抵皱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辩蛋。 梳的紋絲不亂的頭發(fā)上呻畸,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機與錄音悼院,去河邊找鬼伤为。 笑死,一個胖子當著我的面吹牛樱蛤,可吹牛的內(nèi)容都是我干的钮呀。 我是一名探鬼主播剑鞍,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼昨凡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蚁署?” 一聲冷哼從身側(cè)響起便脊,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎光戈,沒想到半個月后哪痰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡久妆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年晌杰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筷弦。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡肋演,死狀恐怖抑诸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爹殊,我是刑警寧澤蜕乡,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站梗夸,受9級特大地震影響层玲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜反症,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一辛块、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铅碍,春花似錦憨降、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呜魄,卻和暖如春悔叽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爵嗅。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工娇澎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人睹晒。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓趟庄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伪很。 傳聞我的和親對象是個殘疾皇子戚啥,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

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