【问题标题】:RuntimeException: native typeface cannot be made or memory leak for custom TextView loading fontRuntimeException:无法制作本机字体或自定义 TextView 加载字体的内存泄漏
【发布时间】: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,但我不知道如何使用/调用它。任何帮助都可以,谢谢。

【问题讨论】:

    标签: android memory-leaks runtimeexception android-fonts inflate-exception


    【解决方案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"
          

          & 成功了。

          【讨论】:

            猜你喜欢
            • 2013-12-01
            • 2013-05-29
            • 2014-07-21
            • 2012-03-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多