Compaq LE2202x Compaq LE2202x - 5 months ago 89
Android Question

RuntimeException: native typeface cannot be made or memory leak for custom TextView loading font

There's a HUGE problem in my code wherein I am loading a font in my

assets\fonts\
folder from a custom
TextView
class. The first problem is that it crashes on 4.0 devices with the exception
Caused by: java.lang.RuntimeException: native typeface cannot be made
. I was using the same process here with the method:

public class MyTextView extends TextView {

public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public MyTextView(Context context) {
super(context);
}


public void setTypeface(Typeface tf, int style) {
if (style == Typeface.BOLD) {
super.setTypeface(Typeface.createFromAsset(
getContext().getAssets(), "fonts/hirakakupronbold.ttf"));
} else if (style == Typeface.ITALIC) {
super.setTypeface(Typeface.createFromAsset(
getContext().getAssets(), "fonts/hirakakupronitalic.ttf"));
} else {
super.setTypeface(Typeface.createFromAsset(
getContext().getAssets(), "fonts/hirakakupron.ttf"));
}
}
}


Notice that I'm using the extension
.ttf
, and I found that this is causing the
RunTimeException
. So I converted the respective fonts with a
.otf
extensions, and now it runs already in 4.0 devices but has memory leaks basing here. There are workarounds here but I don't know how to use/call it. Any help would do, thank you.

Answer

Okay, so I finally figured that instantiating a TypeFace object inside a TextView class would cause so much load each time that same TextView is instantiated. This caused my app to lag and resulted to OutOfMemoryException eventually. So what I did was to create a different custom TypeFace class that would call my fonts from the assets so that it instantiates from the TypeFace class and not from the TextView class.

Here's my TypeFaces class:

public class TypeFaces {

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

    public static Typeface getTypeFace(Context context, String assetPath) {
        synchronized (cache) {
            if (!cache.containsKey(assetPath)) {
                try {
                    Typeface typeFace = Typeface.createFromAsset(
                            context.getAssets(), assetPath);
                    cache.put(assetPath, typeFace);
                } catch (Exception e) {
                    Log.e("TypeFaces", "Typeface not loaded.");
                    return null;
                }
            }
            return cache.get(assetPath);
        }
    }
}

And the custom TextView class:

public class TextViewHirakaku extends TextView {

    public TextViewHirakaku(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public TextViewHirakaku(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TextViewHirakaku(Context context) {
        super(context);
    }

    public void setTypeface(Typeface tf, int style) {
        if (style == Typeface.BOLD) {
            super.setTypeface(TypeFaces.getTypeFace(getContext(),
                    "fonts/hirakakupronbold.ttf"));
        } else if (style == Typeface.ITALIC) {
            super.setTypeface(TypeFaces.getTypeFace(getContext(),
                    "fonts/hirakakupronitalic.ttf"));
        } else {
            super.setTypeface(TypeFaces.getTypeFace(getContext(),
                    "fonts/hirakakupron.ttf"));
        }
    }
}

Notice that I'm now calling getTypeFace method from TypeFaces class here.

Comments