使用自定义字体会导致内存泄漏问题,如何设置自定义字体?

46

以下是设置自定义字体的代码,它使我的整个应用程序变慢。我应该如何修改它以避免内存泄漏并提高速度和良好地管理内存?

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;
    }
    }
2个回答

122
你应该缓存TypeFace,否则在旧型号的手机上可能会出现内存泄漏的风险。缓存还可以提高速度,因为从资源中读取不是非常快。
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;
    }
}

我曾经在回答一个类似的问题时给出了一个完整的加载自定义字体和样式文本视图的示例。你似乎大部分做得都对,但最好按上面建议的缓存字体。

我在我的代码中如何调用FontCache来设置自定义字体?每次尝试都无法正确实现。 - user2386226
7
请用以下翻译替换原文中的英文内容:“将 tf = Typeface.createFromAsset(ctx.getAssets(),"fonts/"+ asset); 替换为 tf = FontCache.get("fonts/" + asset, ctx);” - britzl
1
有使用Hashtable的原因吗?如果没有,由于内存消耗和迭代速度较低,ArrayMap可能是更好的类型。 - wilkas
我其实并没有在数据结构的选择上多加思考。ArrayMap 也许同样适用甚至更好! - britzl
我不确定这是否一直是这种情况,但 createFromAsset() 方法已经使用动态 LruCache 来存储每个 Typeface。该方法通过创建第二个缓存浪费资源。 - Bryan
使用Calligraphy库来处理字体要比这个解决方案好得多。 - blueware

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);
    }

    }

1
如果您只使用一种字体,这个解决方案就可以。对于多种字体情况,其他解决方案更好。 - Gokhan Arik
1
是的,但我认为单个Android应用程序不建议有更多的字体。 - Manikanta
1
我从未听说过这样的事情。如果您有资源,我想阅读。 - Gokhan Arik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接