@linux1s1s
2017-01-22T16:50:37.000000Z
字数 2602
阅读 2960
AndroidMemory
2016-06
在App开发中,一般都会使用自定义的字体,这些字体美化App的同时,可能还会带来额外的问题,最容易带来的问题就是内存泄露,这里举个实际中遇到的问题作为例子
如果需要在Title、Price上做自定义字体。假如我们这么处理这个需求
Typeface tf=Typeface.createFromAsset(getAssets(), Consts.LANTING_FONT_PATH);
title.setTypeface(tf);
Typeface tf=Typeface.createFromAsset(getAssets(), Consts.LANTING_FONT_PATH);
price.setTypeface(tf);
像上面这么处理,进入这个页面以后,在滚动View的时候会明显卡顿 1S左右, 用户体验相当不好。
接下来看看问题在哪里
跑monkey测试:
adb shell dumpsys meminfo 【packgename】
此命令会打出当前应用内存占用情况,如下:
注意很明显的/assets/fonts/fzlthjw.ttf 出现的N多次,而且每次都是2,M多,这个内存占用相当的恐怖了,很明显出现了内存泄露
那么该如何解决?
解决的办法比较简单,因为 Typeface.createFromAsset(...)是个高消耗方法,缓存使用即可。
比如像这样:
protected static final Typeface TYPEFACE = Typeface.createFromAsset(
application.getAssets(), "fonts/fzlthjw.ttf");
titile.setTypeface(TYPEFACE );
price.setTypeface(TYPEFACE );
然后我们再次用monkey测试一下:
问题得以解决
不过建议上面的Typeface用Manager管理起来,防止不恰当使用引起内存泄露,下面给个简单的Manager类以供参考:
import java.util.HashMap;
import java.util.Map;
import android.app.Application;
import android.content.res.AssetManager;
import android.graphics.Typeface;
public class FontManager {
private static FontManager FONT_MANAGER;
private AssetManager mAssetManager;
private static final Map<String, Typeface> CACHE_FONT_MAP = new HashMap<String, Typeface>();
private FontManager(Application application) {
mAssetManager = application.getAssets();
}
public static void createInstance(Application application) {
if (FONT_MANAGER == null) {
synchronized (FontManager.class) {
if (FONT_MANAGER == null) {
FONT_MANAGER = new FontManager(application);
}
}
}
}
public static FontManager getInstance() {
if (FONT_MANAGER == null) {
throw new NullPointerException("NullPoint Exception, Please call createInstance first!");
}
return FONT_MANAGER;
}
public Typeface getFont(FontType type) {
if (type == null) {
return null;
}
final String key = type.getValue();
Typeface typeface = null;
switch (type) {
case TANG_SH:
if (CACHE_FONT_MAP.containsKey(key)) {
return CACHE_FONT_MAP.get(key);
} else {
typeface = Typeface.createFromAsset(mAssetManager, "fonts/fzlthjw.ttf");
CACHE_FONT_MAP.put(key, typeface);
}
break;
default:
break;
}
return typeface;
}
public static enum FontType {
TANG_SH("tang_sh");
String value;
FontType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
// -----------------------------------------------------------------------
// Convenient
// -----------------------------------------------------------------------
public static class FLFont {
public static Typeface getFont(FontType type) {
try {
FontManager manager = FontManager.getInstance();
return manager.getFont(type);
} catch (NullPointerException e) {
e.printStackTrace();
}
return null;
}
}
}
调用的时候在Application中初始化一次
FontManager.createInstance(this);
然后在使用的时候:
title.setTypeface(FLFont.getFont(FontType.TANG_SH))
这样就可以全局避免内存泄露。