內存優化,避免OOM總結

轉載: 原文地址:http://www.csdn.net/article/2015-09-18/2825737/3

減小對象的內存占用

避免OOM的第一步就是要盡量減少新分配出來的對象占用內存的大小,盡量使用更加輕量的對象。

1)使用更加輕量的數據結構
例如,我們可以考慮使用ArrayMap/SparseArray而不是HashMap等傳統數據結構。圖8演示了HashMap 的簡要工作原理,相比起Android專門為移動操作系統編寫的ArrayMap容器,在大多數情況下,都顯示效率低下,更占內存。通常的HashMap 的實現方式更加消耗內存,因為它需要一個額外的實例對象來記錄Mapping操作。另外,SparseArray更加高效,在于他們避免了對key與 value的自動裝箱(autoboxing),并且避免了裝箱后的解箱。

55fbd7593533f.jpg.png

圖8 HashMap簡要工作原理
關于更多ArrayMap/SparseArray的討論,請參考《 Android性能優化典范(三)》的前三個段落。

2)避免在Android里面使用Enum

Android官方培訓課程提到過“Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.”,具體原理請參考《Android性能優化典范(三)》,所以請避免在Android里面使用到枚舉。

3)減小Bitmap對象的內存占用

Bitmap是一個極容易消耗內存的大胖子,減小創建出來的Bitmap的內存占用可謂是重中之重,通常來說有以下2個措施:
inSampleSize:縮放比例,在把圖片載入內存之前,我們需要先計算出一個合適的縮放比例,避免不必要的大圖載入。
decode format:解碼格式,選擇ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差異。

4)使用更小的圖片

在涉及給到資源圖片時,我們需要特別留意這張圖片是否存在可以壓縮的空間,是否可以使用更小的圖片。盡量使用更小的圖片不 僅可以減少內存的使用,還能避免出現大量的InflationException。假設有一張很大的圖片被XML文件直接引用,很有可能在初始化視圖時會 因為內存不足而發生InflationException,這個問題的根本原因其實是發生了OOM。

內存對象的重復利用

大多數對象的復用,最終實施的方案都是利用對象池技術,要么是在編寫代碼時顯式地在程序里創建對象池,然后處理好復用的實現邏輯。要么就是利用系統框架既有的某些復用特性,減少對象的重復創建,從而降低內存的分配與回收(如圖9所示)。


55fbd7ecee68b.jpg

圖9 對象池技術
在Android上面最常用的一個緩存算法是LRU(Least Recently Use),簡要操作原理如圖10所示。

55fbdb10dac05.jpg

圖10 LRU簡要操作原理

1)復用系統自帶的資源

Android系統本身內置了很多的資源,比如字符串、顏色、圖片、動畫、樣式以及簡單布局等,這些資源都可以在 應用程序中直接引用。這樣做不僅能減少應用程序的自身負重,減小APK的大小,還可以在一定程度上減少內存的開銷,復用性更好。但是也有必要留意 Android系統的版本差異性,對那些不同系統版本上表現存在很大差異、不符合需求的情況,還是需要應用程序自身內置進去。

2)注意在ListView/GridView等出現大量重復子組件的視圖里對ConvertView的復用,如圖11所示。

55fbdb3867f9f.jpg.png

3)Bitmap對象的復用
在ListView與GridView等顯示大量圖片的控件里,需要使用LRU的機制來緩存處理好的Bitmap,如圖12所示。

55fbdd4cd635a.jpg

圖12
利用inBitmap的高級特性提高Android系統在Bitmap分配與釋放執行效率(注:3.0以及4.4以后存在一些使用限制上的差異)。使 用inBitmap屬性可以告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的Bitmap會嘗試去使用之前那張Bitmap在Heap中所 占據的pixel data內存區域,而不是去問內存重新申請一塊區域來存放Bitmap。利用這種特性,即使是上千張的圖片,也只會僅僅只需要占用屏幕所能夠顯示的圖片數 量的內存大小,如圖13所示。

55fbdebd4397f.jpg

圖13 利用inBitmap的高級特性提高Android在Bitmap分配與釋放執行效率
使用inBitmap需要注意幾個限制條件:

在SDK 11 -> 18之間,重用的Bitmap大小必須是一致的。例如給inBitmap賦值的圖片大小為100-100,那么新申請的Bitmap必須也為 100-100才能夠被重用。從SDK 19開始,

新申請的Bitmap大小必須小于或者等于已經賦值過的Bitmap大小。新申請的 Bitmap與舊的Bitmap必須有相同的解碼格式。例如大家都是8888的,如果前面的Bitmap是8888,那么就不能支持4444與565格式 的Bitmap了。我們可以創建一個包含多種典型可重用Bitmap的對象池,這樣后續的Bitmap創建都能夠找到合適的“模板”去進行重用,如圖14 所示。

55fbdf583ce78.jpg

另外,在2.x的系統上,盡管Bitmap是分配在Native層,但還是無法避免被計算到OOM的引用計數器 里。這里提示一下,不少應用會通過反射vBitmapFactory.Options里面的inNativeAlloc來達到擴大使用內存的目的,但是如 果大家都這么做,對系統整體會造成一定的負面影響,建議謹慎采納。

4)避免在onDraw方法里面執行對象的創建
類似onDraw等頻繁調用的方法,一定需要注意避免在這里做創建對象的操作,因為他會迅速增加內存的使用,而且很容易引起頻繁的gc,甚至是內存抖動。

5)StringBuilder
在有些時候,代碼中會需要使用到大量的字符串拼接的操作,這種時候有必要考慮使用StringBuilder來替代頻繁的“+”。

避免對象的內存泄露

內存對象的泄漏,會導致一些不再使用的對象無法及時釋放,這樣一方面占用了寶貴的內存空間,很容易導致后續需要分 配內存的時候,空閑空間不足而出現OOM。顯然,這還使得每級Generation的內存區域可用空間變小,GC就會更容易被觸發,容易出現內存抖動,從 而引起性能問題(如圖15所示)。

55fbdff8e22b2.jpg

最新的LeakCanary開源控件,可以很好的幫助我們發現內存泄露的情況,更多關于LeakCanary的介紹,請看 這里中文使用說明)。另外也可以使用傳統的MAT工具查找內存泄露,請參考 這里便捷的中文資料)。

1)注意Activity的泄漏
通常來說,Activity的泄漏是內存泄漏里面最嚴重的問題,它占用的內存多,影響面廣,我們需要特別注意以下兩種情況導致的Activity泄漏:

內部類引用導致Activity的泄漏

最典型的場景是Handler導致的Activity泄漏,如果Handler中有延遲的任務或者是等待執行的任務隊列過長,都有可能因為Handler繼續執行而導致Activity發生泄漏。此時的引用關系鏈是Looper -> MessageQueue -> Message -> Handler -> Activity。為了解決這個問題,可以在UI退出之前,執行remove Handler消息隊列中的消息與runnable對象。或者是使用Static + WeakReference的方式來達到斷開Handler與Activity之間存在引用關系的目的。
Activity Context被傳遞到其他實例中,這可能導致自身被引用而發生泄漏。

內部類引起的泄漏不僅僅會發生在Activity上,其他任何內部類出現的地方,都需要特別留意!我們可以考慮盡量使用static類型的內部類,同時使用WeakReference的機制來避免因為互相引用而出現的泄露。

2)考慮使用Application Context而不是Activity Context
對于大部分非必須使用Activity Context的情況(Dialog的Context就必須是Activity Context),我們都可以考慮使用Application Context而不是Activity的Context,這樣可以避免不經意的Activity泄露。

3)注意臨時Bitmap對象的及時回收
雖然在大多數情況下,我們會對Bitmap增加緩存機制,但是在某些時候,部分Bitmap是需要及時回 收的。例如臨時創建的某個相對比較大的bitmap對象,在經過變換得到新的bitmap對象之后,應該盡快回收原始的bitmap,這樣能夠更快釋放原 始bitmap所占用的空間。
需要特別留意的是Bitmap類里面提供的createBitmap()方法,如圖16所示:

55fbe0a8985ab.jpg.png

這個函數返回的bitmap有可能和source bitmap是同一個,在回收的時候,需要特別檢查source bitmap與return bitmap的引用是否相同,只有在不等的情況下,才能夠執行source bitmap的recycle方法。

4)注意監聽器的注銷

在Android程序里面存在很多需要register與unregister的監聽器,我們需要確保在合適的時候及時unregister那些監聽器。自己手動add的listener,需要記得及時remove這個listener。

5)注意緩存容器中的對象泄漏

有時候,我們為了提高對象的復用性把某些對象放到緩存容器中,可是如果這些對象沒有及時從容器中清除,也 是有可能導致內存泄漏的。例如,針對2.3的系統,如果把drawable添加到緩存容器,因為drawable與View的強應用,很容易導致 activity發生泄漏。而從4.0開始,就不存在這個問題。解決這個問題,需要對2.3系統上的緩存drawable做特殊封裝,處理引用解綁的問 題,避免泄漏的情況。

6)注意WebView的泄漏

Android中的WebView存在很大的兼容性問題,不僅僅是Android系統版本的不同對WebView產生很大的差異,另外不同的廠商出貨的ROM里面WebView也存在著很大的差異。更嚴重的是標準的WebView存在內存泄露的問題,請看 這里。所以通常根治這個問題的辦法是為WebView開啟另外一個進程,通過AIDL與主進程進行通信,WebView所在的進程可以根據業務的需要選擇合適的時機進行銷毀,從而達到內存的完整釋放。

7)注意Cursor對象是否及時關閉

在程序中我們經常會進行查詢數據庫的操作,但時常會存在不小心使用Cursor之后沒有及時關閉的情況。這些Cursor的泄露,反復多次出現的話會對內存管理產生很大的負面影響,我們需要謹記對Cursor對象的及時關閉。

內存使用策略優化

1)謹慎使用large heap

正如前面提到的,Android設備根據硬件與軟件的設置差異而存在不同大小的內存空間,他們為應用程序 設置了不同大小的Heap限制閾值。你可以通過調用getMemoryClass()來獲取應用的可用Heap大小。在一些特殊的情景下,你可以通過在 manifest的application標簽下添加largeHeap=true的屬性來為應用聲明一個更大的heap空間。然后,你可以通過 getLargeMemoryClass()來獲取到這個更大的heap size閾值。然而,聲明得到更大Heap閾值的本意是為了一小部分會消耗大量RAM的應用(例如一個大圖片的編輯應用)。不要輕易的因為你需要使用更多 的內存而去請求一個大的Heap Size。只有當你清楚的知道哪里會使用大量的內存并且知道為什么這些內存必須被保留時才去使用large heap。因此請謹慎使用large heap屬性。使用額外的內存空間會影響系統整體的用戶體驗,并且會使得每次gc的運行時間更長。在任務切換時,系統的性能會大打折扣。另外, large heap并不一定能夠獲取到更大的heap。在某些有嚴格限制的機器上,large heap的大小和通常的heap size是一樣的。因此即使你申請了large heap,你還是應該通過執行getMemoryClass()來檢查實際獲取到的heap大小。

2)綜合考慮設備內存閾值與其他因素設計合適的緩存大小

例如,在設計ListView或者GridView的Bitmap LRU緩存的時候,需要考慮的點有:

應用程序剩下了多少可用的內存空間?

有多少圖片會被一次呈現到屏幕上?有多少圖片需要事先緩存好以便快速滑動時能夠立即顯示到屏幕?

設備的屏幕大小與密度是多少? 一個xhdpi的設備會比hdpi需要一個更大的Cache來hold住同樣數量的圖片。

不同的頁面針對Bitmap的設計的尺寸與配置是什么,大概會花費多少內存?

頁面圖片被訪問的頻率?是否存在其中的一部分比其他的圖片具有更高的訪問頻繁?如果是,也許你想要保存那些最常訪問的到內存中,或者為不同組別的位圖(按訪問頻率分組)設置多個LruCache容器。

3)onLowMemory()與onTrimMemory()

Android用戶可以隨意在不同的應用之間進行快速切換。為了讓background的應用能夠迅速的 切換到forground,每一個background的應用都會占用一定的內存。Android系統會根據當前的系統的內存使用情況,決定回收部分 background的應用內存。如果background的應用從暫停狀態直接被恢復到forground,能夠獲得較快的恢復體驗,如果 background應用是從Kill的狀態進行恢復,相比之下就顯得稍微有點慢,如圖17所示。

55fbe128e9918.jpg

onLowMemory():Android 系統提供了一些回調來通知當前應用的內存使用情況,通常來說,當所有的background應用都被kill掉的時候,forground應用會收到 onLowMemory()的回調。在這種情況下,需要盡快釋放當前應用的非必須的內存資源,從而確保系統能夠繼續穩定運行。
onTrimMemory(int):Android 系統從4.0開始還提供了onTrimMemory()的回調,當系統內存達到某些條件的時候,所有正在運行的應用都會收到這個回調,同時在這個回調里面 會傳遞以下的參數,代表不同的內存使用情況,收到onTrimMemory()回調的時候,需要根據傳遞的參數類型進行判斷,合理的選擇釋放自身的一些內 存占用,一方面可以提高系統的整體運行流暢度,另外也可以避免自己被系統判斷為優先需要殺掉的應用。
TRIM_MEMORY_UI_HIDDEN:你的應用程序的所有UI界面被隱藏了,即用戶點擊了Home鍵或者Back鍵退出應用,導致應用的UI界面完全不可見。這個時候應該釋放一些不可見的時候非必須的資源

當程序正在前臺運行的時候,可能會接收到從onTrimMemory()中返回的下面的值之一:
TRIM_MEMORY_RUNNING_MODERATE:你的應用正在運行并且不會被列為可殺死的。但是設備此時正運行于低內存狀態下,系統開始觸發殺死LRU Cache中的Process的機制。
TRIM_MEMORY_RUNNING_LOW:你的應用正在運行且沒有被列為可殺死的。但是設備正運行于更低內存的狀態下,你應該釋放不用的資源用來提升系統性能。
TRIM_MEMORY_RUNNING_CRITICAL:你 的應用仍在運行,但是系統已經把LRU Cache中的大多數進程都已經殺死,因此你應該立即釋放所有非必須的資源。如果系統不能回收到足夠的RAM數量,系統將會清除所有的LRU緩存中的進 程,并且開始殺死那些之前被認為不應該殺死的進程,例如那個包含了一個運行態Service的進程。
當應用進程退到后臺正在被Cached的時候,可能會接收到從onTrimMemory()中返回的下面的值之一:
TRIM_MEMORY_BACKGROUND: 系 統正運行于低內存狀態并且你的進程正處于LRU緩存名單中最不容易殺掉的位置。盡管你的應用進程并不是處于被殺掉的高危險狀態,系統可能已經開始殺掉 LRU緩存中的其他進程了。你應該釋放那些容易恢復的資源,以便于你的進程可以保留下來,這樣當用戶回退到你的應用的時候才能夠迅速恢復。
TRIM_MEMORY_MODERATE: 系統正運行于低內存狀態并且你的進程已經已經接近LRU名單的中部位置。如果系統開始變得更加內存緊張,你的進程是有可能被殺死的。
TRIM_MEMORY_COMPLETE: 系統正運行于低內存的狀態并且你的進程正處于LRU名單中最容易被殺掉的位置。你應該釋放任何不影響你的應用恢復狀態的資源。

55fbe1931f9d5.jpg

因為onTrimMemory()的回調是在API 14才被加進來的,對于老的版本,你可以使用onLowMemory)回調來進行兼容。onLowMemory相當與TRIM_MEMORY_COMPLETE。
請注意:當系統開始清除LRU緩存中的進程時,雖然它首先按照LRU的順序來執行操作,但是它同樣會考慮進程的內存使用量以及其他因素。占用越少的進程越容易被留下來。

4)資源文件需要選擇合適的文件夾進行存放

我們知道hdpi/xhdpi/xxhdpi等等不同dpi的文件夾下的圖片在不同的設備上會經 過scale的處理。例如我們只在hdpi的目錄下放置了一張100100的圖片,那么根據換算關系,xxhdpi的手機去引用那張圖片就會被拉伸到 200200。需要注意到在這種情況下,內存占用是會顯著提高的。對于不希望被拉伸的圖片,需要放到assets或者nodpi的目錄下。

5)Try catch某些大內存分配的操作

在某些情況下,我們需要事先評估那些可能發生OOM的代碼,對于這些可能發生OOM的代碼,加入catch機制,可以考慮在catch里面嘗試一次降級的內存分配操作。例如decode bitmap的時候,catch到OOM,可以嘗試把采樣比例再增加一倍之后,再次嘗試decode。

6)謹慎使用static對象

因為static的生命周期過長,和應用的進程保持一致,使用不當很可能導致對象泄漏,在Android中應該謹慎使用static對象(如圖19所示)。

55fbe22546ba6.jpg

7)特別留意單例對象中不合理的持有

雖然單例模式簡單實用,提供了很多便利性,但是因為單例的生命周期和應用保持一致,使用不合理很容易出現持有對象的泄漏。

8)珍惜Services資源

如果你的應用需要在后臺使用service,除非它被觸發并執行一個任務,否則其他時候 Service都應該是停止狀態。另外需要注意當這個service完成任務之后因為停止service失敗而引起的內存泄漏。 當你啟動一個Service,系統會傾向為了保留這個Service而一直保留Service所在的進程。這使得進程的運行代價很高,因為系統沒有辦法把 Service所占用的RAM空間騰出來讓給其他組件,另外Service還不能被Paged out。這減少了系統能夠存放到LRU緩存當中的進程數量,它會影響應用之間的切換效率,甚至會導致系統內存使用不穩定,從而無法繼續保持住所有目前正在 運行的service。 建議使用 IntentService,它會在處理完交代給它的任務之后盡快結束自己。更多信息,請閱讀 Running in a Background Service

9)優化布局層次,減少內存消耗

越扁平化的視圖布局,占用的內存就越少,效率越高。我們需要盡量保證布局足夠扁平化,當使用系統提供的View無法實現足夠扁平的時候考慮使用自定義View來達到目的。

10)謹慎使用“抽象”編程

很多時候,開發者會使用抽象類作為”好的編程實踐”,因為抽象能夠提升代碼的靈活性與可維護性。然而,抽象會導致一個顯著的額外內存開銷:他們需要同等量的代碼用于可執行,那些代碼會被mapping到內存中,因此如果你的抽象沒有顯著的提升效率,應該盡量避免他們。

11)使用nano protobufs序列化數據

Protocol buffers是由Google為序列化結構數據而設計的,一種語言無關,平臺無關,具有良好的擴展性。類似XML,卻比XML更加輕量,快速,簡單。如果你需要為你的數據實現序列化與協議化,建議使用nano protobufs。關于更多細節,請參考 protobuf readme的”Nano version”章節。

12)謹慎使用依賴注入框架

使用類似Guice或者RoboGuice等框架注入代碼,在某種程度上可以簡化你的代碼.

13)謹慎使用多進程

使用多進程可以把應用中的部分組件運行在單獨的進程當中,這樣可以擴大應用的內 存占用范圍,但是這個技術必須謹慎使用,絕大多數應用都不應該貿然使用多進程,一方面是因為使用多進程會使得代碼邏輯更加復雜,另外如果使用不當,它可能 反而會導致顯著增加內存。當你的應用需要運行一個常駐后臺的任務,而且這個任務并不輕量,可以考慮使用這個技術。
一個典型的例子是創建一個可以長時間后臺播放的Music Player。如果整個應用都運行在一個進程中,當后臺播放的時候,前臺的那些UI資源也沒有辦法得到釋放。類似這樣的應用可以切分成2個進程:一個用來操作UI,另外一個給后臺的Service。

14)使用ProGuard來剔除不需要的代碼

ProGuard能夠通過移除不需要的代碼,重命名類,域與方法等等對代碼進行壓縮,優化與混淆。使用ProGuard可以使得你的代碼更加緊湊,這樣能夠減少mapping代碼所需要的內存空間。

15)謹慎使用第三方libraries

很多開源的library代碼都不是為移動網絡環境而編寫的,如果運用在移動設 備上,并不一定適合。即使是針對Android而設計的library,也需要特別謹慎,特別是在你不知道引入的library具體做了什么事情的時候。 例如,其中一個library使用的是nano protobufs, 而另外一個使用的是micro protobufs。這樣一來,在你的應用里面就有2種protobuf的實現方式。這樣類似的沖突還可能發生在輸出日志,加載圖片,緩存等等模塊里面。 另外不要為了1個或者2個功能而導入整個library,如果沒有一個合適的庫與你的需求相吻合,你應該考慮自己去實現,而不是導入一個大而全的解決方 案。

16)考慮不同的實現方式來優化內存占用

在某些情況下,設計的某個方案能夠快速實現需求,但是這個方案卻可能在內存占用上表現的效率不夠好。例如:

55fbe2be82985.jpg

對于上面這樣一個時鐘表盤的實現,最簡單的就是使用很多張包含指針的表盤圖片, 使用幀動畫實現指針的旋轉。但是如果把指針扣出來,單獨進行旋轉繪制,顯然比載入N多張圖片占用的內存要少很多。當然這樣做,代碼復雜度上會有所增加,這 里就需要在優化內存占用與實現簡易度之間進行權衡了。

總結

設計風格很大程度上會影響到程序的內存與性能,相對來說,如果大量使用類似Material Design的風格,不僅安裝包可以變小,還可以減少內存的占用,渲染性能與加載性能都會有一定的提升。

內存優化并不就是說程序占用的內存越少就越好,如果因為想要保持更低的內存占用,而頻繁觸發執行gc操作,在某種程度上反而會導致應用性能整體有所下降,這里需要綜合考慮做一定的權衡。

Android的內存優化涉及的知識面還有很多:內存管理的細節,垃圾回收的工作原理,如何查找內存泄漏等等都可以展開講很多。OOM是內存優化當中比較突出的一點,盡量減少OOM的概率對內存優化有著很大的意義。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,808評論 25 708
  • 本文轉載來源 http://www.csdn.net/article/2015-09-18/2825737/1 (...
    yoosir閱讀 1,124評論 0 5
  • HereAndroid的內存優化是性能優化中很重要的一部分,而避免OOM又是內存優化中比較核心的一點。這是一篇關于...
    HarryXR閱讀 3,841評論 1 24
  • Android內存優化是性能優化很重要的一部分,而如何避免OOM又是內存優化的核心。 Android內存管理機制 ...
    lwwlsky閱讀 20,002評論 4 46
  • 平常工作中總是會在一些網頁上發現一些自己感興趣的東西,或者需要自己去了解、去學習的內容,但是由于上班期間不能詳細查...
    左岸浪人閱讀 288評論 0 1