代碼潔癖癥的我涕俗,學(xué)習(xí)Lint學(xué)到心態(tài)爆炸

前言

以前對下面的問題罗丰,我的態(tài)度是,不報錯就是沒問題再姑,報錯就用快捷鍵萌抵,根據(jù)Android Studio提示修復(fù)問題,從來不去問個為什么元镀?現(xiàn)在代碼潔癖癥越來越嚴重的我绍填,忍不住想看搞清什么東西在·搞·鬼·。

認真看完本文栖疑,一定可以學(xué)到最新的知識讨永。就算看不下去,也要點個贊收藏遇革,絕對不虧卿闹。

不知道大家有沒有注意項目中·黃·色·代碼塊的提示揭糕,如下圖所示:


image

或者紅色標(biāo)記的代碼(并沒有任何錯誤),如下圖所示:

image

上文黃色的提醒和紅色警告锻霎,都是來自Android Studio內(nèi)置的Lint工具檢查我們的代碼后而作出的動作著角。
通過配置Lint,也可以消除上面的提醒。例如旋恼,我開發(fā)系統(tǒng)APK,根本不需要考慮用戶是否授權(quán)吏口。
那么Lint是什么呢?

Lint

Android Studio 提供一個名為Lint的靜態(tài)代碼掃描工具蚌铜,可以發(fā)現(xiàn)并糾正代碼結(jié)構(gòu)中的質(zhì)量問題锨侯,而無需實際執(zhí)行該應(yīng)用嫩海,也不必編寫測試用例冬殃。
Lint 工具可檢查您的 Android 項目源文件是否包含潛在錯誤,以及在正確性叁怪、安全性审葬、性能、易用性奕谭、便利性和國際化方面是否需要優(yōu)化改進涣觉。

也就是說,通過Lint工具血柳,我們可以寫出更高質(zhì)量的代碼和代碼潛在的問題官册,媽媽再也不用擔(dān)心我的同事用中文命名了。也可以通過定制Lint相關(guān)配置难捌,提高開發(fā)效率膝宁。

Lint禁止檢查

由于Android Studio內(nèi)置了Lint工具,好像不需要我們干嘛根吁≡币可是呀,我有強迫癥击敌,看著上面的黃色塊介返,超級不爽的。所以我們得了解如何配置Lint沃斤,讓它為我們服務(wù)圣蝎,而不是為Google服務(wù)。

本文開始的紅色錯誤可以通過注解來消除(一般建議是根據(jù)提示進行修正衡瓶,除非明白自己在做什么)徘公,可以在類或該代碼所在的方法添加@SuppressLint

image

上圖中是禁止Lint檢查特定的問題檢查鞍陨,如果要禁止該Java文件所有的Lint問題步淹,可以在類前添加如下注解:@SuppressLint(all)从隆。
對XMl文件的禁止,則可以采用如下形式:

  1. 在lint.xml聲明命名空間
namespace xmlns:tools="http://schemas.android.com/tools"
  1. 在布局中使用:
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:ignore="UnusedResources" >

    <TextView
        android:text="@string/auto_update_prompt" />
</LinearLayout>

父容器聲明了ignore屬性缭裆,那么子視圖會繼承該屬性键闺。例如上文LinearLayout中聲明了禁止Lint檢查LinearLayout的UnusedResources問題,TextView自然也禁止檢查該問題澈驼。禁止檢查多個問題辛燥,問題之間用逗號隔開;禁止檢查所有問題則使用all關(guān)鍵字缝其。

tools:ignore="all"

我們也可以通過配置項目的Gradle文件來禁止檢查挎塌。

例如禁止Lint檢查項目AndroidManifest.xml文件的GoogleAppIndexingWarning問題。在項目對應(yīng)組件工程的Gradle文件添加如下配置,這樣就不會有黃色提醒了内边。

defaultConfig{
    lintOptions {
        disable 'GoogleAppIndexingWarning'
    }
}

那么榴都,可以禁止lint工具檢查什么問題?

配置Lint

在上文中通過注解和在xml使用屬性來禁止Lint工具檢查相關(guān)問題,其實已經(jīng)是對Lint的配置了漠其。Lint將多個問題歸為一個issue(規(guī)則)嘴高,例如下圖右邊的的六大規(guī)則。

image

上圖是Lint工具的工作流程和屎,下面了解相關(guān)概念拴驮。
App Source Files
源文件包含組成 Android 項目的文件,包括 Java 和 XML 文件柴信、圖標(biāo)和 ProGuard 配置文件等套啤。
lint.xml 文件
此配置文件可用于指定您希望排除的任何 Lint 檢查以及自定義問題嚴重級別。
lint Tool
我們可以通過Android Studio 對 Android 項目運行此靜態(tài)代碼掃描工具随常。也可以手動運行潜沦。Lint 工具檢查可能影響 Android 應(yīng)用質(zhì)量和性能的代碼結(jié)構(gòu)問題。
Lint 檢查結(jié)果
我們可以在控制臺(命令行運行)或 Android Studio 的 Inspection Results 窗口中查看 Lint 檢查結(jié)果线罕。

通過Lint工具的工作流程了解到止潮,可以在lint.xml文件配置一些信息。一般新建項目都是沒有l(wèi)int.xml文件的钞楼,在項目的根目錄創(chuàng)建lint.xml文件喇闸。格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<lint>
        <!-- list of issues to configure -->
</lint>

那么有哪些Issues(規(guī)則)呢?

在Android主要有如下六大類:

  • Security 安全性询件。在AndroidManifest.xml中沒有配置相關(guān)權(quán)限等燃乍。
  • Usability 易用性。重復(fù)圖標(biāo)宛琅;上文開始黃色警告也屬于該規(guī)則等刻蟹。
  • Performance 性能。內(nèi)存泄漏嘿辟,xml結(jié)構(gòu)冗余等舆瘪。
  • Correctness 正確性片效。超版本調(diào)用API,設(shè)置不正確的屬性值等英古。
  • Accessibility 無障礙淀衣。單詞拼寫錯誤等。
  • Internationalization國際化召调。字符串缺少翻譯等膨桥。

其他更多Issues,可以通將命令行切換到../Android/sdk/tools/bin目錄下,然后輸入lint --list唠叛。例如在Mac下:
cd /Users/gitcode8/Library/Android/sdk/tools/bin輸入./lint --list
結(jié)果如下:

image

例如官網(wǎng)提供的參考例子:

<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <!-- 忽略整個工程目錄下指定問題的檢查 -->
    <issue id="IconMissingDensityFolder" severity="ignore" />

    <!-- 忽略對指定文件指定問題的檢查 -->
    <issue id="ObsoleteLayoutParam">
        <ignore path="res/layout/activation.xml" />
        <ignore path="res/layout-xlarge/activation.xml" />
    </issue>

    <!-- 更改檢查問題歸屬的嚴重性  -->
    <issue id="HardcodedText" severity="error" />
</lint>

學(xué)習(xí)Lint工具僅僅是為了安撫我的強迫癥只嚣?不,還不知道Lint真正用來干嘛呢艺沼?

檢查項目質(zhì)量

不好容易開發(fā)了個APP,準(zhǔn)備開始上班摸魚了册舞。還讓代碼自查?那就通過Lint來看看代碼質(zhì)量如何吧澳厢。

1环础、Android Studio 檢查

  1. 通過Android Studio 的菜單欄Analyze選項下拉選擇第一個選項Inspect Code.
image

2囚似、在彈出框根據(jù)自己需要選擇lint工具的檢查范圍剩拢,這里選擇整個項目。檢查時間也是根據(jù)項目大小來定的饶唤。

image

3徐伐、等待一段時間后,會列出檢查結(jié)果募狂。從下圖看到办素,不僅會檢查Android存在的問題,也會檢查Java等其他問題祸穷。通過單擊問題性穿,可以從右邊提示框看到問題發(fā)生的地方和相關(guān)建議。

image

到這里雷滚,就開始對項目修修補補吧需曾。

自定義規(guī)則

為什么要自定義呢?已有規(guī)則不符合自己或團隊開發(fā)需求祈远,或者覺得Lint存在一些缺陷呆万。在網(wǎng)上大多數(shù)文章千篇一律,都是通過將Log打印來舉例车份,看著都好累哦谋减。由于沒有相關(guān)官方文檔和第三方教程(可能由于lint的api更新太快,沒人愿意做這種吃力不討好的工作)扫沼,也這就只有這樣了出爹。本文通過自定義命名規(guī)范規(guī)則來講解整個過程庄吼。

Lint中重點的API

先學(xué)習(xí)相關(guān)api,可以快速理解一些概念严就,可以粗略看過霸褒,下結(jié)實踐再回來看。

1盈蛮、Issue

Issue如上文所說废菱,表示lint 工具檢查的一個規(guī)則,一個規(guī)則包含若干問題抖誉。常在Detector中創(chuàng)建殊轴。下文是創(chuàng)建一個Issue的例子。

   private  static final Issue ISSUE = Issue.create("NamingConventionWarning",
            "命名規(guī)范錯誤",
            "使用駝峰命名法袒炉,方法命名開頭小寫旁理,類大寫字母開頭",
            Category.USABILITY,
            5,
            Severity.WARNING,
            new Implementation(NamingConventionDetecor.class,
                    EnumSet.of(Scope.JAVA_FILE)));
  • 第一個參數(shù)id 唯一的id,簡要表面當(dāng)前提示的問題。
  • 第二個參數(shù)briefDescription 簡單描述當(dāng)前問題
  • 第三個參數(shù)explanation 詳細解釋當(dāng)前問題和修復(fù)建議
  • 第四個參數(shù)category 問題類別我磁,例如上文講到的Security孽文、Usability等等。
  • 第五個參數(shù)priority 優(yōu)先級夺艰,從1到10芋哭,10最重要
  • 第六個參數(shù)Severity 嚴重程度:FATAL(奔潰), ERROR(錯誤), WARNING(警告),INFORMATIONAL(信息性),IGNORE(可忽略)
  • 第七個參數(shù)Implementation Issue和哪個Detector綁定,以及聲明檢查的范圍郁副。Scope有如下選擇范圍:
    RESOURCE_FILE(資源文件),BINARY_RESOURCE_FILE(二進制資源文件),RESOURCE_FOLDER(資源文件夾),ALL_RESOURCE_FILES(所有資源文件),JAVA_FILE(Java文件), ALL_JAVA_FILES(所有Java文件),CLASS_FILE(class文件), ALL_CLASS_FILES(所有class文件),MANIFEST(配置清單文件), PROGUARD_FILE(混淆文件),JAVA_LIBRARIES(Java庫), GRADLE_FILE(Gradle文件),PROPERTY_FILE(屬性文件),TEST_SOURCES(測試資源),OTHER(其他);

這樣就能很清楚的定義一個規(guī)則减牺,上文只定義了檢查命名規(guī)范的規(guī)則。

2存谎、IssueRegistry

用于注冊要檢查的Issue(規(guī)則)拔疚,只有注冊了Issue,該Issue才能被使用。例如注冊上文的命名規(guī)范規(guī)則既荚。

public class Register extends IssueRegistry {
    @NotNull
    @Override
    public List<Issue> getIssues() {
        return Arrays.asList(NamingConventionDetector.ISSUE);
    }
}

4稚失、Detector

查找指定的Issue,一個Issue對應(yīng)一個Detector恰聘。自定義Lint 規(guī)則的過程也就是重寫Detector類相關(guān)方法的過程句各。具體看下小結(jié)實踐。

5憨琳、Scanner

掃描并發(fā)現(xiàn)代碼中的Issue,Detector需要實現(xiàn)Scaner,可以繼承一個到多個诫钓。

  • UastScanner 掃描Java文件和Kotlin文件
  • ClassScanner 掃描Class文件
  • XmlScanner 掃描Xml文件
  • ResourceFolderScanner 掃描資源文件夾
  • BinaryResourceScanner 掃描二進制資源文件
  • OtherFileScanner 掃描其他文件
  • GradleScanner 掃描Gradle腳本

舊版本的JavaScanner、JavaPsiScanner隨著版本的更新已經(jīng)被UastScanner替代了篙螟。

自定義Lint規(guī)則實踐

通過實現(xiàn)命名規(guī)范Issue來熟悉和運用上小節(jié)相關(guān)的api菌湃。自定義規(guī)則需要在Java工程中創(chuàng)建,這里通過Android Studio來創(chuàng)建一個Java Library遍略。

步驟:File->New->New Mudle->Java Library

這里L(fēng)ibrary Name為lib惧所。

定義類NamingConventionDetector,并繼承自Detector骤坐。因為這里是檢測Java文件類名和方法是否符合規(guī)則,所以實現(xiàn)Detector.UastScanner接口下愈。

public class NamingConventionDetector 
    extends Detector 
    implements Detector.UastScanner {
}

在NamingConventionDetector類內(nèi)定義上文的Issue:

public class NamingConventionDetector 
    extends Detector 
    implements Detector.UastScanner {
    
    public static final Issue ISSUE = Issue.create("NamingConventionWarning",
        "命名規(guī)范錯誤",
        "使用駝峰命名法纽绍,方法命名開頭小寫",
        Category.USABILITY,
        5,
        Severity.WARNING,
        new Implementation(NamingConventionDetector.class,
            EnumSet.of(Scope.JAVA_FILE)));
}

重寫Detector的createUastHandler方法,實現(xiàn)我們自己的處理類势似。

public class NamingConventionDetector extends Detector implements Detector.UastScanner {
    //定義命名規(guī)范規(guī)則
    public static final Issue ISSUE = Issue.create("NamingConventionWarning",
            "命名規(guī)范錯誤",
            "使用駝峰命名法拌夏,方法命名開頭小寫",
            Category.USABILITY,
            5,
            Severity.WARNING,
            new Implementation(NamingConventionDetector.class,
                    EnumSet.of(Scope.JAVA_FILE)));

    //返回我們所有感興趣的類,即返回的類都被會檢查
    @Nullable
    @Override
    public List<Class<? extends UElement>> getApplicableUastTypes() {
        return Collections.<Class<? extends UElement>>singletonList(UClass.class);
    }

    //重寫該方法履因,創(chuàng)建自己的處理器
    @Nullable
    @Override
    public UElementHandler createUastHandler(@NotNull final JavaContext context) {
        return new UElementHandler() {
            @Override
            public void visitClass(@NotNull UClass node) {
                node.accept(new NamingConventionVisitor(context, node));
            }
        };
    }
    //定義一個繼承自AbstractUastVisitor的訪問器障簿,用來處理感興趣的問題
    public static class NamingConventionVisitor extends AbstractUastVisitor {

        JavaContext context;

        UClass uClass;

        public NamingConventionVisitor(JavaContext context, UClass uClass) {
            this.context = context;
            this.uClass = uClass;
        }

        @Override
        public boolean visitClass(@org.jetbrains.annotations.NotNull UClass node) {
            //獲取當(dāng)前類名
            char beginChar = node.getName().charAt(0);
            int code = beginChar;
            //如果類名不是大寫字母,則觸碰Issue栅迄,lint工具提示問題
            if (97 < code && code < 122) {
                context.report(ISSUE,context.getNameLocation(node),
                        "the  name of class must start with uppercase:" + node.getName());
                //返回true表示觸碰規(guī)則站故,lint提示該問題;false則不觸碰
                return true;
            }

            return super.visitClass(node);
        }

        @Override
        public boolean visitMethod(@NotNull UMethod node) {
            //當(dāng)前方法不是構(gòu)造方法
            if (!node.isConstructor()) {
            char beginChar = node.getName().charAt(0);
            int code = beginChar;
                //當(dāng)前方法首字母是大寫字母毅舆,則報Issue
                if (65 < code && code < 90) {
                    context.report(ISSUE, context.getLocation(node),
                            "the method must start with lowercase:" + node.getName());
                    //返回true表示觸碰規(guī)則西篓,lint提示該問題;false則不觸碰
                    return true;
                }
            }
            return super.visitMethod(node);

        }

    }
}

上文NamingConventionDetector類憋活,已經(jīng)是全部代碼岂津,只檢查類名和方法名是否符合駝峰命名法,可以根據(jù)具體需求,重寫抽象類AbstractUastVisitor的visitXXX方法余掖。

如果處理特定的方法或者其他寸爆,也可以使用默認的處理器。重寫Scanner相關(guān)方法盐欺。例如:

 @Override
public List<String> getApplicableMethodNames() {
    return Arrays.asList("e","v");
}

表示e(),v()方法會被檢測到,并調(diào)用visitMethod()方法仅醇,實現(xiàn)自己的邏輯冗美。

    @Override
    public void visitMethod JavaContext context,  JavaElementVisitor visitor,  PsiMethodCallExpression call, PsiMethod method) {
        //todo something
        super.visitMethod(context, visitor, call, method);
    }

接下來就是注冊自定義的Issue:

public class Register extends IssueRegistry {
    @NotNull
    @Override
    public List<Issue> getIssues() {
        return Arrays.asList(NamingConventionDetector.ISSUE);
    }
}

在lib項目的build.gradle文件添加相關(guān)代碼:

apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.tools.lint:lint-api:26.4.2'
    implementation 'com.android.tools.lint:lint-checks:26.4.2'

}
//添加如下代碼
jar {
    manifest {
        attributes 'Lint-Registry': 'com.gitcode.lib.Register'
    }
}

sourceCompatibility = "7"
targetCompatibility = "7"

到這里就自定義Lint自定義規(guī)則就搞定了,接著是使用和確定規(guī)則是否正確析二。

使用自定Lint規(guī)則

使用自定義Lint規(guī)則有兩種形式:jar包和AAR文件粉洼。

jar形式使用

在Android Studio的Terminal輸入下面命令:

./gradlew lib:assemble

看到BUILD SUCCESSFUL則表示生成jar包成功,可以在下面路徑找到:

lib->build->libs

如圖:

image

將lib.jar拷貝下面目錄:

~/.android/lint/

如果lint文件夾不存在叶摄,則創(chuàng)建属韧。通過命令行輸入lint --list「蛳牛滑到最后可以看到配置的規(guī)則宵喂,如圖:

image

重啟Android Studio,讓規(guī)則生效。
檢測到方法大寫会傲,不符合命名規(guī)范锅棕,報導(dǎo)該問題拙泽。


image

類名不符合規(guī)范:

image

從上文可以看到,放在目錄下的jar包對所有工程都是有效的裸燎。如果要針對單個工程顾瞻,那么就需要需要AAR形式了。

AAR形式

在同個工程新建一個Android Library德绿,名為lintLibrary荷荤,修改相關(guān)配置。

1移稳、修改Java工程的依賴

修改自定義lint規(guī)則的Java庫的build.gradle(這里是上文的Java lib庫)梅猿,注意到要將implementation改為compileOnly。

apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //將implementation改為compileOnly秒裕,不然報錯
    compileOnly 'com.android.tools.lint:lint-api:26.4.2'
    compileOnly 'com.android.tools.lint:lint-checks:26.4.2'

}

jar {
    manifest {
        attributes 'Lint-Registry-v2': 'com.gitcode.lib.Register'
    }
}

sourceCompatibility = "7"
targetCompatibility = "7"
2袱蚓、修改Android Library依賴

Android Library主要用來輸出AAR文件,要注意到Android Studio新特性的變更(在這里踩了大坑)几蜻。

dependencies {
    ......
    
    lintPublish project(':lib')
}

在Android Studio 3.4+喇潘,lintChecks project(':lib'):lint檢查只在當(dāng)前工程生效,也就是Android Library,并不會打包到AAR文件中梭稚。lintPublish project(':lib')才會將lint檢查包含AAR文件中颖低。

3、輸出AAR文件

此時跟輸出普通的AAR文件沒什么區(qū)別弧烤,但為了手把手教會第一個自定義Issue忱屑,我寫!

步驟:

菜單欄:View->Tool Windows->Gradle

此時Android Studio在右邊會打開如下窗口:

image

根據(jù)上圖操作暇昂,雙擊assemble,稍等一會莺戒,在控制臺看BUILD SUCCESSFUL,則可在下面目錄找到AAR文件。

lintLibrary->build->outputs->aar

這一小節(jié)的步驟也可以通過命令行執(zhí)行急波。

4从铲、使用AAR文件

有本地依賴或者上傳遠程倉庫,這里只介紹本地依賴澄暮。將上小結(jié)生成的AAR文件拷貝在app的libs文件夾名段。并配置app組件的build.gradle

repositories {
    flatDir {
        dirs 'libs'
    }
}
dependencies {
    implementation (name:'lintlibrary-release', ext:'aar')
}

到這里,就能使用自定義的lint規(guī)則了泣懊,效果和上面使用jar包是一致的伸辟。如果不生效,重啟Android Studio看看馍刮。

采坑記

1信夫、Found more than one jar in the 'lintChecks' configuration. Only one file is supported

這是因為在輸出AAR文件中,參考其他人的文章。沒有將Java Library的依賴改為compileOnly忙迁。而且Android Library中使用lintChecks脐彩。

2、輸出AAR文件沒有生效

不知道為什么姊扔,Linkedin的參考文章沒有生效,可能是Android Studio版本的問題惠奸。

另外使用lintChecks輸出AAR不生效,Android Studio 3.4+新特性變更恰梢,采用lintPublish佛南。

總結(jié)

花了好長好長的時間寫本文,差點就放棄了嵌言。因為自己Android Studio看不了lint的源碼嗅回,只能從網(wǎng)上找,網(wǎng)上又找不到最新的doc摧茴。過濾太多雷同文章绵载,差點想哭,一些最新的文章也跟不上相關(guān)技術(shù)的更新苛白。娃豹。。

但是一切都值得购裙,因為能幫助到想學(xué)習(xí)Android Studio lint工具的同學(xué)懂版,一起向往美好的生活。

GitHub

點個贊行不

寫此文找到的一些具有參考意義的文章:

Android 官方指導(dǎo)

Linkedin 指導(dǎo)

美團->Android自定義Lint實踐

lint-custom-rules

另外:本文沒有demo躏率,demo的代碼已經(jīng)貼在文章里了躯畴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市薇芝,隨后出現(xiàn)的幾起案子蓬抄,更是在濱河造成了極大的恐慌,老刑警劉巖恩掷,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倡鲸,死亡現(xiàn)場離奇詭異,居然都是意外死亡黄娘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門克滴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逼争,“玉大人,你說我怎么就攤上這事劝赔∈慕梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長杂伟。 經(jīng)常有香客問我移层,道長,這世上最難降的妖魔是什么赫粥? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任观话,我火速辦了婚禮,結(jié)果婚禮上友瘤,老公的妹妹穿的比我還像新娘帕棉。我一直安慰自己甜攀,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布晦溪。 她就那樣靜靜地躺著,像睡著了一般挣跋。 火紅的嫁衣襯著肌膚如雪三圆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天避咆,我揣著相機與錄音舟肉,去河邊找鬼。 笑死牌借,一個胖子當(dāng)著我的面吹牛度气,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播膨报,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼磷籍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了现柠?” 一聲冷哼從身側(cè)響起院领,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎够吩,沒想到半個月后比然,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡周循,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年强法,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湾笛。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡饮怯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嚎研,到底是詐尸還是另有隱情蓖墅,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站论矾,受9級特大地震影響教翩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贪壳,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一饱亿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寥袭,春花似錦路捧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膘掰,卻和暖如春章姓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背识埋。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工凡伊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窒舟。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓系忙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惠豺。 傳聞我的和親對象是個殘疾皇子银还,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355