@linux1s1s
2017-01-22T08:50:37.000000Z
字数 2602
阅读 3309
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))
这样就可以全局避免内存泄露。
