Android模板制作

本文詳細(xì)介紹模板相關(guān)的知識(shí)和如何制作Android模版及使用罢浇,便于較少不必要的重復(fù)性工作。比如我在工作中如果要?jiǎng)?chuàng)建一個(gè)新的模塊变泄,就不要需要?jiǎng)?chuàng)建MVP相關(guān)的幾個(gè)類:Model嗜诀、View、Presenter炬太、Entity等灸蟆。

本文專門介紹和模板相關(guān)的知識(shí),那么問題來了:

  1. 模板是什么
  2. 模板使用位置
  3. 模板如何創(chuàng)建(包含模板存放位置)
  4. 模板如何使用

接下來亲族,我就按照以上順序?yàn)榇蠹医庾x看起來高大上的模板炒考。

警告

本文所有模板路徑均為Mac下的路徑,Windows用戶也可以查看路徑中的相關(guān)信息霎迫,進(jìn)而快速定位斋枢。

模板是什么

個(gè)人理解:模板即為了幫助人們簡化某些固定而繁瑣的操作而制作的工具,用于快速實(shí)現(xiàn)這些固定而繁瑣的操作知给。

模板使用位置

當(dāng)我們在使用AndroidStudio進(jìn)行開發(fā)的時(shí)候瓤帚,將鼠標(biāo)選中工程項(xiàng)目,然后右擊可以在New選項(xiàng)下面看到很多AndroidStudio提供給我們的模板類別涩赢,例如:Activity戈次、AIDL等。具體可看下圖:

工程右擊-New.png

細(xì)心的你會(huì)發(fā)現(xiàn)在這些模板的上面有一個(gè)選項(xiàng):Edit File Templates...筒扒,如下圖所示:

Edit-File-Templates.png

點(diǎn)擊這個(gè)選項(xiàng)怯邪,會(huì)進(jìn)入自定義模板頁面,其中內(nèi)置的變量在頁面下方都有解釋花墩,是不是很方便擎颖,但是它有一個(gè)致命的缺點(diǎn):一次只能創(chuàng)建一個(gè)java文件。具體可看下圖:

Edit-File-Templates-in.png

因?yàn)橛X得這個(gè)很簡單观游,所以我就不做過多闡述了,接下來我就仔細(xì)闡述一下驮俗,如何一次創(chuàng)建多個(gè)java文件懂缕,而且還可以選擇是否包含xml文件。

模板如何創(chuàng)建(包含模板存放位置)

警告

如果直接復(fù)制相關(guān)代碼的話王凑,請注意其中的注釋搪柑,可能會(huì)帶來一些問題,如果出現(xiàn)問題索烹,可以把#開頭的注釋去除工碾,再嘗試!0傩铡渊额!

如果不懂上面這段話的意思的話,可以先行跳過。

FreeMarker

AndroidStudio的模板是使用FreeMarker模板引擎制作的旬迹,有興趣的可以了解一下火惊。

案例&解答

案例:

由于現(xiàn)在的項(xiàng)目使用的是類MVP架構(gòu),所以基本上每個(gè)模塊都需要entity奔垦、request屹耐、activity、presenter椿猎、viewmodel這五個(gè)類惶岭,無論是登錄注冊模塊,還是商品詳情頁犯眠、首頁按灶、收益頁面等模塊,都無法擺脫這幾個(gè)類阔逼,因此準(zhǔn)備為這個(gè)類MVP架構(gòu)制作一個(gè)通用模板兆衅。

解答:

制作好模板之后,我想說嗜浮,其實(shí)很簡單羡亩,只是把會(huì)變化的部分用${...}替換罷了,不過在這里我們還是老老實(shí)實(shí)的從頭開始吧危融!

步驟

模板存放位置

首頁我們進(jìn)入AndroidStudio安裝目錄下的/plugins/android/lib/templates文件夾畏铆,這就是AndroidStudio模板文件的目錄了,到這里你可能還有所迷惑吉殃,因?yàn)槟銢]有發(fā)現(xiàn)像我剛開始所說的Activity辞居、AIDL等模板文件,沒關(guān)系蛋勺,你再進(jìn)入activities文件夾下面就可以看到Activity的相關(guān)模板了瓦灶,進(jìn)入other文件夾就可以看到AIDL的相關(guān)模板了。

模板副本

這里我們選擇activities文件夾抱完,然后你是不是覺得手足無措贼陶,不知道如何下手?其實(shí)一開始我也不知道怎么做巧娱,但是沒關(guān)系碉怔,AndroidStudio不是已經(jīng)提供給我們這么多模板了么,為了簡單起見禁添,我們在這里拷貝一份EmptyActivity撮胧,并將其重命名為MVPActivity放在當(dāng)前目錄下老翘。

目錄結(jié)構(gòu)

打開文件夾后芹啥,我們看到以下目錄結(jié)構(gòu):

EmptyActivity
  |----globals.xml.ftl # 全局變量文件
  |----recipe.xml.ftl  # 配置要引用的模板路徑以及生成文件的路徑
  |----root
    |----src
      |----app_package
        |----SimpleActivity.java.ftl # 模板文件
  |----template_blank_activity.png   # 創(chuàng)建模板時(shí)界面左邊的預(yù)覽圖
  |----template.xml # 模板的配置信息以及要輸入的參數(shù)

接下我們可以根據(jù)目錄結(jié)構(gòu)順序(建議按以下順序看)锻离,打開看一下,這里大致介紹一下:

globals.xml.ftl

globals.xml.ftl中都是類似

<global id="hasNoActionBar" type="boolean" value="false" />

這樣的語句叁征,顯然它的意思就是我定義了一個(gè)全局變量hasNoActionBar纳账,它的類型是boolean,默認(rèn)值為false捺疼。

recipe.xml.ftl

recipe.xml.ftl稍微有些復(fù)雜疏虫,這里講解以下instantiate、open等幾個(gè)重要參數(shù):

copy:復(fù)制--將from中的文件復(fù)制到to路徑下啤呼,但并不會(huì)將ftl中得變量進(jìn)行轉(zhuǎn)換卧秘,即如果源文件中的類名為${activityClass},復(fù)制過后類名還是${activityClass}轉(zhuǎn)換為我們需要的類名官扣。

merge:合并--將from中的文件合并到to路徑下的文件中翅敌。

instantiate:和copy類似,也是將from中的文件復(fù)制到to路徑下惕蹄,但是它會(huì)將${activityClass}轉(zhuǎn)換為我們需要的類名蚯涮。其實(shí)有這樣一個(gè)過程:ftl->freemarker process -> java

open:代碼生成后卖陵,打開file中指定的文件遭顶。

SimpleActivity.java.ftl

打開SimpleActivity.java.ftl文件,會(huì)發(fā)現(xiàn)和我們創(chuàng)建Activity類后及其類似泪蔫,只是把包名棒旗、類名、布局名等用${...}替換了撩荣,其實(shí)${...}中得內(nèi)容都是id名铣揉,這里不做過多闡述,我們繼續(xù)往下看餐曹。

template.xml

template.xml:打開以后你會(huì)發(fā)現(xiàn)這個(gè)文件好長逛拱,看來是重頭戲了!Lê铩橘券!是的,我們來詳細(xì)解讀一下:

一眼看去是不是和AndroidManifest.xml中得Application節(jié)點(diǎn)中的內(nèi)容結(jié)構(gòu)很相似(包括Application節(jié)點(diǎn))

<?xml version="1.0"?>
<template
    format="5"   # The template format version that this template adheres to. Should be 3
    revision="5" # 可選卿吐,當(dāng)你想更新模板的時(shí)候可以以整數(shù)的形式增加此模板的版本號(hào)
    name="Empty Activity" # 模板顯示的名字
    minApi="7"   # 可選,模板所需的最小API值锋华,IDE將確保在實(shí)例化模板之前嗡官,目標(biāo)工程的minSdkVersion不低于這個(gè)值
    minBuildApi="14"      # 可選,模板所需的最小編譯API毯焕,值為API級(jí)別衍腥,IDE將確保在實(shí)例化模板之前磺樱,項(xiàng)目工程的API等級(jí)大于或等于這個(gè)值
    description="Creates a new empty activity"> # 模板的描述信息

    <category value="Activity" /> # 模板類型,用于在菜單欄File-New下顯示婆咸,如Activity竹捉、AIDL等
    <formfactor value="Mobile" /> # 如同我們在創(chuàng)建module時(shí)所顯示的類型,如:Wear尚骄、TV等块差。

    <parameter
        id="activityClass"   # 唯一標(biāo)示,在ftl文件中可以用${activityClass}獲取參數(shù)值
        name="Activity Name" # 創(chuàng)建模板時(shí)在文本框左邊顯示的該文本框名稱
        type="string"        # 這個(gè)參數(shù)的類型倔丈,如:string, boolean, enum等
        constraints="class|unique|nonempty"       # 可選憨闰,這個(gè)參數(shù)的約束類型,可用|符號(hào)聯(lián)合使用需五,constraints值類型大全請看4.5
        suggest="${layoutToActivity(layoutName)}" # 可選鹉动,自動(dòng)提示,比如輸入layout的值可以自動(dòng)生成activityClass
        default="MainActivity" # 可選宏邮,參數(shù)默認(rèn)值泽示,創(chuàng)建模板時(shí)在文本框中顯示,相當(dāng)于hint
        help="The name of the activity class to create" /> # 創(chuàng)建模板時(shí)蜜氨,選中文本框后械筛,在底部顯示的關(guān)于該文本框的幫助信息

    <!-- 128x128 thumbnails relative to template.xml -->
    <thumbs>
        <!-- default thumbnail is required -->
        <thumb>template_blank_activity.png</thumb> # 可選,用于創(chuàng)建模板時(shí)记劝,在左邊顯示名為template_blank_activity的預(yù)覽圖片
    </thumbs>

    <globals file="globals.xml.ftl" /> # 可選变姨,將工程定義的全局變量包含進(jìn)來
    <execute file="recipe.xml.ftl" />  # 開始執(zhí)行模板渲染

</template>

constraints值類型大全

Valid constraint types are:
    nonempty — the value must not be empty
    apilevel — the value should represent a numeric API level
    package — the value should represent a valid Java package name
    class — the value should represent a valid Java class name
    activity — the value should represent a fully-qualified activity class name
    layout — the value should represent a valid layout resource name
    drawable — the value should represent a valid drawable resource name
    string — the value should represent a valid string resource name
    id — the value should represent a valid id resource name
    unique — the value must be unique; this constraint only makes sense when other constraints are specified, such as layout, which would mean that the value should not represent an existing layout resource name
    exists — the value must already exist; this constraint only makes sense when other constraints are specified, such as layout, which would mean that the value should represent an existing layout resource name

template.xml制作

到這里相信大家對template.xml文件有了一定的了解了,好了厌丑,讓我們來大干一場吧定欧!

MVP版template.xml

既然這里詳細(xì)的講解了template.xml文件,我們先從template.xml文件入手吧怒竿,這里我就不一個(gè)個(gè)細(xì)說了砍鸠,直接上完整代碼:

<?xml version="1.0"?>
<template
    format="2"          # 可修改,此處已修改
    revision="2"        # 可修改耕驰,此處已修改
    name="MVP Activity" # 需要修改
    minApi="7"          # 可修改
    minBuildApi="14"    # 可修改
    description="Creates a new MVP activity"> # 需要修改

    <category value="AAShowJoyMVP" /> # 可修改爷辱,此處已修改
    <formfactor value="Mobile" />     # 一般不修改

    <parameter          # Activity類
        id="activityClass"   # 可修改
        name="Activity Name" # 可修改
        type="string"        # 一般不修改
        constraints="class|unique|nonempty" # 一般不修改
        default="TestActivity" # 可修改,此處已修改
        help="The name of the activity class to create" /> # 可修改朦肘,此處未修改

    <parameter          # Activity類的布局文件
        id="layoutName"
        name="Layout Name"
        type="string"
        constraints="layout|unique|nonempty"
        suggest="${classToResource(activityClass)}_activity" # 可修改饭弓,此處已修改,若不明白可以跳過媒抠,之后會(huì)有詳解5芏稀!趴生!
        default="test_activity"
        help="The name of the layout to create for the activity" />

    <parameter          # 是否作為啟動(dòng)Activity
        id="isLauncher"
        name="Launcher Activity"
        type="boolean"
        default="false" # 默認(rèn)非啟動(dòng)Activity
        help="If true, this activity will have a CATEGORY_LAUNCHER intent filter, making it visible in the launcher" />

    <parameter          # 包名
        id="packageName"
        name="Package name"
        type="string"
        constraints="package"
        default="com.showjoy.shop" />

    <parameter          # viewModel類
        id="viewModelClass"
        name="View Model Name"
        type="string"
        constraints="class|nonempty|unique"
        default="TestViewModel"
        suggest="${underscoreToCamelCase(classToResource(activityClass))}ViewModel" # 此類同布局文件阀趴,之后會(huì)有詳解;韬病!刘急!
        help="The name of the ViewModel to create" />

    <parameter          # presenter類
        id="presenterClass"
        name="Presenter Name"
        type="string"
        constraints="class|nonempty|unique"
        default="TestPresenter"
        suggest="${underscoreToCamelCase(classToResource(activityClass))}Presenter"
        help="The name of the Presenter to create" />

    <parameter          # request類
        id="requestClass"
        name="Request Name"
        type="string"
        constraints="class|nonempty|unique"
        default="TestRequest"
        suggest="${underscoreToCamelCase(classToResource(activityClass))}Request"
        help="The name of the Request to create" />

    <parameter          # entity類
        id="entityClass"
        name="Entity Name"
        type="string"
        constraints="class|nonempty|unique"
        default="TestEntity"
        suggest="${underscoreToCamelCase(classToResource(activityClass))}Entity"
        help="The name of the Entity to create" />


    <globals file="globals.xml.ftl" /> # 一般不修改
    <execute file="recipe.xml.ftl" />  # 一般不修改

</template>

template.xml文件的使用到這里就結(jié)束了棚菊,還是比較簡單的,以下闡述之前所留下的兩個(gè)問題:

(1)

suggest="${classToResource(activityClass)}_activity"

classToResource(activityClass):這句話的意思是叔汁,當(dāng)我們在創(chuàng)建該模板后统求,在activityClass對應(yīng)的文本框中輸入某個(gè)值,比如:test攻柠,它會(huì)直接在layoutName對應(yīng)的文本框中顯示球订,即:test,所以以完整的語句(1)而言瑰钮,此時(shí)layoutName對應(yīng)的文本框中顯示的應(yīng)該是test_activity冒滩。

(2)

suggest="${underscoreToCamelCase(classToResource(activityClass))}ViewModel"

classToResource(activityClass)在(1)中描述的已經(jīng)很清楚了,即為test浪谴,那么underscoreToCamelCase又是什么意思呢开睡?其實(shí)就是將test轉(zhuǎn)換為駝峰命名的方法,即Test苟耻。所以以完整的語句(2)而言篇恒,此時(shí)viewModelClass對應(yīng)的文本框中顯示的應(yīng)該是TestViewModel。

如果你覺得文字描述過于繁瑣凶杖,仍然看不懂的話胁艰,可以查看以下gif:

AndroidStudio自帶模板列表-suggest.gif

MVP版目錄結(jié)構(gòu)

接下來我們就可以把要制作成模板的類,拷貝到相應(yīng)的文件夾中智蝠,此時(shí)的目錄結(jié)構(gòu)為:

MVPActivity
  |----globals.xml.filter
  |----recipe.xml.ftl
  |----activity_layout_recipe.xml.filter # 此文件與recipe類似腾么,只是因?yàn)榻怦钏枷耄詫lass和layout分別引入
  |----root
    |----src
      |----app_package
        |----classes
          |----Activity.java.ftl
          |----Entity.java.ftl
          |----Presenter.java.ftl
          |----Request.java.ftl
          |----ViewModel.java.ftl
        |----layout
          |----activity_layout.xml.ftl
  |----template.xml

Request.java.ftl

為了方便而又全面的進(jìn)行講解杈湾,此處我們以Request.java.ftl文件為例解虱,這里我就直接上全部代碼了:

package ${packageName}.request;                # ${packageName}對應(yīng)的是template.xml文件中id為packageName的參數(shù)設(shè)置的字符串,如果該類不在包名根目錄下漆撞,可以在后面添加相應(yīng)的module名殴泰。

import android.support.annotation.NonNull;     # 如果包名中未涉及到在創(chuàng)建模板時(shí)設(shè)置的包名和類名,則無需修改
import ${packageName}.entities.${entityClass}; # 如果包名中涉及到在創(chuàng)建模板時(shí)設(shè)置的包名和類名浮驳,則只需相對應(yīng)的進(jìn)行修改即可

/**
 * 將以下涉及到在創(chuàng)建模板時(shí)設(shè)置的包名和類名悍汛,進(jìn)行如下相對應(yīng)的替換即可,布局文件也是這樣替換的V粱帷T蹦!
 */
public class ${requestClass} extends SHGetRequest<${entityClass}> {
    @Override
    protected Class<${entityClass}> getDataClass() {
        return ${entityClass}.class;
    }

    @Override
    protected TypeReference<${entityClass}> getDataTypeReference() {
        return null;
    }

    @NonNull
    @Override
    protected String getRequestUrl() {
        return null;
    }
}

布局文件

接下來我們來看一下布局文件的替換:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}">

</RelativeLayout>

雖然說tools命名空間一般都是可有可無的奋献,這里為了全面健霹,也講述以下,你應(yīng)該發(fā)現(xiàn)了一個(gè)從未見過的id:relativePackage瓶蚂,不用迷惑糖埋,估計(jì)你也想到了,其實(shí)我就是在globals.xml.ftl文件中定義了一個(gè)全局變量而已窃这,它的值默認(rèn)為包名瞳别,具體代碼如下:

<global id="relativePackage" type="string" value="${packageName}"/>

globals.xml.ftl

既然說到了globals.xml.ftl文件,我們就去看看好了:

<?xml version="1.0"?>
<globals>
    <global id="hasNoActionBar" type="boolean" value="false" />
    <global id="parentActivityClass" value="" />
    <global id="simpleLayoutName" value="${layoutName}" />
    <global id="excludeMenu" type="boolean" value="true" />
    <global id="generateActivityTitle" type="boolean" value="false" />
    <global id="relativePackage" type="string" value="${packageName}"/>
    <#include "../common/common_globals.xml.ftl" />
</globals>

其實(shí)并沒有什么杭攻,global代表的都是全局變量祟敛,#include代表的是引用的文件,相當(dāng)于繼承兆解。

recipe.xml.ftl

然后就只有recipe.xml.ftl文件了馆铁,也快結(jié)束了:

<?xml version="1.0"?>
<recipe>
    <#include "../common/recipe_manifest.xml.ftl" />

    # 引入同級(jí)目錄中的activity_layout_recipe.xml.ftl文件,其內(nèi)容會(huì)在下一節(jié)中講述
    <#include "activity_layout_recipe.xml.ftl" />

    <instantiate from="src/app_package/classes/Activity.java.ftl"
      to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />

    <instantiate from="src/app_package/classes/ViewModel.java.ftl"
      to="${escapeXmlAttribute(srcOut)}/${viewModelClass}.java" />

    <instantiate from="src/app_package/classes/Entity.java.ftl"
      to="${escapeXmlAttribute(srcOut)}/entities/${entityClass}.java" />

    <instantiate from="src/app_package/classes/Presenter.java.ftl"
      to="${escapeXmlAttribute(srcOut)}/${presenterClass}.java" />

    <instantiate from="src/app_package/classes/Request.java.ftl"
      to="${escapeXmlAttribute(srcOut)}/request/${requestClass}.java" />

    <open file="${escapeXmlAttribute(srcOut)}/${viewModelClass}.java" />

    <open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />

</recipe>

instantiate的作用在上面已經(jīng)講的很清楚了锅睛,簡單來說就是將ftl文件轉(zhuǎn)換為java文件埠巨,而open指的是在創(chuàng)建模板成功后,打開指定的文件现拒,很簡單吧辣垒,這里只有一個(gè)注意點(diǎn):路徑不要寫錯(cuò)了!S∈摺勋桶!

${escapeXmlAttribute(srcOut)}代表的即為包名所代表的路徑
${escapeXmlAttribute(resOut)}代表的是res根目錄

activity_layout_recipe.xml.ftl

之前因?yàn)榻怦钏枷耄园巡季治募膔ecipe文件單獨(dú)處理了侥猬,即為activity_layout_recipe.xml.ftl例驹,打開文件,其實(shí)很簡單:

<recipe>

    <instantiate from="src/app_package/layout/activity_layout.xml.ftl"
                 to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />

</recipe>

這里就不做闡述了陵究,大家看上一節(jié)就明白了眠饮。

模板如何使用

模板創(chuàng)建好之后,我們首先需要的是驗(yàn)證是否能夠正確創(chuàng)建出我們需要的部分铜邮,且沒有錯(cuò)誤發(fā)生仪召,這個(gè)過程其實(shí)就是模板使用的過程,具體可以參考模板使用位置松蒜。

總結(jié)

至此扔茅,Android模板制作已經(jīng)全部完成了,本文篇幅還是比較長的秸苗,如果有什么疑問可以評(píng)論召娜,我會(huì)盡力解決每一個(gè)問題的,謝謝>ァ>寥场秸讹!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市雅倒,隨后出現(xiàn)的幾起案子璃诀,更是在濱河造成了極大的恐慌,老刑警劉巖蔑匣,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劣欢,死亡現(xiàn)場離奇詭異,居然都是意外死亡裁良,警方通過查閱死者的電腦和手機(jī)凿将,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來价脾,“玉大人牧抵,你說我怎么就攤上這事”斯鳎” “怎么了灭忠?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長座硕。 經(jīng)常有香客問我弛作,道長,這世上最難降的妖魔是什么华匾? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任映琳,我火速辦了婚禮,結(jié)果婚禮上蜘拉,老公的妹妹穿的比我還像新娘萨西。我一直安慰自己,他們只是感情好旭旭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布谎脯。 她就那樣靜靜地躺著,像睡著了一般持寄。 火紅的嫁衣襯著肌膚如雪源梭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天稍味,我揣著相機(jī)與錄音废麻,去河邊找鬼。 笑死模庐,一個(gè)胖子當(dāng)著我的面吹牛烛愧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼怜姿,長吁一口氣:“原來是場噩夢啊……” “哼慎冤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起沧卢,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對情侶失蹤粪薛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后搏恤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡湃交,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年熟空,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搞莺。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡息罗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出才沧,到底是詐尸還是另有隱情迈喉,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布温圆,位于F島的核電站挨摸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏岁歉。R本人自食惡果不足惜得运,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锅移。 院中可真熱鬧熔掺,春花似錦、人聲如沸非剃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽备绽。三九已至券坞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疯坤,已是汗流浹背报慕。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留压怠,地道東北人眠冈。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蜗顽。 傳聞我的和親對象是個(gè)殘疾皇子布卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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