Gradle for Android(九) 高級構(gòu)建定制

現(xiàn)在你已經(jīng)知道了Gradle是如何工作的哟冬,如何創(chuàng)建你自己的任務(wù)和插件秸苗,如何運(yùn)行測試疚察,以及如何設(shè)置持續(xù)集成派继,你差不多可以稱呼自己為Gradle專家了。本章會(huì)包含一些之前沒有提及的竅門和技巧捻艳,使使用Gradle進(jìn)行構(gòu)建驾窟、開發(fā)和部署變得簡單。

本章內(nèi)容有:

  • 減小APK體積
  • 加速構(gòu)建
  • 忽略Lint檢查
  • 在Gradle中使用Ant
  • 高級應(yīng)用部署

減小APK體積

在過去的幾年里认轨,apk文件的體積有了顯著的增大绅络。這里有幾個(gè)原因:Android開發(fā)者有更多的庫可以使用,增加了更多的密度嘁字,以及應(yīng)用有了更多的功能恩急。

保證APK有更小的體積是很好的想法。不僅是因?yàn)镚oole Play有50M大小的限制纪蜒,還因?yàn)楦〉腁PK意味著用戶可以更快地下載并安裝應(yīng)用衷恭,以及占用更少的內(nèi)存。

本節(jié)纯续,我們會(huì)討論幾個(gè)Gradle構(gòu)建文件的屬性随珠,來幫助減小APK文件體積。

ProGuard

ProGuard是一個(gè)java工具猬错,在編譯階段不僅可以壓縮窗看,還可以優(yōu)化,混淆倦炒,預(yù)先審核代碼显沈。它會(huì)遍歷應(yīng)用中的所有代碼路徑,找到不用的代碼并刪除它逢唤。ProGuard也會(huì)重命名你的類和成員拉讯。這個(gè)過程可以減少應(yīng)用的內(nèi)存占用,并增大反編譯的難度智玻。

Gradle Android插件有一個(gè)minifyEnabled屬性可以設(shè)置開啟ProGuard:

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

當(dāng)你設(shè)置minifyEnabled為true后遂唧,proguardRelease任務(wù)就會(huì)執(zhí)行,并且在構(gòu)建過程中觸發(fā)ProGuard吊奢。

最好在打開ProGuard后重新檢查一下整個(gè)應(yīng)用盖彭,因?yàn)樗赡芴蕹恍┠闳匀恍枰拇a。這是ProGuard令很多開發(fā)者苦惱的問題页滚。為了解決這個(gè)問題召边,你可以定義ProGuard規(guī)則,將不需要移除或者混淆的類排除出去裹驰。proguardFiles屬性用來定義包含ProGuard規(guī)則的文件隧熙。比如,要保持一個(gè)類不變幻林,你可以添加如下規(guī)則:

-keep public class <MyClass>

getDefaultProguardFile('proguard-android.txt')方法從proguard-android.txt文件獲取ProGuard設(shè)置贞盯,該文件在Android SDK的tools/proguard目錄下音念。proguard-rules.pro文件由Android Studio默認(rèn)添加到模塊中,所以你可以很簡單的在該文件添加這個(gè)模塊的規(guī)則躏敢。

ProGuard規(guī)則對于每個(gè)app或者library都是不同的闷愤,所以本書不會(huì)深入研究細(xì)節(jié)。如果你想了解更多相關(guān)內(nèi)容件余,可以瀏覽http://developer.android.com/tools/help/proguard.html

除了壓縮Java代碼讥脐,也可以壓縮不用的資源。

壓縮資源

Gradle和Gradle Android插件可以在構(gòu)建時(shí)去掉不用的資源啼器。這在你有一些舊的忘掉刪除的資源時(shí)非常有用旬渠。另一個(gè)場景是你引入了一個(gè)包含很多資源的庫,但你只用了很少一部分端壳。你可以打開資源壓縮來處理這種情況告丢。有兩種方式可以進(jìn)行資源壓縮:自動(dòng)和手動(dòng)。

自動(dòng)壓縮

最簡單的方式是在你的構(gòu)建中配置shrinkResources屬性更哄。如果設(shè)置為true芋齿,Android構(gòu)建工具會(huì)自動(dòng)檢測哪些資源沒有用到,不應(yīng)該包含到APK中成翩。

使用這個(gè)特性有一個(gè)需求觅捆,就是你也必須使用ProGuard。這源于資源壓縮的工作方式麻敌,因?yàn)锳ndroid構(gòu)建工具在引用資源的代碼被移除之前無法確定哪些資源是沒有用到的栅炒。

下面的代碼片段展示了如何在一個(gè)特定的構(gòu)建類型中配置自動(dòng)壓縮資源:

android {
    buildTypes {
        release {
            minifyEnabled = true
            shrinkResources = true
        }
    }
}

如果你想準(zhǔn)確知道開啟資源壓縮后,APK減小了多少术羔,你可以運(yùn)行shrinkReleaseResources任務(wù)赢赊。這個(gè)任務(wù)會(huì)打印出包減小的大小:

:app:shrinkReleaseResources
Removed unused resources: Binary resource data reduced from 433KB
to 354KB: Removed 18%

通過給構(gòu)建命令添加--info標(biāo)識(shí)级历,你可以得到關(guān)于APK去除的資源的詳細(xì)概況:

$ gradlew clean assembleRelease --info

使用這個(gè)標(biāo)識(shí)后释移,Gradle會(huì)打印出構(gòu)建過程的更多的信息,包括最后的輸出不包含的資源寥殖。

自動(dòng)資源壓縮的一個(gè)問題是它可能移除過多的資源玩讳。尤其是被動(dòng)態(tài)使用的資源可能被意外刪除。為防止這種情況嚼贡,你可以在res/raw/目錄放置keep.xml文件來定義一些特殊情況熏纯。一個(gè)簡單的keep.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/keep_me,@layout/also_used_*"/>

keep.xml本身會(huì)在最終的輸出中被移除。

手動(dòng)壓縮

一個(gè)不那么極端的移除資源的方式是除去特定的語言文件或者特定密度的圖像粤策。某些庫樟澜,比如Google Play Services,包含很多語言。如果你的應(yīng)用只支持一種或者兩種語言秩贰,就沒必要在最終的APK中包含所有的語言文件霹俺。你可以使用resConfigs屬性來配置你想保留的資源,其余的將被移除萍膛。

如果你只想保留英語吭服、丹麥語和荷蘭語的字符串資源,可以如下配置:

android {
    defaultConfig {
        resConfigs "en", "da", "nl"
    }
}

你也可以配置密度:

android {
    defaultConfig {
        resConfigs "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"
    }
}

你還可以結(jié)合語言和密度蝗罗。實(shí)際上,可以使用此屬性限制所有類型的資源蝌戒。

如果你在艱難地設(shè)置ProGuard串塑,或者你只想去除應(yīng)用不支持的語言和密度資源,使用resConfigs是一個(gè)很好的壓縮資源的方式北苟。

加速構(gòu)建

很多剛開始使用Gradle的Android開發(fā)者會(huì)抱怨它編譯時(shí)間長桩匪。Gradle比Ant的構(gòu)建時(shí)間要長,因?yàn)槊看文銏?zhí)行任務(wù)友鼻,它都需要走完生命周期的三個(gè)階段傻昙。這使它的整個(gè)過程是可配置的,但是也會(huì)變慢很多彩扔。幸運(yùn)的是妆档,有幾種方式可以加快Gradle的構(gòu)建。

Gradle屬性

一個(gè)加速Gradle構(gòu)建速度的方法是修改默認(rèn)的配置虫碉。我們在第五章已經(jīng)提及了并行構(gòu)建執(zhí)行贾惦,除此之外,你仍然可以調(diào)整一些其他的配置敦捧。

回顧一下须板,你可以通過設(shè)置項(xiàng)目根目錄的gradle.properties文件打開并行構(gòu)建。只需要添加如下屬性:

org.gradle.parallel=true

另一個(gè)簡單的方式是打開Gradle守護(hù)進(jìn)程兢卵,這會(huì)在你第一次構(gòu)建的時(shí)候啟動(dòng)一個(gè)后臺(tái)進(jìn)程习瑰。任何串行構(gòu)建都會(huì)重復(fù)利用這個(gè)后臺(tái)進(jìn)程,這就減少了啟動(dòng)成本秽荤。這個(gè)進(jìn)程在你使用Gradle期間會(huì)一直保留甜奄,直到空閑3個(gè)小時(shí)后才會(huì)殺死。在你短時(shí)間內(nèi)多次使用Gradle的情況下,使用守護(hù)進(jìn)程是很有用的游沿『凡可以如下打開守護(hù)進(jìn)程:

org.gradle.daemon=true

在Android Studio中,Gradle守護(hù)進(jìn)程是默認(rèn)打開的第喳。這意味著在IDE第一次構(gòu)建之后,接下來的構(gòu)建會(huì)稍微快一些踱稍。如果你通過命令行進(jìn)行構(gòu)建曲饱,Gradle守護(hù)進(jìn)程是關(guān)閉的悠抹,除非你在屬性中打開它。

為了加速編譯扩淀,你可以修改JVM的參數(shù)楔敌。你可以使用jvmargs這個(gè)Gradle屬性來設(shè)置JVM內(nèi)存分配池的值。兩個(gè)對構(gòu)建速度有直接影響的參數(shù)是XmsXmx驻谆。Xms參數(shù)用來設(shè)置初始的內(nèi)存值卵凑,Xmx參數(shù)用來設(shè)置最大值。你可以在gradle.properties文件中手動(dòng)設(shè)置這兩個(gè)值:

org.gradle.jvmargs=-Xms256m -Xmx1024m

你需要設(shè)置一個(gè)值和一個(gè)單位(k,m,g)胜臊。最大內(nèi)存分配(Xmx)默認(rèn)是256MB勺卢,起始內(nèi)存分配(Xms)默認(rèn)沒有設(shè)置∠蠖裕可設(shè)置的值依賴你電腦的內(nèi)存大小黑忱。

最后一個(gè)你可以配置的屬性是org.gradle.configureondemand。如果你的工程有幾個(gè)模塊勒魔,這會(huì)非常有用甫煞。因?yàn)樗梢院雎援?dāng)前任務(wù)不需要的模塊,來嘗試減少配置階段的耗時(shí)冠绢。如果該屬性設(shè)置為true抚吠,Gradle在運(yùn)行配置階段之前,會(huì)嘗試計(jì)算出哪些模塊更改了配置唐全,哪些沒有埃跷。如果你的項(xiàng)目是單app或者library的項(xiàng)目,這個(gè)特性將不會(huì)有太大的作用邮利。如果你有很多松散耦合的模塊弥雹,這個(gè)特性可以節(jié)省你很多構(gòu)建時(shí)間。

系統(tǒng)范圍的Gradle屬性
如果你想將這些屬性應(yīng)用到所有的基于Gradle的項(xiàng)目中延届,你可以在home目錄的.gradle文件夾創(chuàng)建一個(gè)gradle.properties文件剪勿。在home目錄設(shè)置這些屬性是很好的實(shí)踐。因?yàn)橥ǔD阆虢档驮跇?gòu)建服務(wù)器上的內(nèi)存消耗方庭,構(gòu)建時(shí)間相對來說不是那么重要厕吉。

Android Studio

Android Studio的設(shè)置中同樣包含這些可以加速構(gòu)建時(shí)間的配置。打開Settings械念,導(dǎo)航到Build,Execution,Deployment|Compiler头朱。該頁面,你可以找到并行構(gòu)建龄减、JVM選項(xiàng)项钮,configure on demand等配置。這些配置只在基于Gradle的Android模塊中才會(huì)出現(xiàn)。

圖1

性能分析

如果你想找到哪一部分減慢了構(gòu)建速度烁巫,可以分析整個(gè)構(gòu)建過程署隘。你可以在執(zhí)行Gradle任務(wù)的時(shí)候添加--profile標(biāo)識(shí)。有了這個(gè)標(biāo)識(shí)亚隙,Gradle會(huì)生成一個(gè)性能報(bào)告磁餐,告訴你哪一部分耗時(shí)過長。知道了瓶頸阿弃,你就可以進(jìn)行必要的優(yōu)化诊霹。報(bào)告以HTML的形式保存在模塊的build/reports/profile目錄。

圖2 性能報(bào)告

性能報(bào)告展示任務(wù)執(zhí)行過程中渣淳,每個(gè)階段耗時(shí)的概況畅哑。Summary展示了Gradle在配置階段為每一個(gè)模塊消耗的時(shí)間。Dependency Resolution展示了每個(gè)模塊解決依賴的時(shí)間水由。Task Execution展示了任務(wù)執(zhí)行細(xì)節(jié),包含每個(gè)單獨(dú)任務(wù)的耗時(shí)赛蔫,排列順序從耗時(shí)高到耗時(shí)低排序砂客。

Jack和Jill

如果你想使用實(shí)驗(yàn)工具,你可以打開Jack和Jill來加速構(gòu)建時(shí)間呵恢。Jack(Java Android Compiler Kit)是一個(gè)新的Android構(gòu)建工具鏈鞠值,可以直接將Java資源代碼編譯成dex格式。它有自己的.java庫格式渗钉,同時(shí)接管了打包和壓縮彤恶。**Jill(Jack Intermediate Library Linker)是一個(gè)將.aar.jar文件轉(zhuǎn)換為.jack庫的工具。這些工具仍然是實(shí)驗(yàn)性質(zhì)的鳄橘,但它們可以用來加速構(gòu)建時(shí)間声离,簡化Android構(gòu)建過程。雖然不建議在生產(chǎn)版本使用它們瘫怜,但可以嘗試一下术徊。

為了使用Jack和Jill,你需要使用21.1.1或更高版本的build tools鲸湃,1.0.0或更高版本的Gradle Android插件赠涮。在defaultConfig塊打開Jack和Jill:

android {
    buildToolsRevision '22.0.1'
    defaultConfig {
        useJack = true
    }
}

你也可以在特定的構(gòu)建類型或product flavor中打開Jack和Jill。這種情況下暗挑,你可以繼續(xù)使用常規(guī)構(gòu)建工具鏈笋除,并額外使用實(shí)驗(yàn)性質(zhì)的構(gòu)建:

android {
    productFlavors {
        regular {
            useJack = false
        }

        experimental {
            useJack = true
        }
    }
}

一旦設(shè)置了useJack=true,精簡和混淆將不再使用ProGuard炸裆,但你仍然可以使用ProGuard規(guī)則語法來指定特定的規(guī)則和例外垃它,同樣可以使用proguardFiles方法。

忽略Lint

在使用Gradle執(zhí)行release構(gòu)建時(shí),Lint檢查將會(huì)執(zhí)行嗤瞎。Lint是一個(gè)靜態(tài)代碼檢查工具墙歪,會(huì)標(biāo)識(shí)出你的布局和代碼中潛在的問題。在某些情況下贝奇,甚至?xí)枞麡?gòu)建過程虹菲。如果你的工程之前沒有使用過Lint,并且你想遷移到Gradle中掉瞳,Lint檢查可能會(huì)有很多錯(cuò)誤毕源。為使構(gòu)建可以進(jìn)行,你可以通過關(guān)閉abortOnError忽略Lint檢查陕习,阻止它中斷構(gòu)建霎褐。這只是一個(gè)臨時(shí)解決方案,因?yàn)楹雎訪int錯(cuò)誤可能導(dǎo)致一些問題该镣,比如丟失翻譯冻璃,這可能引起應(yīng)用崩潰。代碼如下:

android {
    lintOptions {
        abortOnError false
    }
}

臨時(shí)關(guān)閉Lint檢查可以很容將Ant構(gòu)建遷移到Gradle中损合。另一種平滑過渡方式是在Gradle中執(zhí)行Ant任務(wù)省艳。

在Gradle中使用Ant

如果你已經(jīng)花費(fèi)了大量時(shí)間來設(shè)置Ant構(gòu)建,那么切換到Gradle可能聽起來會(huì)很恐怖嫁审。在這種情況下跋炕,Gradle不僅能夠執(zhí)行Ant任務(wù),還能擴(kuò)展它們律适。這意味著你可以用很少的步驟從Ant遷移到Gradle,而不是花費(fèi)好幾天來進(jìn)行項(xiàng)目轉(zhuǎn)換辐烂。

Gradle為Ant集成使用Groovy的AntBuilder。AntBuilder使你可以執(zhí)行任何標(biāo)準(zhǔn)的Ant任務(wù)捂贿,你自定義的Ant任務(wù)和整個(gè)Ant構(gòu)建纠修。你還可以在Gradle構(gòu)建配置中定義Ant屬性。

在Gradle中運(yùn)行Ant任務(wù)

Gradle可以直接運(yùn)行Ant任務(wù)眷蜓。你只需要為相應(yīng)的Ant任務(wù)添加ant.前綴就可以了分瘾。比如,創(chuàng)建一個(gè)歸檔:

task archive << {
    ant.echo 'Ant is archiving...'
    ant.zip(destfile: 'archive.zip') {
        fileset(dir: 'zipme')
    }
}

這個(gè)任務(wù)在Gradle中定義吁系,使用了echozip這兩個(gè)Ant任務(wù)德召。

你更應(yīng)該首先考慮Gradle相同功能的任務(wù)。上例中汽纤,你可以定義相應(yīng)的Gradle任務(wù):

task gradleArchive(type:Zip) << {
    from 'zipme/'
    archiveName 'grarchive.zip'
}

相應(yīng)的Gradle任務(wù)更加簡潔和易于理解上岗,也更加高效。

引入整個(gè)Ant腳本

如果你創(chuàng)建了一個(gè)Ant腳本來構(gòu)建應(yīng)用蕴坪,你可以使用ant.importBuild來引入整個(gè)構(gòu)建配置肴掷。所有的Ant targets會(huì)自動(dòng)轉(zhuǎn)換為Gradle任務(wù)敬锐,你可以通過原始名稱訪問它們。比如下面這個(gè)Ant構(gòu)建文件:

<project>
    <target name="hello">
        <echo>Hello, Ant</echo>
    </target>
</project>

你可以這樣引入到Gradle:

ant.importBuild 'build.xml'

hello任務(wù)將會(huì)出現(xiàn)在Gradle構(gòu)建中呆瞻,你可以像常規(guī)Gradle任務(wù)一樣執(zhí)行它:

$ gradlew hello
:hello
[ant:echo] Hello, Ant

因?yàn)锳nt任務(wù)被轉(zhuǎn)換為了Gradle任務(wù)台夺,所以你可以使用doFirstdoLast或者<<來進(jìn)行擴(kuò)展。比如痴脾,你可以在控制臺(tái)打印另一行:

hello << {
    println 'Hello, Ant. It\'s me, Gradle'
}

執(zhí)行結(jié)果為:

$ gradlew hello
:hello
[ant:echo] Hello, Ant
Hello, Ant. It's me, Gradle

你也可以依賴這些來自Ant的任務(wù)颤介。比如:

task hi(dependsOn: hello) << {
    println 'Hi!'
}

結(jié)果如下:

$ gradlew intro
:hello
[ant:echo] Hello, Ant
Hello, Ant. It's me, Gradle
:hi
Hi!

如果需要,你甚至可以創(chuàng)建依賴Gradle任務(wù)的Ant任務(wù)赞赖。你需要在build.xml文件中為該任務(wù)添加depends屬性:

<target name="hi" depends="intro">
    <echo>Hi</echo>
</target>

如果你有一個(gè)很大的Ant構(gòu)建文件滚朵,并且你想保證任務(wù)名稱不重復(fù),你可以在引入Ant任務(wù)時(shí)進(jìn)行重命名:

ant.importBuild('build.xml') { antTargetName ->
    'ant-' + antTargetName
}

如果你決定重命名所有的Ant任務(wù)前域,你需要時(shí)刻謹(jǐn)記如果你有Ant任務(wù)依賴于一個(gè)Gradle任務(wù)辕近,那么這個(gè)Gradle任務(wù)也需要添加前綴。否則匿垄,Gradle會(huì)找不到它并拋出UnknownTaskException移宅。

屬性

Gradle和Ant不僅可以共享任務(wù),你還可以在Gradle中定義屬性椿疗,然后在Ant構(gòu)建文件中使用它們吞杭。下面的Ant target打印一個(gè)version的屬性:

<target name="appVersion">
    <echo>${version}</echo>
</target>

你可以在Gradle的構(gòu)建配置中定義version屬性,屬性前添加ant.前綴变丧,就像任務(wù)一樣。這是定義Ant屬性最簡短的方式:

ant.version = '1.0'

Groovy隱藏了很多實(shí)現(xiàn)細(xì)節(jié)绢掰。屬性定義的全寫如下:

ant.properties['version'] = '1.0'

運(yùn)行version任務(wù)痒蓬,輸出如下:

$ gradlew appVersion
:appVersion
[ant:echo] 1.0

Gradle的深度Ant集成使你很容易的將基于Ant的構(gòu)建移植到Gradle中。

高級應(yīng)用部署

在第四章滴劲,我們講解了幾種方式來創(chuàng)建同一個(gè)應(yīng)用的不同版本攻晒,即使用構(gòu)建類型和product flavors。而某些情況下班挖,使用一些特殊技巧將更加方便鲁捏,比如APK分割。

分割A(yù)PK

構(gòu)建變體可以看做單獨(dú)的實(shí)體萧芙,它有自己的代碼给梅、資源和清單文件。另一方面双揪,APK分割只影響應(yīng)用的打包动羽。編譯、壓縮和混淆等仍是共享的渔期。這個(gè)機(jī)制允許你基于密度或者application binary interface(ABI)來分割A(yù)PK运吓。

你可以使用android塊中的splits塊來配置分割渴邦。配置密度分割,可以在splits塊中創(chuàng)建density塊拘哨。同理abi塊用于設(shè)置ABI分割谋梭。

如果你打開密度分割,Gradle會(huì)為每個(gè)密度創(chuàng)建單獨(dú)的APK倦青。你可以手動(dòng)去除不需要的密度瓮床,以加速構(gòu)建過程。如下代碼展示了如何打開密度分割姨夹,并去掉較低的密度:

android {
    splits {
        density {
            enable true
            exclude 'ldpi', 'mdpi'
            compatibleScreens 'normal', 'large', 'xlarge'
        }
    }
}

如果你只支持幾個(gè)密度纤垂,可以使用include來定義白名單。使用include磷账,你首先需要reset()方法來將密度白名單列表置空峭沦。

compatibleScreens屬性是可選的,它會(huì)在manifest文件中注入匹配的節(jié)點(diǎn)逃糟。上例中配置應(yīng)用支持normal及以上的屏幕吼鱼,不支持小屏。

基于ABI分割A(yù)PK也是同樣的方式绰咽,所有的屬性和密度分割一致菇肃,除了compatibleScreens

執(zhí)行配置了密度分割的構(gòu)建取募,Gradle會(huì)創(chuàng)建一個(gè)universal APK和幾個(gè)特定密度的APK琐谤。也就是說你會(huì)得到幾個(gè)APK文件:

app-hdpi-release.apk
app-universal-release.apk
app-xhdpi-release.apk
app-xxhdpi-release.apk
app-xxxhdpi-release.apk

使用APK分割有一個(gè)警告。如果你想向Google Play推幾個(gè)APK玩敏,你需要確保每個(gè)APK有不同的版本號(hào)斗忌。也就是說每個(gè)分割有一個(gè)單獨(dú)的版本號(hào)。幸運(yùn)的是旺聚,現(xiàn)在你可以使用applicationVariants屬性织阳。

下面的片段來自Gradle Android插件的文檔,展示了如何為每個(gè)APK生成不同的版本號(hào):

ext.versionCodes = ['armeabi-v7a':1, mips:2, x86:3]

import com.android.build.OutputFile

android.applicationVariants.all { variant ->
    // assign different version code for each output
    variant.outputs.each { output ->
        output.versionCodeOverride = project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) * 1000000 + android.defaultConfig.versionCode
    }
}

這個(gè)小片段會(huì)檢查每個(gè)構(gòu)建變體使用的ABI砰粹,然后將一個(gè)乘數(shù)應(yīng)用到版本代碼唧躲,以確保每個(gè)變體都有一個(gè)獨(dú)特的版本號(hào)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碱璃,一起剝皮案震驚了整個(gè)濱河市弄痹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嵌器,老刑警劉巖界酒,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嘴秸,居然都是意外死亡毁欣,警方通過查閱死者的電腦和手機(jī)庇谆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凭疮,“玉大人饭耳,你說我怎么就攤上這事≈唇猓” “怎么了寞肖?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衰腌。 經(jīng)常有香客問我新蟆,道長,這世上最難降的妖魔是什么右蕊? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任琼稻,我火速辦了婚禮,結(jié)果婚禮上饶囚,老公的妹妹穿的比我還像新娘帕翻。我一直安慰自己,他們只是感情好萝风,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布嘀掸。 她就那樣靜靜地躺著,像睡著了一般规惰。 火紅的嫁衣襯著肌膚如雪睬塌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天歇万,我揣著相機(jī)與錄音衫仑,去河邊找鬼。 笑死堕花,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粥鞋。 我是一名探鬼主播缘挽,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呻粹!你這毒婦竟也來了壕曼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤等浊,失蹤者是張志新(化名)和其女友劉穎腮郊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筹燕,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡轧飞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年衅鹿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片过咬。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡大渤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掸绞,到底是詐尸還是另有隱情泵三,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布衔掸,位于F島的核電站烫幕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏敞映。R本人自食惡果不足惜较曼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驱显。 院中可真熱鬧诗芜,春花似錦、人聲如沸埃疫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽栓霜。三九已至翠桦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胳蛮,已是汗流浹背销凑。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仅炊,地道東北人斗幼。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像抚垄,于是被迫代替她去往敵國和親蜕窿。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,524評論 25 707
  • 這一章主要針對項(xiàng)目中可以用到的一些實(shí)用功能來介紹Android Gradle呆馁,比如如何隱藏我們的證書文件桐经,降低風(fēng)險(xiǎn)...
    acc8226閱讀 7,564評論 3 25
  • 1.介紹 如果你正在查閱build.gradle文件的所有可選項(xiàng),請點(diǎn)擊這里進(jìn)行查閱:DSL參考 1.1新構(gòu)建系統(tǒng)...
    Chuckiefan閱讀 12,118評論 8 72
  • 上一章我們學(xué)習(xí)了Gralde的使用浙滤,創(chuàng)建和轉(zhuǎn)換Android工程阴挣。本章我們將深入了解構(gòu)建文件,學(xué)習(xí)一些有用的tas...
    sollian閱讀 1,367評論 0 3
  • 認(rèn)識(shí)她是因?yàn)榕笥炎非笏睦埃沂桥笥训能妿熍线帧Uf來對不起朋友茎芭,她和朋友的話越來越少,和我的話卻越來越多盒卸。順利成章的我約了...
    一個(gè)特別的人閱讀 478評論 0 1