Подтвердить что ты не робот

Возможно ли получить ресурсы внутри статического контекстного блока?

Я хочу создать таблицу static Hash для преобразования строк в целые числа. Оговорка здесь в том, что я хочу использовать строки, которые я определил как ресурсы в нескольких списках в XML файлах.

Я могу написать это, используя только идентификаторы ресурсов:

public class MyActivity extends Activity {

private static Map<Integer, Integer> views = new HashMap<Integer, Integer>();
static {
    views.put(R.string.full_text, MessageTable.VIEW_FULL);
    views.put(R.string.only_text, MessageTable.VIEW_MSG);
    views.put(R.string.tag_text, MessageTable.VIEW_TAGMSG);
}

Я не получаю ошибок, но мне действительно нужно сделать что-то вроде этого:

public class MyActivity extends Activity {

private static Map<String, Integer> views = new HashMap<String, Integer>();
static {
    views.put(getResources().getString(R.string.full_text), MessageTable.VIEW_FULL);
    views.put(getResources().getString(R.string.only_text), MessageTable.VIEW_MSG);
    views.put(getResources().getString(R.string.tag_text), MessageTable.VIEW_TAGMSG);
}

который дает мне следующую ошибку в Eclipse:

Cannot make a static reference to the non-static method getResources() from the type ContextWrapper

Сообщение имеет смысл, но нет смысла в том, что ресурсы недоступны из статического блока, можно было бы подумать, что статические переменные были созданы пользователем для использования ресурсов.
Наверное, я могу заполнить таблицу Hash во время конструктора объекта, но это означало бы сделать это не в том месте.

4b9b3361

Ответ 1

getResources() (сокращение от ~ MyActivity.this.getResources()) требует объекта контекста, который в это время не инициализируется. Поскольку контекст доступен только после того, как вы нажали onCreate, вы даже не можете сделать это во время построения MyActivity.

Причина в том, что менеджер активности, который создает экземпляр класса MyActivity, должен определить конфигурацию (ориентацию, размер экрана, язык...), прежде чем он узнает, какие ресурсы необходимо извлечь из xml. → Ресурсы не являются статическими и не могут быть доступны из статического контекста.

Итак, я думаю, что нет никаких способов делать эти операции в onCreate или новее.

Изменить: Хотя вы, безусловно, можете обновить статический HashMap (или статический Context) от onCreate, я бы не рекомендовал это, так как вы можете иметь несколько экземпляров одного и того же Activity с возможными разными/изменяющимися конфигурациями. Также сохранение статического Context - отличный способ создать Утечка памяти

Ответ 2

public Static Resources mResources;
public MyApplication extends Application
{
     @Override
     public void onCreate()
     {
           mResources = getResources();
     }

}

Когда у вас есть статическая ссылка на ресурсы, вы можете ссылаться на нее в любом месте всего приложения. Тем не менее, я не уверен, что это приведет к утечке памяти или нет;

Ответ 3

Одна вещь, которую вы можете сделать, это создать класс Application и зарегистрировать его в вашем AndroidManifest.xml. Затем переопределите метод onCreate и установите класс Application как статическую ссылку, а затем коснитесь класса Activity для запуска статического инициализатора. Класс Application будет запущен, так как apk загружается в память, поэтому он всегда будет работать до любого Activity.

Есть некоторые существенные недостатки. Наиболее очевидным я думаю, что если системный язык меняется, и вы добавили переводы к этим ресурсам; то у вас будут несогласованные строки, потому что приложение будет использовать значение по умолчанию/независимо от того, какой язык был при запуске приложения. На ресурсы String влияет система управления ресурсами Android, поэтому изменения в таких вещах, как ориентация, системный язык, размеры экрана, могут влиять на эти значения. Что причины, по которым Activities получают reset, когда

Короче, вам лучше использовать постоянные пары ключ-значение Strings для этого задания. Если вам нужно использовать строковые ресурсы, чтобы лучше выполнять переводы. Я загружаю их каждый раз, когда начинается действие. В противном случае вы рискуете утечками памяти и несогласованными строковыми переводами.

public MyApplication extends Application {

  public static Context GlobalContext = null;

  @Override
  protected void onCreate() {
    MyApplication.GlobalContext = this;

    // Touch the activity class.
    MyActivity activity = new MyActivity();
    // Throw it away by not using it.

    // invalidate handle to prevent GC leaks.
    GlobalContext = null;
  }
}

public class MyActivity extends Activity {
  private static Map<String, Integer> views = new HashMap<String, Integer>();

  static {
    Context context = MyApplication.GlobalContext;
    Resources res = context.getResources();
    views.put(res.getString(R.string.full_text), MessageTable.VIEW_FULL);
    views.put(res.getString(R.string.only_text), MessageTable.VIEW_MSG);
    views.put(res.getString(R.string.tag_text), MessageTable.VIEW_TAGMSG);
  }
}

Ответ 5

Я не знаю, что такое BEST. Но, например, в моем приложении у меня есть Singleton (так называемый GuiaUtil), который сохраняет мои текущие действия и контекст.

private static Map<String, Integer> views = new HashMap<String, Integer>();
static {
views.put(GuiaUtil.instance().getAppContext().getResources().getString(R.string.full_text), MessageTable.VIEW_FULL);
views.put(GuiaUtil.instance().getAppContext().getResources().getString(R.string.only_text), MessageTable.VIEW_MSG);
views.put(GuiaUtil.instance().getAppContext().getResources().getString(R.string.tag_text), MessageTable.VIEW_TAGMSG);
}