是讓人耳目一新的 Jetpack MVVM 精講氨Α肯骇!

前言

最近在后臺(tái) 時(shí)有收到 讀者的留言傲须,說(shuō)能不能出一期 Jetpack MVVM 精講梦抢,以及配套一份簡(jiǎn)練的案例,好 把玩把玩愧哟、感受感受奥吩、加深對(duì) MVVM 的印象。

答案是肯定的蕊梧。

面向標(biāo)準(zhǔn)化開(kāi)發(fā)已成現(xiàn)實(shí)

金九銀十霞赫,相信有不少讀者在抓緊機(jī)會(huì)面試。

Android 市場(chǎng)已今非昔比肥矢。在過(guò)去端衰,迫于招人的壓力,應(yīng)試者只需了解四大組件甘改、視圖旅东、網(wǎng)絡(luò)請(qǐng)求,即可謀得一份滿意的工作楼誓。

現(xiàn)如今玉锌,Jetpack 架構(gòu)組件 及 標(biāo)準(zhǔn)化開(kāi)發(fā)模式 的確立,意味著 Android 開(kāi)發(fā)已步入成熟階段:

許多 樣板代碼 不再需要開(kāi)發(fā)者手寫(xiě)疟羹,而是可以通過(guò)模版工具 自動(dòng)生成主守,在取締繁雜耗時(shí)的重復(fù)工作的同時(shí),避免因人工操作的疏忽榄融,而造成難以排查尾菇、不可預(yù)期的錯(cuò)誤双仍。

這十分符合企業(yè)的利益途茫,因而面試官在招人的時(shí)候收擦,也更加看重應(yīng)試者對(duì) 架構(gòu)組件 —— 至少是 MVVM 的理解程度。

像“解耦”等 含糊其辭的說(shuō)法力九,已經(jīng)不能夠被面試官所認(rèn)可耍铜,稍微對(duì) MVVM 有一點(diǎn)經(jīng)驗(yàn)的面試官都會(huì)請(qǐng)你舉例說(shuō)明,好證明你確實(shí)對(duì) MVVM 有著正確跌前、深入的理解棕兼,能夠自然而然地寫(xiě)出標(biāo)準(zhǔn)化、規(guī)范化的代碼抵乓,能夠迅速適應(yīng) 各家公司自制的 自動(dòng)化模版工具伴挚。

本文的目標(biāo)

本人擁有 3 年的 移動(dòng)端架構(gòu) 踐行和設(shè)計(jì)經(jīng)驗(yàn)靶衍,領(lǐng)導(dǎo)或參與團(tuán)隊(duì)重構(gòu)的中大型項(xiàng)目多達(dá)十?dāng)?shù)個(gè),對(duì) Jetpack MVVM 架構(gòu)在確立規(guī)范化茎芋、標(biāo)準(zhǔn)化 開(kāi)發(fā)模式 以減少不可預(yù)期的錯(cuò)誤 所作的努力颅眶,有著深入的理解。

因而本文的目標(biāo)田弥,就是結(jié)合前幾期我們分別 深入淺出 介紹過(guò)的 Lifecycle涛酗、LiveData、ViewModel偷厦、DataBinding煤杀,來(lái)融匯貫通地演繹一下:

作為 應(yīng)用開(kāi)發(fā)骨架 的 標(biāo)準(zhǔn)化狀態(tài)管理框架,究竟為 快速開(kāi)發(fā)過(guò)程中 減少不可預(yù)期的錯(cuò)誤 做了哪些努力沪哺。

不同于 東拼西湊、人云亦云酌儒、徒添困擾 的網(wǎng)文辜妓,愿意將 標(biāo)準(zhǔn)化開(kāi)發(fā)模式的 深度思考知識(shí)實(shí)戰(zhàn)反思經(jīng)驗(yàn) 無(wú)保留地分享,全網(wǎng)僅此一家忌怎。這樣的文章可以說(shuō)是 看一篇籍滴、少一篇,因此榴啸,就算不去 hold 住面試官孽惰,也請(qǐng)務(wù)必跟隨本文的腳步,無(wú)障礙地將 Jetpack MVVM 過(guò)一遍鸥印!

文章目錄一覽

  • 前言
  • 面向標(biāo)準(zhǔn)化開(kāi)發(fā)已成現(xiàn)實(shí)
  • 本文的目標(biāo)
  • Jetpack Lifecycle
    • Lifecycle 存在前的混沌世界
    • Lifecycle 為什么能解決上述這些問(wèn)題勋功?
  • Jetpack LiveData
    • LiveData 存在前的混沌世界
    • LiveData 為什么能解決上述這些問(wèn)題?
    • LiveData 有個(gè)坑需要注意
    • Note 2020.07.09 加餐
  • Jetpack ViewModel
    • ViewModel 存在前的混沌世界
    • ViewModel 為什么能做到這幾點(diǎn)库说?
  • Jetpack DataBinding
    • DataBinding 存在前的混沌世界
    • DataBinding 就是來(lái)解決這些問(wèn)題
  • 綜上

Jetpack Lifecycle

Lifecycle 的存在狂鞋,主要是為了解決 生命周期管理 的一致性問(wèn)題

Lifecycle 存在前的混沌世界

在 Lifecycle 面市前,生命周期管理 純靠手工維持潜的,這樣就容易滋生大量的一致性問(wèn)題骚揍。

例如跨頁(yè)面共享的 GpsManager 組件,在每個(gè)依賴它的 Activity 的 onResume 和 onPause 中都需要 手工 激活啰挪、解綁 和 叫停信不。

那么 隨著 Activity 的增多,這種手工操作 埋下的一致性隱患 就會(huì)指數(shù)級(jí)增長(zhǎng)

一方面亡呵,凡是手工維持的抽活,開(kāi)發(fā)者容易疏忽,特別是工作交接給其他同事時(shí)政己,同事并不能及時(shí)注意到這些細(xì)節(jié)酌壕。

另一方面掏愁,分散的代碼不利于修改,日后除了激活卵牍、叫停果港,若有其他操作需要補(bǔ)充(例如狀態(tài)監(jiān)聽(tīng)),那么每個(gè) Activity 都需要額外書(shū)寫(xiě)一遍糊昙。

Lifecycle 為什么能解決上述這些問(wèn)題辛掠?

Lifecycle 通過(guò) 模板方法模式 和 觀察者模式,將生命周期管理的復(fù)雜操作释牺,全部在作為 LifecycleOwner 的基類中(例如視圖控制器的基類)封裝好萝衩,默默地在背后為開(kāi)發(fā)者運(yùn)籌帷幄,

開(kāi)發(fā)者因而得以在視圖控制器(子類)中只需一句 getLifecycle().addObserver(GpsManager.getInstance) 没咙,優(yōu)雅地完成 第三方組件在自己內(nèi)部 對(duì) LifecycleOwner 生命周期的感知猩谊。

除了解決一致性問(wèn)題,這樣做還 順帶地提供了其他 2 個(gè)好處

1.規(guī)避 為監(jiān)聽(tīng)狀態(tài) 而 注入視圖控制器 的做法

當(dāng)需要監(jiān)聽(tīng)狀態(tài)時(shí)祭刚,以往我們的做法是 通過(guò)方法手工注入 Activity 等參數(shù)牌捷,這埋下了內(nèi)存泄漏的隱患 —— 因?yàn)閳F(tuán)隊(duì)中的新手容易因這是個(gè) Activity,而在日后誤將其依賴給組件中的其他成員涡驮。

現(xiàn)如今暗甥,我們可以直接在組件內(nèi)部 點(diǎn)到為止 地監(jiān)聽(tīng) LifecycleOwner 的狀態(tài),從而規(guī)避這種不恰當(dāng)?shù)氖褂谩?/p>

2.規(guī)避 為追溯事故來(lái)源 而 注入視圖控制器 的做法

當(dāng)發(fā)生事故時(shí)捉捅,以往我們?nèi)粝朐诮M件中 追溯事故來(lái)源撤防,同樣不得不從方法中直接注入 Activity 等,這同樣埋下了內(nèi)存泄漏的隱患“艨冢現(xiàn)如今組件因?qū)崿F(xiàn)了 DefaultLifecycleObserver寄月,而得以通過(guò)生命周期回調(diào)方法中的 LifecycleOwner 參數(shù),在方法作用域中 即可得知事故來(lái)源陌凳,無(wú)需更多帶有隱患的操作剥懒。

如果這么說(shuō)還不理解的話,可具體參考我在 《為你還原一個(gè)真實(shí)的 Jetpack Lifecycle》 中提供的 GpsManager 案例合敦,本文不再累述初橘。

Jetpack LiveData

LiveData 的存在,主要是為了幫助 新手老手 都能不假思索地遵循 通過(guò)唯一可信源分發(fā)狀態(tài) 的標(biāo)準(zhǔn)化開(kāi)發(fā)理念充岛,從而使在快速開(kāi)發(fā)過(guò)程中 難以追溯保檐、難以排查、不可預(yù)期 的問(wèn)題所發(fā)生的概率降低到最小崔梗。

LiveData 存在前的混沌世界

在 LiveData 面市前夜只,我們分發(fā)狀態(tài),多是通過(guò) EventBus 或 Java Interface 來(lái)完成的蒜魄。不管你是用于網(wǎng)絡(luò)請(qǐng)求回調(diào)的情況扔亥,還是跨頁(yè)面通信的情況场躯。

那這造成了什么問(wèn)題呢?首先旅挤,EventBus 只是純粹的 Bus踢关,它 缺乏上述提到的 標(biāo)準(zhǔn)化開(kāi)發(fā)理念 的約束,那么人們?cè)谑褂眠@個(gè)框架時(shí)粘茄,容易因 去中心化 地濫用签舞,而造成 諸如 毫無(wú)防備地收到 預(yù)期外的 不明來(lái)源的推送、拿到過(guò)時(shí)的數(shù)據(jù) 及 事件源追溯復(fù)雜度 為 n2 的局面柒瓣。

并且儒搭,EventBus 本身缺乏 Lifecycle 的加持,存在生命周期管理的一致性問(wèn)題芙贫。這是 EventBus 的硬傷搂鲫,也是我拒絕使用 EventBus 的最主要因素。

對(duì)上述狀況不理解的磺平,可具體參考我在 《LiveData 鮮為人知的 身世背景 和 獨(dú)特使命》 中提供的 播放器狀態(tài)全局通知 的案例

LiveData 為什么能解決上述這些問(wèn)題默穴?

首先,LiveData 是在 Google 希望確立 標(biāo)準(zhǔn)化褪秀、規(guī)范化 的開(kāi)發(fā)模式 —— 這樣一種背景下誕生的,因而為了達(dá)成這個(gè)艱巨的 使命薛训,LiveData 被十分克制地設(shè)計(jì)為媒吗,僅支持狀態(tài)的輸入和監(jiān)聽(tīng),并且可基于 “訪問(wèn)權(quán)限控制” 來(lái)實(shí)現(xiàn) “讀寫(xiě)分離”乙埃。

這使得任何一次數(shù)據(jù)推送闸英,都可被限制為 “只能單方面地從唯一可信源推送而來(lái)”,從而避免了消息同步不一致介袜、不可靠甫何、或是在事件追溯復(fù)雜度為 n2 的迷宮中白費(fèi)時(shí)間。(也即遇伞,無(wú)論是從哪個(gè)視圖控制器發(fā)起的 對(duì)某個(gè)共享狀態(tài)改變的請(qǐng)求辙喂,狀態(tài)最終的改變 都由 作為唯一可信源的 單例或 SharedViewModel 在其內(nèi)部統(tǒng)一決策,并一對(duì)多地通知改變

并且鸠珠,這種承上啟下的方式巍耗,使得單向依賴成為可能:?jiǎn)卫裏o(wú)需通過(guò) Java Interface 回調(diào)通知視圖控制器,從而規(guī)避了視圖控制器 被生命周期更長(zhǎng)的單例 依賴 所埋下的內(nèi)存泄漏的隱患渐排。

LiveData 有個(gè)坑需要注意

不過(guò)炬太,LiveData 的設(shè)計(jì)有個(gè)坑,這里我順帶提一下驯耻。

為了在視圖控制器發(fā)生重建后亲族,能夠 自動(dòng)倒灌 所觀察的 LiveData 的最后一次數(shù)據(jù)炒考,LiveData 被設(shè)計(jì)為粘性事件

—— 我姑且認(rèn)為這是個(gè)拓展性不佳的設(shè)計(jì)霎迫,甚至可以說(shuō)是一個(gè) bug斋枢,

因?yàn)?Jetpack MVVM 是一個(gè)整體,既然 ViewModel 支持共享作用域女气,并且官方文檔都承認(rèn)了通過(guò) 共享 ViewModel 來(lái)實(shí)現(xiàn)跨頁(yè)面通信的需求杏慰,

那么基于 “開(kāi)閉原則”,LiveData 理應(yīng)提供一個(gè)與 MutableLiveData 平級(jí)的底層支持炼鞠,專門(mén)用于非粘性的事件通信的情況缘滥,否則直接在跨頁(yè)面通信中使用 MutableLiveData 必造成 事件回調(diào)的一致性問(wèn)題 及 難以預(yù)期的錯(cuò)誤

《在 SnackBar 和其他事件中使用 LiveData》(SingleLiveEvent 案例)

《LiveDataBus實(shí)現(xiàn)原理#用法詳解#LiveData擴(kuò)展》(反射案例)

無(wú)論是使用哪一種實(shí)現(xiàn)谒主,我都建議 遵循傳統(tǒng) LiveData 所遵循的開(kāi)發(fā)理念朝扼,通過(guò)唯一可信源分發(fā)狀態(tài),來(lái)確保消息同步的可預(yù)期和可追溯霎肯。對(duì)于 “去中心化” 的 Bus 方式擎颖,我拒絕在項(xiàng)目中這樣使用。

Note 2020.07.09 加餐:

Event 包裝器 非入侵重寫(xiě) UnPeekLiveData

考慮到手寫(xiě) Event 事件包裝器观游,在 Java 中存在 null 安全的一致性問(wèn)題搂捧;而反射干預(yù) Version 的方式又存在延遲(無(wú)法用于對(duì)實(shí)時(shí)性有要求的場(chǎng)景)、并且數(shù)據(jù)會(huì)隨著 SharedViewModel 長(zhǎng)久滯留在內(nèi)存中得不到釋放懂缕。

于是重寫(xiě)并封裝了 專用于 “一次性事件” 場(chǎng)景需求UnPeek-LiveData允跑。

UnPeek-LiveData 經(jīng)過(guò)小伙伴們的熱心嘗試和反饋,現(xiàn)已演化成熟并滿足:

  1. 一條消息能被多個(gè)觀察者消費(fèi)

  2. 消息被所有觀察者消費(fèi)完畢后才開(kāi)始阻止倒灌

  3. 可以通過(guò) clear 方法手動(dòng)將消息從內(nèi)存中移除

  4. 讓非入侵設(shè)計(jì)成為可能搪柑,遵循開(kāi)閉原則

  5. 基于 “訪問(wèn)權(quán)限控制” 支持 "讀寫(xiě)分離”聋丝,遵循唯一可信源的消息分發(fā)理念

具體可詳見(jiàn)《LiveData 數(shù)據(jù)倒灌 背景緣由全貌 獨(dú)家解析》篇 及參考 《UnPeek-LiveData》 最新源碼。

Jetpack ViewModel

ViewModel 的存在工碾,主要是為了解決 狀態(tài)管理 和 頁(yè)面通信 的問(wèn)題弱睦。

ViewModel 存在前的混沌世界

ViewModel 的本職工作是 狀態(tài)托管狀態(tài)管理的分治,也即當(dāng)視圖控制器重建時(shí)渊额,

對(duì)于輕量的狀態(tài)况木,可以通過(guò)視圖控制器基類的 saveInstanceState 機(jī)制,以序列化的方式完成存儲(chǔ)和恢復(fù)旬迹。

對(duì)于重量級(jí)的狀態(tài)焦读,例如通過(guò)網(wǎng)絡(luò)請(qǐng)求得到的 List,可以通過(guò)生命周期長(zhǎng)于視圖控制器的 ViewModel 持有舱权,從而得以直接從 ViewModel 恢復(fù)矗晃,而不是以效率較低的序列化方式。

在 Jetpack ViewModel 面市之前宴倍,MVP 的 Presenter 和 MVVM - Clean 的 ViewModel 都不具備狀態(tài)管理分治的能力张症。

Presenter 和 Clean ViewModel 的生命周期都與視圖控制器同生共死仓技,因而它們頂多是為 DataBinding 提供狀態(tài)的托管,而無(wú)法實(shí)現(xiàn)狀態(tài)的分治俗他。

到了 Jetpack 這一版脖捻,ViewModel 以精妙的設(shè)計(jì),達(dá)成了狀態(tài)管理兆衅,以及可共享的作用域地沮。

ViewModel 為什么能做到這幾點(diǎn)?

其實(shí)這版主要是基于 工廠模式羡亩,使得 ViewModel 被 LifecycleOwner 所持有摩疑、通過(guò) ViewModelProvider 來(lái)引用

所以 它既類似于單例:
—— 當(dāng)被作為 LifecycleOwner 的 Activity 持有時(shí)畏铆,能夠脫離 Activity 旗下 Fragment 的生命周期雷袋,從而實(shí)現(xiàn)作用域共享,

實(shí)際上又不是單例:
—— 生命周期跟隨 作為 LifecycleOwner 的視圖控制器辞居,當(dāng) Owner(Activity 或 Fragment)被銷毀時(shí)楷怒,它也被 clear。

此外瓦灶,出于對(duì)視圖控制器重建的考慮鸠删,Google 在視圖控制器基類中通過(guò) retain 機(jī)制對(duì) ViewModel 進(jìn)行了保留。

因此贼陶,對(duì)于 作用域共享 和 視圖重建 的情況冶共,狀態(tài)因完好地被保留,而得以被視圖控制器在恢復(fù)時(shí)直接使用每界。

再者,由于存在 共享作用域的考慮家卖,所以 ViewModel 本身也承擔(dān)了跨頁(yè)面通信(例如事件回調(diào))的職責(zé)眨层。前面在介紹 LiveData 時(shí),對(duì)于 LiveData 在事件通信時(shí)粘性設(shè)計(jì)的問(wèn)題已經(jīng)介紹過(guò)了上荡,這里不再累述趴樱。

截至 2020.2.1,ViewModel 在 Fragment 中的 retain 設(shè)計(jì)已發(fā)生劇變酪捡,具體緣由可參考我在 《有了 Jetpack ViewModel . . . 真的可以為所欲為叁征!》 文末及評(píng)論區(qū)的最新補(bǔ)充。

Jetpack DataBinding

DataBinding 的存在逛薇,主要是為了解決 視圖調(diào)用 的一致性問(wèn)題捺疼。

DataBinding 存在前的混沌世界

在 DataBinding 面市前,我們?nèi)粢淖円晥D的狀態(tài)永罚,首先就要引用該視圖啤呼,例如 textView.setText()卧秘,

這造成什么問(wèn)題呢?

當(dāng)頁(yè)面存在橫官扣、豎布局翅敌,且兩種布局的控件存在差異,例如橫屏存在 textView 控件惕蹄,而豎屏沒(méi)有蚯涮,那么我們就不得不在視圖控制器中為 textView 做判空處理,這就造成了一致性問(wèn)題 —— 容易疏忽而忘記判空卖陵,畢竟頁(yè)面多達(dá)數(shù)十個(gè)遭顶、每個(gè)頁(yè)面的控件也無(wú)數(shù)。

那怎么辦呢赶促?

DataBinding 就是來(lái)解決這些問(wèn)題

通過(guò)讓 “布局中存在的控件” 與 “可觀察的數(shù)據(jù)” 發(fā)生綁定液肌,那么當(dāng)該數(shù)據(jù)被 set 新的內(nèi)容時(shí),被綁定了該數(shù)據(jù)的控件即可獲得通知和刷新鸥滨。

Note 2020.4.18:這一切都是 “編譯時(shí)自動(dòng)生成的中間代碼” 在背后完成的邏輯銜接嗦哆,也即控件如存在于布局中(例如豎屏布局中)且綁定了可觀察數(shù)據(jù),就會(huì)被調(diào)用和通知婿滓,如不存在(例如橫屏布局中)老速,就沒(méi)被調(diào)用,無(wú)論哪一種情況都不至于發(fā)生 null 安全一致性問(wèn)題凸主。

換言之橘券,在使用 DataBinding 后,唯一的改變是卿吐,你無(wú)需手工調(diào)用視圖來(lái) set 新?tīng)顟B(tài)旁舰,你只需 set 數(shù)據(jù)本身。

因而嗡官,DataBinding 并非許多人不假思索認(rèn)為的箭窜,將 UI 邏輯搬到 XML 中寫(xiě) 從而難以調(diào)試 —— 事實(shí)根本不是這樣的:

DataBinding 只負(fù)責(zé)綁定數(shù)據(jù)、負(fù)責(zé)作為 UI 邏輯末端的狀態(tài)的改變(也即它是一個(gè)不可再分的原子操作衍腥,本來(lái)就不需要調(diào)試)磺樱,原本在視圖控制器中 UI 邏輯怎么寫(xiě),現(xiàn)在還是怎么寫(xiě)婆咸,只不過(guò)不再需要 textView.setText(xxx)竹捉,而是直接 xxx.set()。

所以在 DataBinding 的幫助下尚骄,好處總共有多少個(gè)呢块差?

1.規(guī)避了視圖狀態(tài)的 一致性問(wèn)題 —— 無(wú)需手工判空。

2.規(guī)避了視圖狀態(tài)的 一致性問(wèn)題,乃至無(wú)需視圖調(diào)用憾儒,從而完全不用編寫(xiě) findViewById询兴。

3.就算要調(diào)用視圖,也不用 findViewById起趾,而是直接通過(guò) binding 來(lái)引用诗舰。

4.先前的 UI 邏輯基本不用改動(dòng),改的只是作為末端的狀態(tài)改變的方式训裆。

……

此外眶根,DataBinding 有個(gè)大殺器就是,能為控件提供自定義屬性的 BindingAdapter边琉,它不僅可以解決 圓角 Drawable 復(fù)用的問(wèn)題(你懂得)属百,還可以實(shí)現(xiàn) imageView 直接綁定 url 等需求,總之变姨,沒(méi)有它辦不到的族扰,只有你想不到的,DataBinding 的好處等著你挖掘定欧。

關(guān)于 DataBinding 的注意事項(xiàng)渔呵,以及屢試不爽的排坑技巧,可具體參考 《從 被誤解 到 真香 的 Jetpack DataBinding砍鸠!》扩氢,這里不做累述。

綜上

Lifecycle 的存在爷辱,主要是為了解決 生命周期管理 的一致性問(wèn)題录豺。

LiveData 的存在,主要是為了幫助 新手老手 都能不假思索地 遵循 通過(guò)唯一可信源分發(fā)狀態(tài) 的標(biāo)準(zhǔn)化開(kāi)發(fā)理念饭弓,從而在快速開(kāi)發(fā)過(guò)程中 規(guī)避一系列 難以追溯双饥、難以排查、不可預(yù)期 的問(wèn)題弟断。

ViewModel 的存在咏花,主要是為了解決 狀態(tài)管理 和 頁(yè)面通信 的問(wèn)題

DataBinding 的存在夫嗓,主要是為了解決 視圖調(diào)用 的一致性問(wèn)題

它們的存在 大都是為了 在軟件工程的背景下 解決一致性的問(wèn)題冲秽、將容易出錯(cuò)的操作在后臺(tái)封裝好舍咖,方便使用者快速、穩(wěn)定锉桑、不產(chǎn)生預(yù)期外錯(cuò)誤地編碼排霉。

這樣說(shuō),你理解了嗎民轴?

GitHub : Jetpack-MVVM-Best-Practice

版權(quán)聲明

本文以 CC 署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際協(xié)議 發(fā)行攻柠。

Copyright ? 2019-present KunMinX

image

文中提到的 “xxx 架構(gòu)組件的存在球订,主要是為了在 多人協(xié)作的軟件工程背景下 解決 xxx 的一致性問(wèn)題”,以及 “LiveData 在頁(yè)面通信瑰钮、事件回調(diào)的場(chǎng)景下發(fā)生 數(shù)據(jù)倒灌” 等多處 對(duì)特定現(xiàn)象及其本質(zhì)的匹配和概括冒滩,均屬于本人獨(dú)立原創(chuàng)的成果,本人對(duì)此享有所有權(quán)和最終解釋權(quán)浪谴。

當(dāng)您借鑒或引用本文的引言开睡、思路、結(jié)論進(jìn)行二次創(chuàng)作苟耻,或全文轉(zhuǎn)載時(shí)篇恒,須注明鏈接出處,否則我們保留追責(zé)的權(quán)利凶杖。

未經(jīng)與作者本人當(dāng)面溝通許可胁艰,不得將文章內(nèi)容用于洗稿、廣告包裝等商業(yè)用途智蝠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腾么,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子寻咒,更是在濱河造成了極大的恐慌哮翘,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毛秘,死亡現(xiàn)場(chǎng)離奇詭異饭寺,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)叫挟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)艰匙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人抹恳,你說(shuō)我怎么就攤上這事员凝。” “怎么了奋献?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵健霹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我瓶蚂,道長(zhǎng)糖埋,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任窃这,我火速辦了婚禮瞳别,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己祟敛,他們只是感情好疤坝,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著馆铁,像睡著了一般跑揉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叼架,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天畔裕,我揣著相機(jī)與錄音,去河邊找鬼乖订。 笑死扮饶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的乍构。 我是一名探鬼主播甜无,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼哥遮!你這毒婦竟也來(lái)了岂丘?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤眠饮,失蹤者是張志新(化名)和其女友劉穎奥帘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體仪召,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寨蹋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扔茅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片已旧。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖召娜,靈堂內(nèi)的尸體忽然破棺而出运褪,到底是詐尸還是另有隱情,我是刑警寧澤玖瘸,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布秸讹,位于F島的核電站,受9級(jí)特大地震影響雅倒,放射性物質(zhì)發(fā)生泄漏璃诀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一屯断、第九天 我趴在偏房一處隱蔽的房頂上張望文虏。 院中可真熱鬧,春花似錦殖演、人聲如沸氧秘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)丸相。三九已至,卻和暖如春彼棍,著一層夾襖步出監(jiān)牢的瞬間灭忠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工座硕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弛作,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓华匾,卻偏偏與公主長(zhǎng)得像映琳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜘拉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

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