【问题标题】:Android : Dealing with multiple font files - Correct wayAndroid:处理多个字体文件 - 正确的方法
【发布时间】:2015-07-11 17:48:00
【问题描述】:

在我的应用程序中,我需要处理多个字体文件。因此,我没有每次都创建新实例,而是实现了 Singleton 来获得这样的字体:

public class FontSingleton {

    private static FontSingleton instance;
    private static Typeface typeface;

    private FontSingleton(){
        //private constructor to avoid direct creation of objects
    }

    public static FontSingleton getInstance(Context context,String fontFileName){
        if(instance==null){
            instance = new FontSingleton();
            typeface = Typeface.createFromAsset(context.getResources().getAssets(), fontFileName);
        }
        return instance;
    }

    public Typeface getTypeFace(){
        return typeface;
    }
}

现在,我可以像这样得到typeface

FontSingleton.getInstance(mContext,"font1.otf").getTypeFace();

是处理内存泄漏和实现单例的正确方法吗?我是设计模式和Android的新手。谁能指导我正确的方法?

【问题讨论】:

    标签: java android android-layout design-patterns singleton


    【解决方案1】:

    FontSingleton 设为Singleton 是没有用的,因为您真正需要的是缓存Typeface 对象,而不是创建它们的类。因此,您可以使您的FontSingleton(不再是单例,所以我们称它为FontHelper)一个没有实例的类,并让它存储MapTypefaces。这些将以惰性方式创建:如果字体名称没有Typeface - 创建它并将其存储在Map 中,否则重用现有实例。代码如下:

    public class FontHelper {
    
        private static final Map<String, Typeface> TYPEFACES = new HashMap<>();
    
        public static Typeface get(Context context,String fontFileName){
            Typeface typeface = TYPEFACES.get(fontFileName);
            if(typeface == null){
                typeface = Typeface.createFromAsset(context.getResources().getAssets(), fontFileName);
                TYPEFACES.put(fontFileName, typeface);
            }
            return typeface;
        }
    }
    

    对不起,如果代码不能按原样工作,但希望这个想法很清楚。

    【讨论】:

      【解决方案2】:

      如果我没看错的话,这会过于复杂且不正确(实例将始终保留给定的第一个字体,因为实例已经存在,因此不会再次调用它)。

      为什么不实现这样的东西:

      public class FontHelper {
          public static Typeface get(Context context, String fontFilename) {
              return Typeface.createFromAsset(context.getResources().getAssets(), fontFileName);
          }
      }
      

      然后你只需调用:

      FontHelper.get(mContext,"font1.otf")

      【讨论】:

      • 我也会将字体缓存在静态 HashMap 中。
      • 使用这种方法,每次调用 get() 方法时都会创建一个新的字体,并且检索资产是一项非常昂贵的操作:这段代码会很慢。
      • @Karakuri 我同意。这只是我的想法。
      【解决方案3】:

      Is是处理内存泄漏和实现的正确方法 单身人士?

      getInstance() 应该是synchronized,在你将它标记为synchronized 之后,对于模式的实现来说,它是正确的。我仍然认为它不能很好地满足您的需求。例如,您不能创建新的 TypeFace 对象。您编写它的方式是使用font1.otf。如果需要,则不需要提供字体名称,作为 getInstance() 的参数。

      作为替代解决方案,您应该考虑将TextView 子类化的可能性,提供自定义xml 属性,您可以通过该属性指定要使用的字体。

      【讨论】:

      • 谢谢,但是“您不需要提供字体名称,作为 getInstance() 的参数”。那我该怎么做呢?
      • 但正如我所说,我需要处理多种字体。我应该有多种方法来获取实例吗?
      • 按照您的编写方式,您将始终只有一种类型的TypeFace。你可能想要的是 Factory 而不是 Singleton,但如果我在你里面,我会选择子类解决方案
      • Egor 的解决方案可以满足您对单例的想法。你可以在这里找到 TextView 的子类。我没有测试它,所以你可能需要修复一些小问题。 Here 是代码的要点
      • @Blackbelt,这是一个非常方便的解决方案,但它不能解决缓存 Typeface 实例的问题。将为每个 TextView 实例创建一个新的字体。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 2013-07-24
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      相关资源
      最近更新 更多