RuntimeException:无法制作本机字体或自定义 TextView 加载字体的内存泄漏

Posted

技术标签:

【中文标题】RuntimeException:无法制作本机字体或自定义 TextView 加载字体的内存泄漏【英文标题】:RuntimeException: native typeface cannot be made or memory leak for custom TextView loading font 【发布时间】:2014-01-23 10:13:50 【问题描述】:

我的代码中存在一个巨大的问题,其中我从自定义 TextView 类加载我的 assets\fonts\ 文件夹中的字体。第一个问题是它在 4.0 设备上崩溃,但 Caused by: java.lang.RuntimeException: native typeface cannot be made 除外。我正在使用相同的过程here 方法:

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 设备中运行,但基于here 存在内存泄漏。有解决方法here,但我不知道如何使用/调用它。任何帮助都可以,谢谢。

【问题讨论】:

【参考方案1】:

好的,所以我终于想到,在 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 方法。

【讨论】:

【参考方案2】:

如果您在 android Studio 上遇到此问题,请将您的资产放在主目录下,而不是放在 res 目录下。

在字体命名中也只能使用小写字母和下划线,例如我的字体.ttf

这对我来说很有魅力

【讨论】:

【参考方案3】:

如果您是从 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”

问候,

【讨论】:

【参考方案4】:

就我而言,我用于自定义视图 (costum) 的 XML 命名空间前缀设置不正确:

xmlns:costum="http://schemas.android.com/apk/tools"

我要做的就是把它改成

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

& 成功了。

【讨论】:

以上是关于RuntimeException:无法制作本机字体或自定义 TextView 加载字体的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

React 本机 iOS 字体无法以任何方式工作

java.lang.RuntimeException:无法连接到相机服务

Android Java.Lang.RuntimeException:无法启动活动组件信息

java.lang.IllegalArgumentException:无法加载本机库

使用自定义字体时出现问题 - “无法制作原生字体”

java.lang.RuntimeException:无法在尚未调用 Looper.prepare() 的线程上敬酒 [重复]