背景
ES 加入新文件提醒功能模塊廢棄了使用 mediastore 來查找所有文件册养,而是基于 android 底層的文件系統(tǒng)自己實現(xiàn)了一套全盤掃描監(jiān)控文件的方案。
這種方案可以更方便的處理和監(jiān)控文件的變化咆爽,但由于涉及到全盤掃描,對于數(shù)據(jù)量龐大的文件來說置森,內(nèi)存占用是很大的一個挑戰(zhàn)斗埂。
android 的內(nèi)存碎片和 OutOfMemoryError
OutOfMemoryError 不一定是內(nèi)存不足!Y旌!呛凶!
ES 的文件掃描方案分配和使用了大量的對象,由于5.0以前的系統(tǒng)(dalvik 虛擬機)的內(nèi)存回收算法會造成大量的內(nèi)存碎片行贪,經(jīng)過一段時間的運行后出現(xiàn)內(nèi)存不足的 Error漾稀。(android GC 見末尾的文章參考)
StringBuilderHelper 減少碎片產(chǎn)生
在做內(nèi)存優(yōu)化的時候用到了一個小功能函數(shù)解決一個大問題模闲。
/**
* 重復(fù)利用 StringBuild 的內(nèi)存區(qū)域,減少 enlargeBuffer 造成的內(nèi)存碎片
*/
public class StringBuilderHelper {
private static final ThreadLocal<StringBuilder> threadLocalStringBuilder = new ThreadLocal<StringBuilder>() {
@Override
protected StringBuilder initialValue() {
return new StringBuilder(256);
}
};
public static StringBuilder getThreadLocalStringBuilder() {
StringBuilder sb = threadLocalStringBuilder.get();
sb.setLength(0);
return sb;
}
}
將所有 StringBuilder sb = ew StringBuilder();
替換成
StringBuilder sb = StringBuilderHelper.getThreadLocalStringBuilder();
和 StringBuilder 一樣使用即可县好。
在一臺沒有太多文件的手機上對比围橡,StringBuilderHelper 減少了 300K 的內(nèi)存占用。