运行时异常:无法创建本地字体或自定义TextView加载字体时出现内存泄漏。

4
我的代码存在一个严重问题,我正在从自定义的TextView类中加载位于“assets\fonts\”文件夹中的字体。第一个问题是,在4.0设备上会崩溃,并显示异常信息“Caused by: java.lang.RuntimeException: native typeface cannot be made”。我的使用方法与此处相同
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"));
        }
    }
}

注意到我正在使用扩展名为.ttf的字体文件,发现这导致了RunTimeException。因此,我将相应的字体转换成了.otf格式,现在它可以在4.0设备上运行,但存在内存泄漏问题,见这里。有一些解决方法在这里,但我不知道如何使用或调用它们。希望能得到帮助,谢谢。
4个回答

8
好的,我终于弄清楚在TextView类中实例化TypeFace对象会导致每次实例化该TextView时产生如此大的负载。这导致我的应用程序出现了延迟,并最终导致了OutOfMemoryException。因此,我创建了一个不同的自定义TypeFace类,它将从资源中调用我的字体,以便从TypeFace类而不是TextView类实例化。
这是我的TypeFaces类:
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);
        }
    }
}

还有自定义的TextView类:

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

请注意,我现在正在这里从TypeFaces类调用getTypeFace方法。

7
如果您在Android Studio上遇到此问题,请将资产放在main目录下,而不是放在res目录下。同时,在字体命名中只使用小写字母和下划线,例如:my_font.ttf。这对我起了很好的作用。

1
如果您正在从XML扩展此视图,请尝试以以下方式使用它:
public class MyTextView extends TextView {

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

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

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


public void init() {
    Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/hirakakupronbold.ttf");
    setTypeface(tf);

}

}

这对我来说很好用。为每个字体样式创建一个扩展TextView的单独类。要应用它,请将"TextView"替换为"com.yourpackage.MyTextView"

致敬,


0
在我的情况下,我为自定义视图使用的 XML 命名空间前缀(costum)没有正确设置:
xmlns:costum="http://schemas.android.com/apk/tools"

我所要做的就是将其更改为

xmlns:costum="http://schemas.android.com/apk/res-auto"

它起作用了。


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