阿里Android開發(fā)手冊

本手冊以開發(fā)者為中心視角分為 Java語言規(guī)范(遵循《阿里巴巴 Java開發(fā)手冊》),Android 資源文件命名與使用泉坐,Android 基本組件为鳄,UI 與布局,進(jìn)程腕让、線程與消息通信孤钦,文件與數(shù)據(jù)庫,Bitmap纯丸、 Drawable 與動(dòng)畫偏形,安全,其他等九大部分觉鼻,根據(jù)約束力強(qiáng)弱俊扭,規(guī)約依次分為強(qiáng)制、推薦坠陈、參考三大類:

【強(qiáng)制】 必須遵守萨惑,違反本約定或?qū)饑?yán)重的后果;

【推薦】 盡量遵守仇矾,長期遵守有助于系統(tǒng)穩(wěn)定性和合作效率的提升庸蔼;

【參考】 充分理解,技術(shù)意識的引導(dǎo)贮匕,是個(gè)人學(xué)習(xí)姐仅、團(tuán)隊(duì)溝通、項(xiàng)目合作的方向刻盐。

image

二掏膏、Android資源文件命名與使用

1.【推薦】資源文件需帶模塊前綴。

2.【推薦】layout 文件的命名方式敦锌。

Activity 的 layout 以 module_activity 開頭

Fragment 的 layout 以 module_fragment 開頭

Dialog 的 layout 以 module_dialog 開頭

include 的 layout 以 module_include 開頭

ListView 的行 layout 以 module_list_item 開頭

RecyclerView 的 item layout 以 module_recycle_item 開頭

GridView 的行 layout 以 module_grid_item 開頭

3.【推薦】drawable 資源名稱以小寫單詞+下劃線的方式命名壤追,根據(jù)分辨率不同存放在不同的 drawable 目錄下,建議只使用一套供屉,例如 drawable-xhdpi行冰。采用規(guī)則如下:

模塊名業(yè)務(wù)功能描述控件描述_控件狀態(tài)限定詞

如:module_login_btn_pressed,module_tabs_icon_home_normal

4.【推薦】anim 資源名稱以小寫單詞+下劃線的方式命名溺蕉,采用以下規(guī)則:

模塊名邏輯名稱[方向|序號]

tween 動(dòng) 畫 資 源 : 盡 可 能 以 通 用 的 動(dòng) 畫 名 稱 命 名 , 如:module_fade_in ,module_fade_out , module_push_down_in (動(dòng)畫+方向)悼做;

frame 動(dòng)畫資源:盡可能以模 塊+功能命名+序號疯特。如:module_loading_grey_001

5.【推薦】color 資源使用#AARRGGBB 格式,寫入 module_colors.xml 文件中肛走,命名格式采用以下規(guī)則:

模塊名邏輯名稱顏色

如:#33b5e5e5

6.【推薦】dimen 資源以小寫單詞+下劃線方式命名漓雅,寫入 module_dimens.xml 文件中,采用以下規(guī)則:

模塊名_描述信息

如:1dp

7.【推薦】style 資源采用小寫單詞+下劃線方式命名朽色,寫入 module_styles.xml 文件中邻吞,采用以下規(guī)則:

父 style 名稱.當(dāng)前 style 名稱

8.【推薦】string資源文件或者文本用到字符需要全部寫入 module_strings.xml文件中,字符串以小寫單詞+下劃線的方式命名葫男,采用以下規(guī)則:

模塊名_邏輯名稱

如:moudule_login_tips,module_homepage_notice_desc

9.【推薦】Id 資源原則上以駝峰法命名抱冷,View 組件的資源 id 需要以 View 的縮寫作為前綴。常用縮寫表如下:

image
其它控件的縮寫推薦使用小寫字母并用下劃線進(jìn)行分割梢褐,例如:

ProgressBar 對應(yīng)的縮寫為 progress_bar

DatePicker 對應(yīng)的縮寫為 date_picker

10.【推薦】大分辨率圖片(單維度超過 1000)大分辨率圖片建議統(tǒng)一放在 xxhdpi 目錄下管理旺遮,否則將導(dǎo)致占用內(nèi)存成倍數(shù)增加。

說明:

為了支持多種屏幕尺寸和密度盈咳, Android 為多種屏幕提供不同的資源目錄進(jìn)行適配耿眉。為不同屏幕密度提供不同的位圖可繪制對象,可用于密度特定資源的配置限定符(在

下面詳述) 包括 ldpi(低)鱼响、 mdpi(中)帆谍、 hdpi(高)视乐、 xhdpi(超高)添怔、 xxhdpi (超超高)和 xxxhdpi(超超超高)饼齿。例如讶舰,高密度屏幕的位圖應(yīng)使用 drawable-hdpi/感论。

根據(jù)當(dāng)前的設(shè)備屏幕尺寸和密度表箭,將會尋找最匹配的資源求橄,如果將高分辨率圖片放入低密度目錄娘锁,將會造成低端機(jī)加載過大圖片資源牙寞,又可能造成 OOM,同時(shí)也是資源浪費(fèi)莫秆,沒有必要在低端機(jī)使用大圖间雀。

三、Android基本組件

Android 基本組件指 Activity镊屎、 Fragment惹挟、 Service、 BroadcastReceiver缝驳、ContentProvider 等等连锯。

1.【強(qiáng)制】Activity 間的數(shù)據(jù)通信归苍,對于數(shù)據(jù)量比較大的,避免使用 Intent + Parcelable的方式运怖,可以考慮 EventBus 等替代方案拼弃,以免造成 TransactionTooLargeException。

2.【推薦】Activity#onSaveInstanceState()方法不是 Activity 生命周期方法摇展,也不保證一定會被調(diào)用吻氧。它是用來在 Activity 被意外銷毀時(shí)保存 UI 狀態(tài)的,只能用于保存臨時(shí)性數(shù)據(jù)咏连,例如 UI 控件的屬性等盯孙,不能跟數(shù)據(jù)的持久化存儲混為一談。持久化存儲應(yīng)該在 Activity#onPause()/onStop()中實(shí)行祟滴。

3.【強(qiáng)制】Activity 間通過隱式 Intent 的跳轉(zhuǎn)振惰,在發(fā)出 Intent 之前必須通過 resolveActivity檢查,避免找不到合適的調(diào)用組件踱启,造成 ActivityNotFoundException 的異常报账。

4.【強(qiáng)制】避免在 Service#onStartCommand()/onBind()方法中執(zhí)行耗時(shí)操作,如果確實(shí)有需求埠偿,應(yīng)改用 IntentService 或采用其他異步機(jī)制完成透罢。

5.【強(qiáng)制】避免在 BroadcastReceiver#onReceive()中執(zhí)行耗時(shí)操作,如果有耗時(shí)工作冠蒋,應(yīng)該創(chuàng)建 IntentService 完成羽圃,而不應(yīng)該在 BroadcastReceiver 內(nèi)創(chuàng)建子線程去做。

說明:

由于該方法是在主線程執(zhí)行抖剿,如果執(zhí)行耗時(shí)操作會導(dǎo)致 UI 不流暢朽寞。可以使用IntentService 斩郎、 創(chuàng) 建 HandlerThread 或 者 調(diào) 用 Context#registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)方法等方式脑融,在其他 Wroker 線程執(zhí)行 onReceive 方法。BroadcastReceiver#onReceive()方法耗時(shí)超過 10 秒鐘缩宜,可能會被系統(tǒng)殺死肘迎。

6.【強(qiáng)制】避免使用隱式 Intent 廣播敏感信息,信息可能被其他注冊了對應(yīng)BroadcastReceiver 的 App 接收锻煌。

說明:

通過 Context#sendBroadcast()發(fā)送的隱式廣播會被所有感興趣的 receiver 接收妓布,惡意應(yīng)用注冊監(jiān)聽該廣播的 receiver 可能會獲取到 Intent 中傳遞的敏感信息,并進(jìn)行其他危險(xiǎn)操作宋梧。如果發(fā)送的廣播為使用 Context#sendOrderedBroadcast()方法發(fā)送的有序廣播匣沼,優(yōu)先級較高的惡意 receiver 可能直接丟棄該廣播,造成服務(wù)不可用捂龄,或者向廣播結(jié)果塞入惡意數(shù)據(jù)释涛。

如果廣播僅限于應(yīng)用內(nèi)加叁,則可以使用 LocalBroadcastManager#sendBroadcast()實(shí)現(xiàn),避免敏感信息外泄和 Intent 攔截的風(fēng)險(xiǎn)枢贿。

7.【推薦】添 加 Fragment 時(shí) 殉农, 確 保 FragmentTransaction#commit() 在Activity#onPostResume()或者 FragmentActivity#onResumeFragments()內(nèi)調(diào)用。不要隨意使用 FragmentTransaction#commitAllowingStateLoss()來代替局荚,任何commitAllowingStateLoss()的使用必須經(jīng)過 code review超凳,確保無負(fù)面影響。

說明:

Activity 可 能 因 為 各 種 原 因 被 銷 毀 耀态, Android 支 持 頁 面 被 銷 毀 前 通 過Activity#onSaveInstanceState() 保 存 自 己 的 狀 態(tài) 轮傍。 但 如 果FragmentTransaction.commit()發(fā)生在 Activity 狀態(tài)保存之后,就會導(dǎo)致 Activity 重建首装、恢復(fù)狀態(tài)時(shí)無法還原頁面狀態(tài)创夜,從而可能出錯(cuò)。為了避免給用戶造成不好的體驗(yàn)仙逻,系統(tǒng)會拋出 IllegalStateExceptionStateLoss 異常驰吓。推薦的做法是在 Activity 的onPostResume() 或 onResumeFragments() ( 對 FragmentActivity ) 里 執(zhí) 行FragmentTransaction.commit(),如有必要也可在 onCreate()里執(zhí)行系奉。不要隨意改用FragmentTransaction.commitAllowingStateLoss() 或 者 直 接 使 用 try-catch 避 免crash檬贰,這不是問題的根本解決之道,當(dāng)且僅當(dāng)你確認(rèn) Activity 重建缺亮、恢復(fù)狀態(tài)時(shí)翁涤,本次 commit 丟失不會造成影響時(shí)才可這么做。

8.【推薦】不要在 Activity#onDestroy()內(nèi)執(zhí)行釋放資源的工作萌踱,例如一些工作線程的銷毀和停止葵礼,因?yàn)?onDestroy()執(zhí)行的時(shí)機(jī)可能較晚〔⑼遥可根據(jù)實(shí)際需要鸳粉,在Activity#onPause()/onStop()中結(jié)合 isFinishing()的判斷來執(zhí)行。

9.【推薦】如非必須园担,避免使用嵌套的 Fragment届谈。

說明:

嵌套 Fragment 是在 Android API 17 添加到 SDK 以及 Support 庫中的功能,F(xiàn)ragment 嵌套使用會有一些坑粉铐,容易出現(xiàn) bug疼约,比較常見的問題有如下幾種:

1) onActivityResult()方法的處理錯(cuò)亂卤档,內(nèi)嵌的 Fragment 可能收不到該方法的回調(diào)蝙泼,需要由宿主 Fragment 進(jìn)行轉(zhuǎn)發(fā)處理;

2) 突變動(dòng)畫效果劝枣;

3) 被繼承的 setRetainInstance()汤踏,導(dǎo)致在 Fragment 重建時(shí)多次觸發(fā)不必要的邏輯织鲸。

非必須的場景盡可能避免使用嵌套 Fragment,如需使用請注意上述問題溪胶。

10.【推薦】總是使用顯式 Intent 啟動(dòng)或者綁定 Service搂擦,且不要為服務(wù)聲明 Intent Filter,保證應(yīng)用的安全性哗脖。如果確實(shí)需要使用隱式調(diào)用瀑踢,則可為 Service 提供 Intent Filter并從 Intent 中排除相應(yīng)的組件名稱,但必須搭配使用 Intent#setPackage()方法設(shè)置Intent 的指定包名才避,這樣可以充分消除目標(biāo)服務(wù)的不確定性橱夭。

11.【推薦】Service 需要以多線程來并發(fā)處理多個(gè)啟動(dòng)請求,建議使用 IntentService桑逝,可避免各種復(fù)雜的設(shè)置棘劣。

說明:

Service 組件一般運(yùn)行主線程,應(yīng)當(dāng)避免耗時(shí)操作楞遏,如果有耗時(shí)操作應(yīng)該在 Worker線程執(zhí)行茬暇。 可以使用 IntentService 執(zhí)行后臺任務(wù)。

12.【推薦】對于只用于應(yīng)用內(nèi)的廣播寡喝,優(yōu)先使用 LocalBroadcastManager 來進(jìn)行注冊和發(fā)送糙俗,LocalBroadcastManager 安全性更好,同時(shí)擁有更高的運(yùn)行效率拘荡。

說明:

對于使用 Context#sendBroadcast()等方法發(fā)送全局廣播的代碼進(jìn)行提示臼节。如果該廣播僅用于應(yīng)用內(nèi),則可以使用 LocalBroadcastManager 來避免廣播泄漏以及廣播被攔截等安全問題珊皿,同時(shí)相對全局廣播本地廣播的更高效网缝。

13.【推薦】當(dāng)前 Activity的 onPause方法執(zhí)行結(jié)束后才會執(zhí)行下一個(gè) Activity的 onCreate方法,所以在 onPause 方法中不適合做耗時(shí)較長的工作蟋定,這會影響到頁面之間的跳轉(zhuǎn)效率粉臊。

14.【強(qiáng)制】不要在 Android 的 Application 對象中緩存數(shù)據(jù)∈欢担基礎(chǔ)組件之間的數(shù)據(jù)共享請使用 Intent 等機(jī)制扼仲,也可使用 SharedPreferences 等數(shù)據(jù)持久化機(jī)制。

15.【推薦】使用 Toast 時(shí)抄淑,建議定義一個(gè)全局的 Toast 對象屠凶,這樣可以避免連續(xù)顯示Toast 時(shí)不能取消上一次 Toast 消息的情況(如果你有連續(xù)彈出 Toast 的情況,避免使用 Toast.makeText)肆资。

16.【強(qiáng)制】使用 Adapter 的時(shí)候矗愧,如果你使用了 ViewHolder 做緩存,在 getView()的方法中無論這項(xiàng) convertView 的每個(gè)子控件是否需要設(shè)置屬性(比如某個(gè) TextView設(shè)置的文本可能為 null郑原,某個(gè)按鈕的背景色為透明唉韭,某控件的顏色為透明等)夜涕,都需要為其顯式設(shè)置屬性(Textview 的文本為空也需要設(shè)置 setText(""),背景透明也需要設(shè)置)属愤,否則在滑動(dòng)的過程中女器,因?yàn)?adapter item 復(fù)用的原因,會出現(xiàn)內(nèi)容的顯示錯(cuò)亂住诸。

17.【強(qiáng)制】Activity或者 Fragment 中動(dòng)態(tài)注冊 BroadCastReceiver 時(shí)驾胆, registerReceiver()和 unregisterReceiver()要成對出現(xiàn)。

說明:

如果 registerReceiver()和 unregisterReceiver()不成對出現(xiàn)贱呐,則可能導(dǎo)致已經(jīng)注冊的receiver 沒有在合適的時(shí)機(jī)注銷俏拱,導(dǎo)致內(nèi)存泄漏,占用內(nèi)存空間吼句,加重 SystemService負(fù)擔(dān)锅必。

部分華為的機(jī)型會對 receiver 進(jìn)行資源管控,單個(gè)應(yīng)用注冊過多 receiver 會觸發(fā)管控模塊拋出異常惕艳,應(yīng)用直接崩潰搞隐。

Activity 的生命周期不對應(yīng),可能出現(xiàn)多次 onResume 造成 receiver 注冊多個(gè)远搪,但最終只注銷一個(gè)劣纲,其余 receiver 產(chǎn)生內(nèi)存泄漏。

四谁鳍、UI與布局

1.【強(qiáng)制】布局中不得不使用 ViewGroup 多重嵌套時(shí)癞季,不要使用 LinearLayout 嵌套,改用 RelativeLayout倘潜,可以有效降低嵌套數(shù)绷柒。

說明:

Android 應(yīng)用頁面上任何一個(gè) View 都需要經(jīng)過 measure、 layout涮因、 draw 三個(gè)步驟才能被正確的渲染废睦。從 xml layout 的頂部節(jié)點(diǎn)開始進(jìn)行 measure,每個(gè)子節(jié)點(diǎn)都需要向自己的父節(jié)點(diǎn)提供自己的尺寸來決定展示的位置养泡,在此過程中可能還會重新measure(由此可能導(dǎo)致 measure 的時(shí)間消耗為原來的 2-3 倍)嗜湃。節(jié)點(diǎn)所處位置越深,套嵌帶來的 measure 越多澜掩,計(jì)算就會越費(fèi)時(shí)购披。這就是為什么扁平的 View 結(jié)構(gòu)會性能更好。

同時(shí)肩榕,頁面擁上的 View 越多刚陡,measure、 layout、 draw 所花費(fèi)的時(shí)間就越久橘荠。要縮短這個(gè)時(shí)間,關(guān)鍵是保持 View 的樹形結(jié)構(gòu)盡量扁平郎逃,而且要移除所有不需要渲染的View哥童。理想情況下,總共的 measure褒翰,layout贮懈,draw 時(shí)間應(yīng)該被很好的控制在 16ms以內(nèi),以保證滑動(dòng)屏幕時(shí) UI 的流暢优训。

要找到那些多余的 View(增加渲染延遲的 view)朵你,可以用 Android Studio Monitor里的 Hierarachy Viewer 工具,可視化的查看所有的 view揣非。

2.【推薦】在 Activity 中顯示對話框或彈出浮層時(shí)抡医,盡量使用 DialogFragment,而非Dialog/AlertDialog早敬,這樣便于隨Activity生命周期管理對話框/彈出浮層的生命周期忌傻。

3.【推薦】源文件統(tǒng)一采用 UTF-8 的形式進(jìn)行編碼。

4.【強(qiáng)制】禁止在非 ui 線程進(jìn)行 view 相關(guān)操作搞监。

5.【推薦】文本大小使用單位 dp水孩,view 大小使用單位 dp。對于 Textview琐驴,如果在文字大小確定的情況下推薦使用 wrap_content 布局避免出現(xiàn)文字顯示不全的適配問題俘种。

6.【強(qiáng)制】禁止在設(shè)計(jì)布局時(shí)多次設(shè)置子 view 和父 view 中為同樣的背景造成頁面過度繪制,推薦將不需要顯示的布局進(jìn)行及時(shí)隱藏绝淡。

7.【推薦】靈活使用布局宙刘,推薦 Merge、 ViewStub 來優(yōu)化布局牢酵,盡可能多的減少 UI布局層級荐类,推薦使用 FrameLayout,LinearLayout茁帽、 RelativeLayout 次之玉罐。

8.【推薦】在需要時(shí)刻刷新某一區(qū)域的組件時(shí),建議通過以下方式避免引發(fā)全局 layout刷新:

1) 設(shè)置固定的 view 大小的高寬潘拨,如倒計(jì)時(shí)組件等吊输;

2) 調(diào)用 view 的 layout 方式修改位置,如彈幕組件等铁追;

3) 通過修改 canvas 位置并且調(diào)用 invalidate(int l, int t, int r, int b)等方式限定刷新區(qū)域季蚂;

4) 通過設(shè)置一個(gè)是否允許 requestLayout 的變量,然后重寫控件的 requestlayout、onSizeChanged 方 法 扭屁, 判 斷 控 件 的 大 小 沒 有 改 變 的 情 況 下 算谈, 當(dāng) 進(jìn) 入requestLayout 的時(shí)候,直接返回而不調(diào)用 super 的 requestLayout 方法料滥。

9.【推薦】不能在 Activity 沒有完全顯示時(shí)顯示 PopupWindow 和 Dialog然眼。

10.【推薦】盡量不要使用 AnimationDrawable,它在初始化的時(shí)候就將所有圖片加載到內(nèi)存中葵腹,特別占內(nèi)存高每,并且還不能釋放,釋放之后下次進(jìn)入再次加載時(shí)會報(bào)錯(cuò)践宴。

說明:

Android 的幀動(dòng)畫可以使用 AnimationDrawable 實(shí)現(xiàn)鲸匿,但是如果你的幀動(dòng)畫中如果包含過多幀圖片,一次性加載所有幀圖片所導(dǎo)致的內(nèi)存消耗會使低端機(jī)發(fā)生 OOM異常阻肩。幀動(dòng)畫所使用的圖片要注意降低內(nèi)存消耗带欢,當(dāng)圖片比較大時(shí),容易出現(xiàn) OOM烤惊。

11.【強(qiáng)制】不能使用 ScrollView 包裹 ListView/GridView/ExpandableListVIew;因?yàn)檫@樣會把 ListView 的所有 Item 都加載到內(nèi)存中洪囤,要消耗巨大的內(nèi)存和 cpu 去繪制圖面。

說明:

ScrollView 中嵌套 List 或 RecyclerView 的做法官方明確禁止撕氧。除了開發(fā)過程中遇到的各種視覺和交互問題瘤缩,這種做法對性能也有較大損耗。 ListView 等 UI 組件自身有垂直滾動(dòng)功能伦泥,也沒有必要在嵌套一層 ScrollView剥啤。目前為了較好的 UI 體驗(yàn),更貼近 Material Design 的設(shè)計(jì)不脯,推薦使用 NestedScrollView府怯。

五、進(jìn)程防楷、線程與消息通信

1.【強(qiáng)制】不要通過 Intent 在 Android 基礎(chǔ)組件之間傳遞大數(shù)據(jù)(binder transaction緩存為 1MB)牺丙,可能導(dǎo)致 OOM。

2.【強(qiáng)制】在 Application 的業(yè)務(wù)初始化代碼加入進(jìn)程判斷复局,確保只在自己需要的進(jìn)程初始化冲簿。特別是后臺進(jìn)程減少不必要的業(yè)務(wù)初始化。

3.【強(qiáng)制】新建線程時(shí)亿昏,必須通過線程池提供(AsyncTask 或者 ThreadPoolExecutor或者其他形式自定義的線程池) 峦剔,不允許在應(yīng)用中自行顯式創(chuàng)建線程。

說明:

使用線程池的好處是減少在創(chuàng)建和銷毀線程上所花的時(shí)間以及系統(tǒng)資源的開銷角钩,解決資源不足的問題吝沫。如果不使用線程池呻澜,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致消耗完內(nèi)存或者“過度切換”的問題。 另外創(chuàng)建匿名線程不便于后續(xù)的資源使用分析惨险,對性能分析等會造成困擾羹幸。

4.【強(qiáng)制】線程池不允許使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor 的方式辫愉,這樣的處理方式讓寫的同學(xué)更加明確線程池的運(yùn)行規(guī)則栅受,規(guī)避資源耗盡的風(fēng)險(xiǎn)。

說明:

Executors 返回的線程池對象的弊端如下:

1) FixedThreadPool 和 SingleThreadPool : 允 許 的 請 求 隊(duì) 列 長 度 為Integer.MAX_VALUE一屋,可能會堆積大量的請求,從而導(dǎo)致 OOM袋哼;

2) CachedThreadPool 和 ScheduledThreadPool : 允 許 的 創(chuàng) 建 線 程 數(shù) 量 為Integer.MAX_VALUE冀墨,可能會創(chuàng)建大量的線程,從而導(dǎo)致 OOM涛贯。

5.【強(qiáng)制】子線程中不能更新界面诽嘉,更新界面必須在主線程中進(jìn)行,網(wǎng)絡(luò)操作不能在主線程中調(diào)用弟翘。

6.【強(qiáng)制】不要在非 UI 線程中初始化 ViewStub虫腋,否則會返回 null。

7.【推薦】盡量減少不同 APP 之間的進(jìn)程間通信及拉起行為稀余。拉起導(dǎo)致占用系統(tǒng)資源悦冀,影響用戶體驗(yàn)。

8.【推薦】新建線程時(shí)睛琳,定義能識別自己業(yè)務(wù)的線程名稱盒蟆,便于性能優(yōu)化和問題排查。

9.【推薦】ThreadPoolExecutor 設(shè)置線程存活時(shí)間(setKeepAliveTime)师骗,確崩龋空閑時(shí)線程能被釋放。

10.【推薦】禁 止 在 多 進(jìn) 程 之 間 用 SharedPreferences 共 享 數(shù) 據(jù) 辟癌, 雖 然 可 以(MODE_MULTI_PROCESS)寒屯,但官方已不推薦。

11.【推薦】謹(jǐn)慎使用 Android 的多進(jìn)程黍少,多進(jìn)程雖然能夠降低主進(jìn)程的內(nèi)存壓力寡夹,但會遇到如下問題:

1) 不能實(shí)現(xiàn)完全退出所有 Activity 的功能;

2) 首次進(jìn)入新啟動(dòng)進(jìn)程的頁面時(shí)會有延時(shí)的現(xiàn)象(有可能黑屏厂置、白屏幾秒要出,是白屏還是黑屏和新 Activity 的主題有關(guān)) ;

3) 應(yīng)用內(nèi)多進(jìn)程時(shí)农渊,Application 實(shí)例化多次患蹂,需要考慮各個(gè)模塊是否都需要在所有進(jìn)程中初始化或颊;

4) 多進(jìn)程間通過 SharedPreferences 共享數(shù)據(jù)時(shí)不穩(wěn)定。

六传于、文件與數(shù)據(jù)庫

1.【強(qiáng)制】任何時(shí)候不要硬編碼文件路徑囱挑,請使用 Android 文件系統(tǒng) API 訪問。

說明:

Android 應(yīng)用提供內(nèi)部和外部存儲沼溜,分別用于存放應(yīng)用自身數(shù)據(jù)以及應(yīng)用產(chǎn)生的用戶數(shù)據(jù)平挑。可以通過相關(guān) API 接口獲取對應(yīng)的目錄系草,進(jìn)行文件操作通熄。

2.【強(qiáng)制】當(dāng)使用外部存儲時(shí),必須檢查外部存儲的可用性找都。

3.【強(qiáng)制】應(yīng)用間共享文件時(shí)唇辨,不要通過放寬文件系統(tǒng)權(quán)限的方式去實(shí)現(xiàn),而應(yīng)使用FileProvider能耻。

4.【推薦】SharedPreference 中只能存儲簡單數(shù)據(jù)類型(int赏枚、 boolean、 String 等)晓猛,復(fù)雜數(shù)據(jù)類型建議使用文件饿幅、數(shù)據(jù)庫等其他方式存儲。

5.【推薦】SharedPreference 提 交 數(shù) 據(jù) 時(shí) 戒职, 盡 量 使 用 Editor#apply() 栗恩, 而 非Editor#commit()。一般來講洪燥,僅當(dāng)需要確定提交結(jié)果摄凡,并據(jù)此有后續(xù)操作時(shí),才使用 Editor#commit()蚓曼。

說明:

SharedPreference 相關(guān)修改使用 apply 方法進(jìn)行提交會先寫入內(nèi)存亲澡,然后異步寫入磁盤, commit 方法是直接寫入磁盤纫版。如果頻繁操作的話 apply 的性能會優(yōu)于 commit床绪,apply 會將最后修改內(nèi)容寫入磁盤。但是如果希望立刻獲取存儲操作的結(jié)果其弊,并據(jù)此做相應(yīng)的其他操作癞己,應(yīng)當(dāng)使用 commit。

6.【強(qiáng)制】數(shù)據(jù)庫 Cursor 必須確保使用完后關(guān)閉梭伐,以免內(nèi)存泄漏痹雅。

說明:

Cursor 是對數(shù)據(jù)庫查詢結(jié)果集管理的一個(gè)類,當(dāng)查詢的結(jié)果集較小時(shí)糊识,消耗內(nèi)存不易察覺绩社。但是當(dāng)結(jié)果集較大摔蓝,長時(shí)間重復(fù)操作會導(dǎo)致內(nèi)存消耗過大,需要開發(fā)者在操作完成后手動(dòng)關(guān)閉 Cursor愉耙。

數(shù)據(jù)庫 Cursor 在創(chuàng)建及使用時(shí)贮尉,可能發(fā)生各種異常,無論程序是否正常結(jié)束朴沿,必須在最后確保 Cursor 正確關(guān)閉猜谚,以避免內(nèi)存泄漏。同時(shí)赌渣,如果 Cursor 的使用還牽涉多線程場景魏铅,那么需要自行保證操作同步。

7.【強(qiáng)制】多線程操作寫入數(shù)據(jù)庫時(shí)坚芜,需要使用事務(wù)览芳,以免出現(xiàn)同步問題。

說明:

Android 的通過 SQLiteOpenHelper 獲取數(shù)據(jù)庫 SQLiteDatabase 實(shí)例货岭, Helper 中會自動(dòng)緩存已經(jīng)打開的 SQLiteDatabase 實(shí)例路操,單個(gè) App 中應(yīng)使用 SQLiteOpenHelper的單例模式確保數(shù)據(jù)庫連接唯一疾渴。由于 SQLite 自身是數(shù)據(jù)庫級鎖千贯,單個(gè)數(shù)據(jù)庫操作是保證線程安全的(不能同時(shí)寫入),transaction 時(shí)一次原子操作搞坝,因此處于事務(wù)中的操作是線程安全的搔谴。

若同時(shí)打開多個(gè)數(shù)據(jù)庫連接,并通過多線程寫入數(shù)據(jù)庫桩撮,會導(dǎo)致數(shù)據(jù)庫異常敦第,提示數(shù)據(jù)庫已被鎖住。

8.【推薦】大數(shù)據(jù)寫入數(shù)據(jù)庫時(shí)店量,請使用事務(wù)或其他能夠提高 I/O 效率的機(jī)制芜果,保證執(zhí)行速度。

9.【強(qiáng)制】執(zhí)行 SQL 語句時(shí)融师,應(yīng)使用 SQLiteDatabase#insert()右钾、 update()、 delete()旱爆,不要使用 SQLiteDatabase#execSQL()舀射,以免 SQL 注入風(fēng)險(xiǎn)。

10.【強(qiáng)制】如果 ContentProvider 管理的數(shù)據(jù)存儲在 SQL 數(shù)據(jù)庫中怀伦,應(yīng)該避免將不受信任的外部數(shù)據(jù)直接拼接在原始 SQL 語句中脆烟,可使用一個(gè)用于將 ? 作為可替換參數(shù)的選擇子句以及一個(gè)單獨(dú)的選擇參數(shù)數(shù)組,會避免 SQL 注入房待。

七邢羔、Bitmap驼抹、Drawable與動(dòng)畫

1.【強(qiáng)制】加載大圖片或者一次性加載多張圖片,應(yīng)該在異步線程中進(jìn)行张抄。圖片的加載砂蔽,涉及到 IO 操作,以及 CPU 密集操作署惯,很可能引起卡頓左驾。

2.【強(qiáng)制】在 ListView,ViewPager极谊,RecyclerView诡右,GirdView 等組件中使用圖片時(shí),應(yīng)做好圖片的緩存轻猖,避免始終持有圖片導(dǎo)致內(nèi)存泄露帆吻,也避免重復(fù)創(chuàng)建圖片,引起性 能 問 題 咙边。 建 議 使 用 Fresco ( https://github.com/facebook/fresco )猜煮、 Glide(https://github.com/bumptech/glide)等圖片庫。

3.【強(qiáng)制】png 圖片使用 tinypng 或者類似工具壓縮處理败许,減少包體積王带。

4.【推薦】應(yīng)根據(jù)實(shí)際展示需要,壓縮圖片市殷,而不是直接顯示原圖愕撰。手機(jī)屏幕比較小,直接顯示原圖醋寝,并不會增加視覺上的收益搞挣,但是卻會耗費(fèi)大量寶貴的內(nèi)存。

5.【強(qiáng)制】使用完畢的圖片音羞,應(yīng)該及時(shí)回收囱桨,釋放寶貴的內(nèi)存。

6.【推薦】針對不同的屏幕密度嗅绰,提供對應(yīng)的圖片資源舍肠,使內(nèi)存占用和顯示效果達(dá)到合理的平衡。如果為了節(jié)省包體積办陷,可以在不影響 UI 效果的前提下貌夕,省略低密度圖片。

7.【強(qiáng)制】在 Activity.onPause()或 Activity.onStop()回調(diào)中民镜,關(guān)閉當(dāng)前 activity 正在執(zhí)行的的動(dòng)畫啡专。

8.【推薦】在動(dòng)畫或者其他異步任務(wù)結(jié)束時(shí),應(yīng)該考慮回調(diào)時(shí)刻的環(huán)境是否還支持業(yè)務(wù)處理制圈。例如 Activity 的 onStop()函數(shù)已經(jīng)執(zhí)行们童,且在該函數(shù)中主動(dòng)釋放了資源畔况,此時(shí)回調(diào)中如果不做判斷就會空指針崩潰。

9.【推薦】使用 inBitmap 重復(fù)利用內(nèi)存空間慧库,避免重復(fù)開辟新內(nèi)存跷跪。

10.【推薦】使用 ARGB_565 代替 ARGB_888,在不怎么降低視覺效果的前提下齐板,減少內(nèi)存占用吵瞻。

說明:

android.graphics.Bitmap.Config 類中關(guān)于圖片顏色的存儲方式定義:

1) ALPHA_8 代表 8 位 Alpha 位圖;

2) ARGB_4444 代表 16 位 ARGB 位圖甘磨;

3) ARGB_8888 代表 32 位 ARGB 位圖橡羞;

4) RGB_565 代表 8 位 RGB 位圖。

位圖位數(shù)越高济舆,存儲的顏色信息越多卿泽,圖像也就越逼真。大多數(shù)場景使用的是ARGB_8888 和 RGB_565滋觉,RGB_565 能夠在保證圖片質(zhì)量的情況下大大減少內(nèi)存的開銷签夭,是解決 oom 的一種方法。

但是一定要注意 RGB_565 是沒有透明度的椎侠,如果圖片本身需要保留透明度第租,那么就不能使用 RGB_565。

11.【推薦】盡量減少 Bitmap (BitmapDrawable)的使用肺蔚,盡量使用純色(ColorDrawable)煌妈、漸變色(GradientDrawable)儡羔、 StateSelector(StateListDrawable)等與 Shape 結(jié)合的形式構(gòu)建繪圖宣羊。

12.【推薦】謹(jǐn)慎使用 gif 圖片,注意限制每個(gè)頁面允許同時(shí)播放的 gif 圖片汰蜘,以及單個(gè)gif 圖片的大小仇冯。

13.【參考】大圖片資源不要直接打包到 apk,可以考慮通過文件倉庫遠(yuǎn)程下載族操,減小包體積苛坚。

14.【推薦】根據(jù)設(shè)備性能,選擇性開啟復(fù)雜動(dòng)畫色难,以實(shí)現(xiàn)一個(gè)整體較優(yōu)的性能和體驗(yàn)泼舱;

15.【推薦】在有強(qiáng)依賴 onAnimationEnd 回調(diào)的交互時(shí),如動(dòng)畫播放完畢才能操作頁面 枷莉, onAnimationEnd 可 能 會 因 各 種 異 常 沒 被 回 調(diào) ( 參 考 :https://stackoverflow.com/questions/5474923/onanimationend-is-not-getting-called-onanimationstart-works-fine )娇昙, 建 議 加 上 超 時(shí) 保 護(hù) 或 通 過 postDelay 替 代onAnimationEnd。

16.【推薦】當(dāng) View Animation 執(zhí)行結(jié)束時(shí)笤妙,調(diào)用 View.clearAnimation()釋放相關(guān)資源冒掌。

八噪裕、安全

1.【強(qiáng)制】使用 PendingIntent 時(shí),禁止使用空 intent股毫,同時(shí)禁止使用隱式 Intent

說明:

1) 使用 PendingIntent 時(shí)膳音,使用了空 Intent,會導(dǎo)致惡意用戶劫持修改 Intent 的內(nèi)容。禁止使用一個(gè)空 Intent 去構(gòu)造 PendingIntent铃诬,構(gòu)造 PendingIntent 的 Intent一定要設(shè)置 ComponentName 或者 action祭陷。

2) PendingIntent 可以讓其他 APP 中的代碼像是運(yùn)行自己 APP 中。 PendingIntent的intent接收方在使用該intent時(shí)與發(fā)送方有相同的權(quán)限趣席。在使用PendingIntent時(shí)颗胡,PendingIntent 中包裝的 intent 如果是隱式的 Intent,容易遭到劫持吩坝,導(dǎo)致信息泄露毒姨。

2.【強(qiáng)制】禁止使用常量初始化矢量參數(shù)構(gòu)建 IvParameterSpec,建議 IV 通過隨機(jī)方式產(chǎn)生钉寝。

說明:

使用固定初始化向量弧呐,結(jié)果密碼文本可預(yù)測性會高得多,容易受到字典式攻擊嵌纲。 iv的作用主要是用于產(chǎn)生密文的第一個(gè) block俘枫,以使最終生成的密文產(chǎn)生差異(明文相同的情況下),使密碼攻擊變得更為困難逮走,除此之外 iv 并無其它用途鸠蚪。因此 iv 通過隨機(jī)方式產(chǎn)生是一種十分簡便、有效的途徑师溅。

3.【強(qiáng)制】將 android:allowbackup 屬性設(shè)置為 false茅信,防止 adb backup 導(dǎo)出數(shù)據(jù)。

說明:

在 AndroidManifest.xml 文件中為了方便對程序數(shù)據(jù)的備份和恢復(fù)在 Android APIlevel 8 以后增加了 android:allowBackup 屬性值墓臭。默認(rèn)情況下這個(gè)屬性值為 true,故當(dāng) allowBackup 標(biāo)志值為 true 時(shí)蘸鲸,即可通過 adb backup 和 adb restore 來備份和恢復(fù)應(yīng)用程序數(shù)據(jù)。

4.【強(qiáng)制】在實(shí)現(xiàn)的 HostnameVerifier 子類中窿锉,需要使用 verify 函數(shù)效驗(yàn)服務(wù)器主機(jī)名的合法性酌摇,否則會導(dǎo)致惡意程序利用中間人攻擊繞過主機(jī)名效驗(yàn)。

說明:

在握手期間嗡载,如果 URL 的主機(jī)名和服務(wù)器的標(biāo)識主機(jī)名不匹配窑多,則驗(yàn)證機(jī)制可以回調(diào)此接口的實(shí)現(xiàn)程序來確定是否應(yīng)該允許此連接。如果回調(diào)內(nèi)實(shí)現(xiàn)不恰當(dāng)洼滚,默認(rèn)接受所有域名埂息,則有安全風(fēng)險(xiǎn)。

5.【強(qiáng)制】利用 X509TrustManager 子類中的 checkServerTrusted 函數(shù)效驗(yàn)服務(wù)器端證書的合法性。

說明:

在實(shí)現(xiàn)的 X509TrustManager 子類中未對服務(wù)端的證書做檢驗(yàn)耿芹,這樣會導(dǎo)致不被信任的證書繞過證書效驗(yàn)機(jī)制崭篡。

6.【強(qiáng)制】META-INF 目錄中不能包含如.apk,.odex,.so 等敏感文件,該文件夾沒有經(jīng)過簽名吧秕,容易被惡意替換报嵌。

7.【強(qiáng)制】Receiver/Provider 不能在毫無權(quán)限控制的情況下哨毁,將 android:export 設(shè)置為 true舟误。

8.【參考】數(shù)據(jù)存儲在 Sqlite 或者輕量級存儲需要對數(shù)據(jù)進(jìn)行加密顺囊,取出來的時(shí)候進(jìn)行解密。

9.【強(qiáng)制】阻止 webview 通過 file:schema 方式訪問本地敏感數(shù)據(jù)砂碉。

10.【強(qiáng)制】不要廣播敏感信息蛀蜜,只能在本應(yīng)用使用 LocalBroadcast,避免被別的應(yīng)用收到增蹭,或者 setPackage 做限制滴某。

11.【強(qiáng)制】不要把敏感信息打印到 log 中。

說明:

在 APP 的開發(fā)過程中滋迈,為了方便調(diào)試霎奢,通常會使用 log 函數(shù)輸出一些關(guān)鍵流程的信息,這些信息中通常會包含敏感內(nèi)容饼灿,如執(zhí)行流程幕侠、明文的用戶名密碼等,這會讓攻擊者更加容易的了解 APP 內(nèi)部結(jié)構(gòu)方便破解和攻擊碍彭,甚至直接獲取到有價(jià)值的敏感信息晤硕。

12.【強(qiáng)制】對于內(nèi)部使用的組件,顯示設(shè)置組件的"android:exported"屬性為 false庇忌。

說明:

Android 應(yīng)用使用 Intent 機(jī)制在組件之間傳遞數(shù)據(jù)舞箍,如果應(yīng)用在使用 getIntent(),getAction()漆枚,Intent.getXXXExtra()獲取到空數(shù)據(jù)创译、異车种或者畸形數(shù)據(jù)時(shí)沒有進(jìn)行異常捕獲墙基,應(yīng)用就會發(fā)生 Crash,應(yīng)用不可使用(本地拒絕服務(wù))刷喜。惡意應(yīng)用可通過向受害者應(yīng)用發(fā)送此類空數(shù)據(jù)残制、異常或者畸形數(shù)據(jù)從而使應(yīng)用產(chǎn)生本地拒絕服務(wù)掖疮。

13.【強(qiáng)制】應(yīng)用發(fā)布前確保 android:debuggable 屬性設(shè)置為 false初茶。

14.【強(qiáng)制】使用 Intent Scheme URL 需要做過濾。

說明:

如果瀏覽器支持 Intent Scheme Uri 語法浊闪,如果過濾不當(dāng)恼布,那么惡意用戶可能通過瀏覽器 js 代碼進(jìn)行一些惡意行為螺戳,比如盜取 cookie 等。如果使用了 Intent.parseUri函 數(shù) 折汞, 獲 取 的 intent 必 須 嚴(yán) 格 過 濾 倔幼, intent 至 少 包 含addCategory(“android.intent.category.BROWSABLE”) , setComponent(null) 爽待,setSelector(null)3 個(gè)策略损同。

15.【強(qiáng)制】密鑰加密存儲或者經(jīng)過變形處理后用于加解密運(yùn)算,切勿硬編碼到代碼中鸟款。

說明:

應(yīng)用程序在加解密時(shí)膏燃,使用硬編碼在程序中的密鑰,攻擊者通過反編譯拿到密鑰可以輕易解密 APP 通信數(shù)據(jù)何什。

16.【強(qiáng)制】將所需要?jiǎng)討B(tài)加載的文件放置在 apk 內(nèi)部组哩,或應(yīng)用私有目錄中,如果應(yīng)用必須要把所加載的文件放置在可被其他應(yīng)用讀寫的目錄中(比如 sdcard)处渣,建議對不可信的加載源進(jìn)行完整性校驗(yàn)和白名單處理禁炒,以保證不被惡意代碼注入。

17.【強(qiáng)制】除非 min API level >=17霍比,請注意 addJavascriptInterface 的使用幕袱。

說明:

API level>=17,允許 js 被調(diào)用的函數(shù)必須以@JavascriptInterface 進(jìn)行注解悠瞬,因此不受影響们豌; 對于 API level < 17,盡量不要使用 addJavascriptInterface浅妆,如果一定要用望迎,那么:

1) 使用 https 協(xié)議加載 URL,使用證書校驗(yàn)凌外,防止訪問的頁面被篡改掛馬辩尊;

2) 對加載 URL 做白名單過濾、完整性校驗(yàn)等防止訪問的頁面被篡改康辑;

3) 如果加載本地 html,應(yīng)該會 HTML 內(nèi)置在 APK 中摄欲,以及對 HTML 頁面進(jìn)行完整性校驗(yàn)。

18.【強(qiáng)制】使用 Android 的 AES/DES/DESede 加密算法時(shí)疮薇,不要使用默認(rèn)的加密模式ECB胸墙,應(yīng)顯示指定使用 CBC 或 CFB 加密模式。

說明:

加密模式 ECB按咒、 CBC迟隅、 CFB、 OFB 等,其中 ECB 的安全性較弱智袭,會使相同的銘文在不同的時(shí)候產(chǎn)生相同的密文奔缠,容易遇到字典攻擊,建議使用 CBC 或 CFB 模式吼野。

1) ECB:Electronic codebook添坊,電子密碼本模式

2) CBC:Cipher-block chaining,密碼分組鏈接模式

3) CFB:Cipher feedback箫锤,密文反饋模式

4) OFB:Output feedback贬蛙,輸出反饋模式

19.【強(qiáng)制】不要使用 loopback 來通信敏感信息。

20.【推薦】對于不需要使用 File 協(xié)議的應(yīng)用谚攒,禁用 File 協(xié)議阳准,顯式設(shè)置 webView.getSettings().setAllowFileAccess(false),對于需要使用 File 協(xié)議的應(yīng)用馏臭,禁止 File協(xié)議調(diào)用 JavaScript野蝇,顯式設(shè)置 webView.getSettings().setJavaScriptEnabled(false)。

21.【強(qiáng)制】Android APP 在 HTTPS 通信中括儒,驗(yàn)證策略需要改成嚴(yán)格模式绕沈。

說明: AndroidAPP 在 HTTPS 通信中,使用ALLOW_ALL_HOSTNAME_VERIFIER帮寻,表示允許和所有的 HOST 建立 SSL 通信乍狐,這會存在中間人攻擊的風(fēng)險(xiǎn),最終導(dǎo)致敏感信息可能會被劫持固逗,以及其他形式的攻擊浅蚪。

22.【推薦】Android5.0 以后安全性要求 較高的應(yīng)用 應(yīng)該使 用 window.setFlag(LayoutParam.FLAG_SECURE) 禁止錄屏。

23.【推薦】zip 中不建議允許../../file 這樣的路徑烫罩,可能被篡改目錄結(jié)構(gòu)惜傲,造成攻擊。

說明:當(dāng) zip 壓縮包中允許存在"../"的字符串贝攒,攻擊者可以利用多個(gè)"../"在解壓時(shí)改變zip 文件存放的位置盗誊,當(dāng)文件已經(jīng)存在是就會進(jìn)行覆蓋,如果覆蓋掉的文件是 so隘弊、dex 或者 odex 文件哈踱,就有可能造成嚴(yán)重的安全問題。

24.【強(qiáng)制】開放的 activity/service/receiver 等需要對傳入的 intent 做合法性校驗(yàn)长捧。

25.【推薦】加密算法:使用不安全的 Hash 算法(MD5/SHA-1)加密信息嚣鄙,存在被破解的風(fēng)險(xiǎn),建議使用 SHA-256 等安全性更高的 Hash 算法串结。

26.【推薦】Android WebView 組件加載網(wǎng)頁發(fā)生證書認(rèn)證錯(cuò)誤時(shí),采用默認(rèn)的處理方法handler.cancel(),停止加載問題頁面。

說明:

Android WebView 組件加載網(wǎng)頁發(fā)生證書認(rèn)證錯(cuò)誤時(shí)肌割,會調(diào)用 WebViewClient 類的onReceivedSslError 方法卧蜓,如果該方法實(shí)現(xiàn)調(diào)用了 handler.proceed()來忽略該證書錯(cuò)誤,則會受到中間人攻擊的威脅把敞,可能導(dǎo)致隱私泄露弥奸。

27.【推薦】直接傳遞命令字或者間接處理有敏感信息或操作時(shí),避免使用 socket 實(shí)現(xiàn)奋早,使用能夠控制權(quán)限校驗(yàn)身份的方式通訊盛霎。

九、其他

1.【強(qiáng)制】不要通過 Msg 傳遞大的對象耽装,會導(dǎo)致內(nèi)存問題愤炸。

2.【強(qiáng)制】不能使用 System.out.println 打印 log。

3.【強(qiáng)制】Log 的 tag 不能是" "掉奄。

作者:m_博客
鏈接:http://www.reibang.com/p/8cb2cff0214c
來源:簡書
簡書著作權(quán)歸作者所有规个,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末姓建,一起剝皮案震驚了整個(gè)濱河市诞仓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌速兔,老刑警劉巖墅拭,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涣狗,居然都是意外死亡帜矾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門屑柔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屡萤,“玉大人,你說我怎么就攤上這事掸宛∷缆剑” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵唧瘾,是天一觀的道長措译。 經(jīng)常有香客問我,道長饰序,這世上最難降的妖魔是什么领虹? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮求豫,結(jié)果婚禮上塌衰,老公的妹妹穿的比我還像新娘诉稍。我一直安慰自己,他們只是感情好最疆,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布杯巨。 她就那樣靜靜地躺著,像睡著了一般努酸。 火紅的嫁衣襯著肌膚如雪服爷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天获诈,我揣著相機(jī)與錄音仍源,去河邊找鬼。 笑死舔涎,一個(gè)胖子當(dāng)著我的面吹牛笼踩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播终抽,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼戳表,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了昼伴?” 一聲冷哼從身側(cè)響起匾旭,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎圃郊,沒想到半個(gè)月后价涝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡持舆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年色瘩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逸寓。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡居兆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出竹伸,到底是詐尸還是另有隱情泥栖,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布勋篓,位于F島的核電站吧享,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏譬嚣。R本人自食惡果不足惜钢颂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拜银。 院中可真熱鬧殊鞭,春花似錦遭垛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疯汁。三九已至牲尺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間幌蚊,已是汗流浹背谤碳。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溢豆,地道東北人蜒简。 一個(gè)月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像漩仙,于是被迫代替她去往敵國和親搓茬。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

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