2011-01-28 6 views
5

Я родом из фона ActionScript3, и это моя первая запись любой Java в моей жизни. Hashtables, похоже, похожи на словари во Flash, но я хочу убедиться, что правильно их использую. Я считаю, что Hashtable печатается, чтобы принимать строки как ключи и Typefaces как объекты. Это верно? Есть ли другой подкласс класса, который был бы более подходящим для чего-то подобного? Во что бы то ни стало, пожалуйста, разорвите мою n00b Java. Мне нужно это узнать.Является ли Hashtable подходящим для хранения активов?

package com.typeoneerror.apps.app_name.utils; 

import android.content.Context; 
import android.graphics.Typeface; 

import java.util.Hashtable; 

public class FontRegistry 
{ 
    private static FontRegistry _instance; 

    private Context       _context; 
    private Hashtable<String, Typeface>  _fonts; 

    private FontRegistry() 
    { 
     _fonts = new Hashtable<String, Typeface>(); 
    } 

    public static FontRegistry getInstance() 
    { 
     if (_instance == null) 
     { 
      _instance = new FontRegistry(); 
     } 
     return _instance; 
    } 

    public void init(Context context) 
    { 
     _context = context; 

    } 

    public Typeface getTypeface(int resourceId) 
    { 
     String fontName = _context.getResources().getString(resourceId); 
     if (!_fonts.containsKey(fontName)) 
     { 
      String fontPath = "fonts/" + fontName; 
      Typeface typeface = Typeface.createFromAsset(_context.getAssets(), fontPath); 
      _fonts.put(fontName, typeface); 
     } 
     return (Typeface)_fonts.get(fontName); 
    } 
} 
+2

За исключением того, что сказал rfeak, все в порядке. Еще несколько советов: когда вы опускаете символы подчеркивания (пожалуйста, сделайте), вам понадобится 'this.context = context'. Вы можете инициализировать шрифты наподобие 'private final Map fonts = new HashMap ()'. Если был параллелизм, тогда у вас могут возникнуть проблемы с вашим ленивым синглом. Включите предупреждение, ваш последний бросок, безусловно, не нужен. – maaartinus

+1

Будет ли доступ к этому классу одно- или многопоточным? Я только спрашиваю, как ваша текущая реализация 'getInstance()' не является потокобезопасной. –

+0

@ dave.c Должен признаться, я понятия не имею. Как я уже сказал, это первый раз, когда я пишу java, поэтому любые советы по этому поводу в качестве ответа будут очень оценены. – typeoneerror

ответ

7

Два предложения для вас.

Во-первых, тип переменной должен относиться к интерфейсу карты. Это дает вам больше гибкости для будущего и будет лучше работать с большинством других разработчиков Java.

Во-вторых, реализация должна быть HashMap, а не HashTable. HashTable синхронизирует все, где не работает HashMap.

Если вам нужен многопоточный доступ, я бы предложил использовать ConcurrentHashMap вместо HashTable. ConcurrentHashMap работает лучше, поскольку он не блокирует всю карту во время доступа.

Так,

private Map<String, Typeface>  _fonts; 

и

_fonts = new HashMap<String, Typeface>(); 

Наконец, многие Java разработчики предпочли бы, чтобы не начать переменных-членов с подчеркиванием. Хотя это спорно предпочтение.

EDIT: Последний нитпик. Кажется, вы используете шаблон singleton для реестра. Это может укусить вас позже, поэтому подумайте об избежании одиночных игр http://accu.org/index.php/journals/337. Но, игнорируя это, вам может быть лучше создать экземпляр singleton в объявлении. Он может избежать возможного разногласия при первом его получении.

Итак:

private static FontRegistry _instance = new FontRegistry; 
+0

отличный ответ, спасибо.Я тоже не поклонник одноэлементного паттерна. вероятно, будет рефактором. – typeoneerror

+1

Шаблон singleton с 'Context' как' static' член также опасен для Android, так как он может помешать 'Activity', который был передан как« Контекст »из собранного мусора. –

1

Чтобы расширить мои комментарии, ваша реализация getInstance() не поточно. Если вы действительно должны использовать шаблон Singleton, вы можете использовать «Bill Pugh» версии (которую я нагло скопирована из wikipedia article):

public class Singleton { 

    // Private constructor prevents instantiation from other classes 
    private Singleton() { 
    } 

    /** 
    * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
    * or the first access to SingletonHolder.INSTANCE, not before. 
    */ 
    private static class SingletonHolder { 
     public static final Singleton INSTANCE = new Singleton(); 
    } 

    public static Singleton getInstance() { 
     return SingletonHolder.INSTANCE; 
    } 
} 

Далее вам нужно быть осторожным при разработке для Android не «утечки "a Context. Вот good article о том, почему так плохо, и как этого избежать. Суть в том, что ссылка static на Context (или объект, который сам ссылается на Context) может означать, что ваш экземпляр Activity не может быть собранным мусором.

+0

спасибо, что написал это, дэйв. – typeoneerror

+0

отличные ссылки. Я должен отметить, что я использую контекст приложения для инициализатора: FontRegistry.getInstance(). Init (getApplicationContext()); . в статье указывается, что «... контекст приложения. Этот контекст будет жить до тех пор, пока ваше приложение будет живым и не будет зависеть от жизненного цикла деятельности» – typeoneerror

+0

Рад, что вы нашли их полезными. Как вы заявляете, использование метода getApplicationContext() - это способ избежать проблемы. –

Смежные вопросы