用于设置自定义字体的自定义字体的内存泄漏

Posted

技术标签:

【中文标题】用于设置自定义字体的自定义字体的内存泄漏【英文标题】:Memory leaks with custom font for set custom font 【发布时间】:2013-05-29 21:50:51 【问题描述】:

以下用于设置自定义字体的代码会降低我的整个应用程序的速度。如何修改它以避免内存泄漏并提高速度和管理内存?

public class FontTextView extends TextView 
    private static final String TAG = "FontTextView";

    public FontTextView(Context context) 
        super(context);
    

    public FontTextView(Context context, AttributeSet attrs) 
        super(context, attrs);
        setCustomFont(context, attrs);
    

    public FontTextView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    

    private void setCustomFont(Context ctx, AttributeSet attrs) 
        TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.FontTextView);
        String customFont = a.getString(R.styleable.FontTextView_customFont);
        setCustomFont(ctx, customFont);
        a.recycle();
    

    public boolean setCustomFont(Context ctx, String asset) 
        Typeface tf = null;
        try 
        tf = Typeface.createFromAsset(ctx.getAssets(),"fonts/"+ asset);  
         catch (Exception e) 
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        

        setTypeface(tf);  
        return true;
    
    

【问题讨论】:

【参考方案1】:

你应该缓存字体,否则you might risk memory leaks on older handsets。缓存也会提高速度,因为从资源中读取并不是非常快。

public class FontCache 

    private static Hashtable<String, Typeface> fontCache = new Hashtable<String, Typeface>();

    public static Typeface get(String name, Context context) 
        Typeface tf = fontCache.get(name);
        if(tf == null) 
            try 
                tf = Typeface.createFromAsset(context.getAssets(), name);
            
            catch (Exception e) 
                return null;
            
            fontCache.put(name, tf);
        
        return tf;
    

我给了full example on how to load custom fonts and style textviews as an answer to a similar question。您似乎大部分都做对了,但您应该按照上面的建议缓存字体。

【讨论】:

如何在 setcustomfont 的 nmy 代码中调用 fontcache?我每次尝试都做不好 替换 tf = Typeface.createFromAsset(ctx.getAssets(),"fonts/"+asset); with tf = FontCache.get("fonts/" + assets, ctx); 有理由使用Hashtable吗?如果没有,ArrayMap 可能是更好的类型,因为内存消耗和迭代速度更低。 其实我并没有过多考虑数据结构的选择。 ArrayMap 可能工作得同样好或更好! 我不确定是否总是这样,但createFromAsset() 方法已经使用动态LruCache 来存储每个Typeface。这种方法通过创建第二个缓存来浪费资​​源。【参考方案2】:

我觉得不需要使用字体缓存。我们可以这样做吗?

对以上代码稍作改动,如有错误请指正。

public class FontTextView extends TextView 
    private static final String TAG = "FontTextView";
    private static Typeface mTypeface;

    public FontTextView(Context context) 
        super(context);
    

    public FontTextView(Context context, AttributeSet attrs) 
        super(context, attrs);
    

    public FontTextView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
        if (mTypeface == null) 
            mTypeface = Typeface.createFromAsset(context.getAssets(),   GlobalConstants.SECONDARY_TTF);
        
        setTypeface(mTypeface);
    

    

【讨论】:

如果你只有一个字体,这个解决方案可以工作。其他解决方案更适合多种字体情况。 是的,但我认为不建议为单个 android 应用程序使用更多字体。? 我从未听说过这样的事情。如果您有资源,我想阅读

以上是关于用于设置自定义字体的自定义字体的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

iPhone中的自定义字体

Xcode 6 大小类中的自定义字体大小无法与自定义字体一起正常工作

ios:自定义字体的字距调整

Bold / Italic不适用于使用PhantomJS的自定义字体

如何在iOS中将具有特定大小的自定义字体设置为Web View?

Android API中的自定义字体低于16?