[官方文檔]使用注解改進(jìn)代碼檢查

原文地址:https://developer.android.com/studio/write/annotations#thread-annotations

使用代碼檢查工具(例如 Lint)可以幫助您找到問(wèn)題并改進(jìn)代碼,不過(guò)俏站,檢查工具只能推斷這么多信息讯蒲。例如,Android 資源 ID 使用 int 標(biāo)識(shí)字符串肄扎、圖形爱葵、顏色和其他資源類(lèi)型,因此反浓,檢查工具無(wú)法告訴您何時(shí)指定字符串資源以及應(yīng)在什么地方指定顏色萌丈。在這種情況下,您的應(yīng)用可能無(wú)法正確渲染或根本無(wú)法運(yùn)行雷则,即使使用代碼檢查也是如此辆雾。

您可以使用注解向 Lint 之類(lèi)的代碼檢查工具提供提示,幫助檢測(cè)這些更細(xì)微的代碼問(wèn)題月劈。您可以將注解作為元數(shù)據(jù)標(biāo)記附加至變量度迂、參數(shù)和返回值,用于檢查方法返回值猜揪、傳遞的參數(shù)以及本地變量和字段惭墓。如果與代碼檢查工具搭配使用,注解可以幫助您檢測(cè)問(wèn)題而姐,例如 null 指針異常和資源類(lèi)型沖突腊凶。

Android 通過(guò)注解支持庫(kù)支持各種注解。您可以通過(guò) android.support.annotation 軟件包獲取該庫(kù)拴念。

向您的項(xiàng)目添加注解

要在您的項(xiàng)目中啟用注解钧萍,請(qǐng)向您的庫(kù)或應(yīng)用添加 support-annotations 依賴項(xiàng)。添加的任何注解都會(huì)在您隨后運(yùn)行代碼檢查或 lint 任務(wù)時(shí)進(jìn)行檢查政鼠。

添加支持注解庫(kù)依賴項(xiàng)

支持注解庫(kù)是 Android 支持庫(kù)的一部分风瘦。要向您的項(xiàng)目添加注解,您必須下載支持存儲(chǔ)庫(kù)并向 build.gradle 文件中添加 support-annotations 依賴項(xiàng)公般。

  1. 打開(kāi) SDK 管理器万搔,方法是點(diǎn)擊工具欄中的 SDK Manager 或者選擇 Tools > Android > SDK Manager
  2. 點(diǎn)擊 SDK Tools 標(biāo)簽官帘。
  3. 展開(kāi) Support Repository 并選中 Android Support Repository 復(fù)選框瞬雹。
  4. 點(diǎn)擊 OK
  5. 繼續(xù)安裝向?qū)У恼f(shuō)明操作遏佣,安裝軟件包挖炬。
  6. 將以下代碼行添加到 build.gradle 文件的 dependencies 塊中,向您的項(xiàng)目添加 support-annotations 依賴項(xiàng):
dependencies { compile 'com.android.support:support-annotations:24.2.0' } 

您下載的庫(kù)版本可能較高,因此意敛,確保您在此指定的值與第 3 步中的版本匹配馅巷。

  1. 在顯示的工具欄或同步通知中,點(diǎn)擊 Sync Now草姻。

如果您在自己的庫(kù)模塊中使用注解钓猬,注解將作為 Android 歸檔 (AAR) 工件的一部分以 XML 格式添加到 annotations.zip文件中。添加 support-annotations 依賴項(xiàng)不會(huì)為您的庫(kù)的任何下游用戶引入依賴關(guān)系撩独。

如果想要在未使用適用于 Gradle 的 Android 插件但使用 Gradle Java 插件的 Gradle 模塊中使用注解(com.android.applicationcom.android.library)敞曹,您必須明確添加 SDK 存儲(chǔ)庫(kù),因?yàn)闊o(wú)法從 JCenter Java 存儲(chǔ)庫(kù)獲得 Android 支持庫(kù):

repositories {
   jcenter()
   maven { url '<your-SDK-path>/extras/android/m2repository' }
}

:如果您使用 appcompat 庫(kù)综膀,則無(wú)需添加 support-annotations 依賴項(xiàng)澳迫。因?yàn)?appcompat 庫(kù)已經(jīng)依賴注解庫(kù),您可以訪問(wèn)相關(guān)注解剧劝。

要查看支持存儲(chǔ)庫(kù)中包含的完整注解列表橄登,請(qǐng)查看支持注解庫(kù)參考,或者使用自動(dòng)填充功能顯示 import android.support.annotation. 語(yǔ)句的可用選項(xiàng)讥此。

運(yùn)行代碼檢查

要從 Android Studio 啟動(dòng)代碼檢查(包含驗(yàn)證注解和自動(dòng) Lint 檢查)拢锹,請(qǐng)從菜單欄中選擇 Analyze > Inspect Code。Android Studio 將顯示沖突消息萄喳,在您的代碼與注解沖突的地方標(biāo)記潛在問(wèn)題并建議可能的解決方法卒稳。

您還可以通過(guò)使用命令行運(yùn)行 lint 任務(wù)來(lái)強(qiáng)制注解。盡管這對(duì)標(biāo)記持續(xù)集成服務(wù)器遇到的問(wèn)題可能有用他巨,請(qǐng)注意充坑,lint 任務(wù)并不會(huì)強(qiáng)制 nullness 注解(只有 Android Studio 會(huì)強(qiáng)制)。如需了解有關(guān)啟用和運(yùn)行 Lint 檢查的詳細(xì)信息闻蛀,請(qǐng)參閱使用 Lint 改進(jìn)您的代碼匪傍。

請(qǐng)注意您市,盡管注解沖突會(huì)生成警告觉痛,但這些警告不會(huì)阻止您的應(yīng)用編譯。

Nullness 注解

添加 @Nullable@NonNull注解茵休,以檢查給定變量薪棒、參數(shù)或返回值的 nullness。@Nullable 注解指示可以為 null 的變量榕莺、參數(shù)或返回值俐芯,而 @NonNull 則指示不可為 null 的變量、參數(shù)或返回值钉鸯。

例如吧史,如果一個(gè)包含 null 值的局部變量作為已附加 @NonNull 注解的參數(shù)傳遞到某個(gè)方法,則構(gòu)建代碼將生成一個(gè)指示非 null 沖突的警告唠雕。另一方面贸营,對(duì)于通過(guò) @Nullable 標(biāo)記的方法的結(jié)果吨述,如果不先檢查其是否為 null,那么在嘗試引用它時(shí)將生成 nullness 警告钞脂。只有在每次使用方法時(shí)都應(yīng)明確檢查是否為 null 的情況下揣云,才應(yīng)對(duì)方法返回值使用 @Nullable

下面的示例會(huì)將 @NonNull 注解附加到 contextattrs 參數(shù)冰啃,以檢查傳遞的參數(shù)值是否不為 null邓夕。它還會(huì)檢查 onCreateView() 方法本身是否不會(huì)返回 null:

import android.support.annotation.NonNull;
...

    /** Add support for inflating the <fragment> tag. **/
    @NonNull
    @Override
    public View onCreateView(String name, @NonNull Context context,
      @NonNull AttributeSet attrs) {
      ...
      }
...

Nullability 分析

Android Studio 支持通過(guò)運(yùn)行 nullability 分析,在您的代碼中自動(dòng)推斷和插入 nullness 注解阎毅。Nullability 分析會(huì)在您代碼的整個(gè)方法層次結(jié)構(gòu)中掃描協(xié)定類(lèi)焚刚,以檢測(cè):

  • 可返回 Null 的調(diào)用方法
  • 不會(huì)返回 Null 的方法
  • 可以為 Null 的變量,如字段扇调、局部變量和參數(shù)
  • 不能為 Null 值的變量汪榔,如字段、局部變量和參數(shù)

然后肃拜,此分析將自動(dòng)在已檢測(cè)到的位置插入相應(yīng)的 null 注解痴腌。

要在 Android Studio 中運(yùn)行 nullability 分析,請(qǐng)選擇 Analyze > Infer Nullity燃领。Android Studio 會(huì)在代碼中已檢測(cè)到的位置插入 Android @Nullable@NonNull 注解士聪。運(yùn)行 null 分析后,最好驗(yàn)證一下插入的這些注解猛蔽。

:添加 nullness 注解時(shí)剥悟,自動(dòng)填充可能會(huì)建議 IntelliJ @Nullable@NotNull 注解而不是 Android null 注解,并且可能會(huì)自動(dòng)導(dǎo)入相應(yīng)的庫(kù)曼库。不過(guò)区岗,Android Studio Lint 檢查器僅會(huì)查找 Android null 注解。驗(yàn)證您的注解時(shí)毁枯,請(qǐng)確認(rèn)您的項(xiàng)目使用 Android null 注解慈缔,以便 Lint 檢查器可以在代碼檢查期間正確通知您。

資源注解

驗(yàn)證資源類(lèi)型可能非常有用种玛,因?yàn)?Android 對(duì)資源(例如可繪制對(duì)象字符串資源)的引用以整型形式傳遞藐鹤。需要參數(shù)來(lái)引用特定類(lèi)型資源(例如可繪制對(duì)象)的代碼可以作為預(yù)計(jì)的引用類(lèi)型 int 傳入,不過(guò)實(shí)際將引用不同類(lèi)型的資源赂韵,例如 R.string 資源娱节。

例如,添加 @StringRes注解祭示,以檢查資源參數(shù)是否包含 R.string 引用肄满,如下面所示:

public abstract void setTitle(@StringRes int resId) { … }

在代碼檢查期間,如果參數(shù)中未傳入 R.string 引用,注解將生成警告稠歉。

其他資源類(lèi)型的注解(例如 @DrawableRes讥电、@DimenRes@ColorRes@InterpolatorRes)可以使用相同的注解格式添加并在代碼檢查期間運(yùn)行轧抗。如果您的參數(shù)支持多種資源類(lèi)型恩敌,您可以在給定參數(shù)上添加更多注解。使用 @AnyRes能夠指示注解的參數(shù)可為任意類(lèi)型的 R 資源横媚。

盡管您可以使用 @ColorRes 指定某個(gè)參數(shù)應(yīng)為顏色資源纠炮,但是顏色整型(RRGGBBAARRGGBB 格式)無(wú)法識(shí)別為顏色資源。請(qǐng)改用 @ColorInt 注解指示某個(gè)參數(shù)必須為顏色整型灯蝴。構(gòu)建工具會(huì)標(biāo)記不正確代碼恢口,該代碼會(huì)將顏色資源 ID(例如 android.R.color.black)而不是顏色整型傳遞到已注解方法。

線程注解

線程注解可以檢查某個(gè)方法是否從特定類(lèi)型的線程調(diào)用穷躁。支持以下線程注解:

:構(gòu)建工具會(huì)將 @MainThread@UiThread 注解視為可互換耕肩,因此,您可以從 @MainThread 方法調(diào)用 @UiThread 方法问潭,反之亦然猿诸。不過(guò),如果系統(tǒng)應(yīng)用在不同線程上帶有多個(gè)視圖狡忙,UI 線程可與主線程不同梳虽。因此,您應(yīng)使用 @UiThread 標(biāo)注與應(yīng)用的視圖層次結(jié)構(gòu)關(guān)聯(lián)的方法灾茁,使用 @MainThread 僅標(biāo)注與應(yīng)用生命周期關(guān)聯(lián)的方法窜觉。

如果某個(gè)類(lèi)中的所有方法具有相同的線程要求,您可以向該類(lèi)添加一個(gè)線程注解北专,以驗(yàn)證該類(lèi)中的所有方法是否均從相同類(lèi)型的線程調(diào)用禀挫。

線程注解的一個(gè)常見(jiàn)用途是驗(yàn)證 AsyncTask 類(lèi)中的方法替換,因?yàn)榇祟?lèi)會(huì)執(zhí)行后臺(tái)操作并將結(jié)果僅發(fā)布到 UI 線程上拓颓。

筆記:一般情況下语婴,安卓系統(tǒng)內(nèi)的一般應(yīng)用中,MainThread和UiThread是一樣的录粱。@MainThread和@UiThread的注解可以相互替換腻格。在特殊情況下,如個(gè)別系統(tǒng)應(yīng)用可能存在MainThread和UiThread不一致的場(chǎng)景啥繁,參考https://stackoverflow.com/questions/40784584/difference-between-the-main-thread-and-ui-thread

值約束注解

使用 @IntRange@FloatRange@Size 注解可以驗(yàn)證傳遞的參數(shù)的值青抛。在應(yīng)用到用戶可能弄錯(cuò)其范圍的參數(shù)時(shí)旗闽,@IntRange@FloatRange 都非常有用。

@IntRange 注解可以驗(yàn)證整型或長(zhǎng)整型參數(shù)值是否位于指定范圍內(nèi)。下面的示例可以確保 alpha 參數(shù)包含 0 至 255 范圍內(nèi)的整數(shù)值:

public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }

@FloatRange 注解可以檢查浮點(diǎn)或雙整型參數(shù)值是否位于指定的浮點(diǎn)值范圍內(nèi)适室。下面的示例可以確保 alpha 參數(shù)包含 0.0 至 1.0 的浮點(diǎn)值:

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}

@Size 注解可以檢查集合或數(shù)組的大小嫡意,以及字符串的長(zhǎng)度。@Size 注解可用于驗(yàn)證以下質(zhì)量:

  • 最小大械妨尽(例如 @Size(min=2))
  • 最大大惺呙(例如 @Size(max=2))
  • 確切大小(例如 @Size(2))
  • 表示大小必須為此倍數(shù)的數(shù)字(例如 @Size(multiple=2))

例如汽畴,@Size(min=1) 可以檢查某個(gè)集合是否不為空旧巾,@Size(3) 可以驗(yàn)證某個(gè)數(shù)組是否剛好包含三個(gè)值。下面的示例可以確保 location 數(shù)組至少包含一個(gè)元素:

int[] location = new int[3];
button.getLocationOnScreen(@Size(min=1) location);

權(quán)限注解

使用 @RequiresPermission 注解可以驗(yàn)證方法調(diào)用方的權(quán)限忍些。要檢查有效權(quán)限列表中是否存在某個(gè)權(quán)限鲁猩,請(qǐng)使用 anyOf 屬性。要檢查是否存在一組權(quán)限罢坝,請(qǐng)使用 allOf 屬性廓握。下面的示例會(huì)標(biāo)注 setWallpaper() 方法,以確保方法的調(diào)用方擁有 permission.SET_WALLPAPERS 權(quán)限:

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;

此示例要求 copyFile() 方法的調(diào)用方同時(shí)具有外部存儲(chǔ)空間的讀寫(xiě)權(quán)限:

@RequiresPermission(allOf = {
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) {
    ...
}

對(duì)于 intent 權(quán)限嘁酿,請(qǐng)將權(quán)限要求添加到定義 intent 操作名稱的字符串字段上:

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
            "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";

對(duì)于您需要單獨(dú)讀寫(xiě)權(quán)限的內(nèi)容提供程序的權(quán)限隙券,請(qǐng)?jiān)?@RequiresPermission.Read @RequiresPermission.Write注解中包含每個(gè)權(quán)限要求:

@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

間接權(quán)限

如果權(quán)限依賴于提供給方法參數(shù)的特定值,請(qǐng)對(duì)參數(shù)本身使用 @RequiresPermission闹司,而不用列出具體權(quán)限是尔。例如,startActivity(Intent) 方法會(huì)對(duì)傳遞到方法的 intent 使用間接權(quán)限:

public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle) {...}

在您使用間接權(quán)限時(shí)开仰,構(gòu)建工具將執(zhí)行數(shù)據(jù)流分析以檢查傳遞到方法的參數(shù)是否具有任何 @RequiresPermission 注解拟枚。隨后,它們會(huì)對(duì)方法本身強(qiáng)制參數(shù)的任何現(xiàn)有注解众弓。在 startActivity(Intent) 示例中恩溅,當(dāng)一個(gè)不具有相應(yīng)權(quán)限的 intent 傳遞到方法時(shí),Intent類(lèi)中的注解會(huì)針對(duì) startActivity(Intent) 的無(wú)效使用生成警告谓娃,如圖 1 中所示脚乡。

圖 1. startActivity(Intent) 方法上從間接權(quán)限注解生成的警告。

構(gòu)建工具會(huì)在 startActivity(Intent) 上從 [Intent](https://developer.android.com/reference/android/content/Intent.html) 類(lèi)中相應(yīng) intent 操作名稱的注解生成警告:

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";

如果需要滨达,在標(biāo)注方法的參數(shù)時(shí)奶稠,您可以將 @RequiresPermission 替換為 @RequiresPermission.Read 和/或 @RequiresPermission.Write。不過(guò)捡遍,間接權(quán)限 @RequiresPermission 不應(yīng)與讀取或?qū)懭霗?quán)限注解搭配使用锌订。

返回值注解

使用 @CheckResult 注解可以驗(yàn)證實(shí)際使用的是方法的結(jié)果還是返回值。添加注釋來(lái)闡明可能令人困惑的方法的結(jié)果画株,而不是使用 @CheckResult 標(biāo)注每個(gè)非空方法辆飘。例如啦辐,新 Java 開(kāi)發(fā)者經(jīng)常誤認(rèn)為 <*String*>.trim() 會(huì)移除原始字符串中的空格。使用 @CheckResult 標(biāo)注方法會(huì)在調(diào)用方未對(duì)方法返回值作任何處理的地方標(biāo)記 <*String*>.trim() 的使用蜈项。

下面的示例會(huì)標(biāo)注 checkPermissions()方法芹关,以確保實(shí)際引用方法的返回值。它還會(huì)將 enforcePermission() 方法指定為要向開(kāi)發(fā)者建議的替換方法:

@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);

CallSuper 注解

使用 @CallSuper注解可以驗(yàn)證替換方法是否會(huì)調(diào)用方法的超類(lèi)實(shí)現(xiàn)紧卒。下面的示例會(huì)標(biāo)注 onCreate() 方法侥衬,以確保任何替換方法實(shí)現(xiàn)都會(huì)調(diào)用 super.onCreate()

@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

Typedef 注解

使用 @IntDef@StringDef注解,以便能夠創(chuàng)建整型和字符串集的枚舉注解來(lái)驗(yàn)證其他類(lèi)型的代碼引用跑芳。Typedef 注解可以確保特定參數(shù)轴总、返回值或字段引用特定的常量集。它們還可以完成代碼以自動(dòng)提供允許的常量聋亡。

Typedef 注解使用 @interface 聲明新的枚舉注解類(lèi)型肘习。@IntDef@StringDef 注解以及 @Retention 可以標(biāo)注新注解,并且為定義枚舉的類(lèi)型所必需坡倔。@Retention(RetentionPolicy.SOURCE) 注解可以告知編譯器不將枚舉的注解數(shù)據(jù)存儲(chǔ)在 .class 文件中漂佩。

下面的示例說(shuō)明了創(chuàng)建注解的具體步驟,此注解可以確保作為方法參數(shù)傳遞的值引用一個(gè)定義的常量:

import android.support.annotation.IntDef;
...
public abstract class ActionBar {
    ...
    // Define the list of accepted constants and declare the NavigationMode annotation
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
    public @interface NavigationMode {}

    // Declare the constants
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

    // Decorate the target methods with the annotation
    @NavigationMode
    public abstract int getNavigationMode();

    // Attach the annotation
    public abstract void setNavigationMode(@NavigationMode int mode);

在您構(gòu)建此代碼時(shí)罪塔,如果 mode 參數(shù)不引用一個(gè)定義的常量(NAVIGATION_MODE_STANDARD投蝉、NAVIGATION_MODE_LISTNAVIGATION_MODE_TABS),則會(huì)生成警告征堪。

筆記:IntDef還可以直接在注解中定義常量瘩缆。寫(xiě)法參考http://blog.shamanland.com/2016/02/int-string-enum.html

您還可以組合 @IntDef@IntRange,以指示整型可以是給定的常量集或某個(gè)范圍內(nèi)的值佃蚜。

允許將常量與標(biāo)志相結(jié)合

如果用戶可以將允許的常量與標(biāo)志(例如庸娱,|、& 和 ^谐算,等等)相結(jié)合熟尉,則您可以通過(guò) flag 屬性定義一個(gè)注解,以檢查某個(gè)參數(shù)或返回值是否會(huì)引用有效模式洲脂。下面的示例將使用一組有效的 DISPLAY_ 常量創(chuàng)建 DisplayOptions 注解:

import android.support.annotation.IntDef;
...

@IntDef(flag=true, value={
        DISPLAY_USE_LOGO,
        DISPLAY_SHOW_HOME,
        DISPLAY_HOME_AS_UP,
        DISPLAY_SHOW_TITLE,
        DISPLAY_SHOW_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayOptions {}

...

在您使用注解標(biāo)志構(gòu)建代碼時(shí)斤儿,如果經(jīng)過(guò)修飾的參數(shù)或返回值不引用有效模式,則將生成警告恐锦。

代碼可訪問(wèn)性注解

使用 @VisibleForTesting@Keep 注解可以表示方法往果、類(lèi)或字段的可訪問(wèn)性。

@VisibleForTesting 注解指示一個(gè)代碼塊的可見(jiàn)性是否高于讓代碼變得可測(cè)試所需要的水平一铅。

@Keep 注解可以確保如果在構(gòu)建時(shí)縮減代碼陕贮,標(biāo)注的元素不會(huì)移除。它一般會(huì)添加到通過(guò)反射訪問(wèn)的方法和類(lèi)中馅闽,以阻止編譯器將代碼視為未使用飘蚯。

筆記:多用注解來(lái)提高代碼的規(guī)范性和可讀性馍迄。

參考文檔:
https://stackoverflow.com/questions/40784584/difference-between-the-main-thread-and-ui-thread

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末福也,一起剝皮案震驚了整個(gè)濱河市局骤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌暴凑,老刑警劉巖峦甩,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異现喳,居然都是意外死亡凯傲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)嗦篱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)冰单,“玉大人,你說(shuō)我怎么就攤上這事灸促〗肭罚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵浴栽,是天一觀的道長(zhǎng)荒叼。 經(jīng)常有香客問(wèn)我,道長(zhǎng)典鸡,這世上最難降的妖魔是什么被廓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮萝玷,結(jié)果婚禮上嫁乘,老公的妹妹穿的比我還像新娘。我一直安慰自己球碉,他們只是感情好蜓斧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著汁尺,像睡著了一般法精。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上痴突,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天搂蜓,我揣著相機(jī)與錄音,去河邊找鬼辽装。 笑死帮碰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拾积。 我是一名探鬼主播殉挽,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼丰涉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了斯碌?” 一聲冷哼從身側(cè)響起一死,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎傻唾,沒(méi)想到半個(gè)月后投慈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冠骄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年伪煤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凛辣。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抱既,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扁誓,到底是詐尸還是另有隱情防泵,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布跋理,位于F島的核電站择克,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏前普。R本人自食惡果不足惜肚邢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拭卿。 院中可真熱鬧骡湖,春花似錦、人聲如沸峻厚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惠桃。三九已至浦夷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辜王,已是汗流浹背劈狐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呐馆,地道東北人肥缔。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像汹来,于是被迫代替她去往敵國(guó)和親续膳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子改艇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355