是否可以在静态上下文块中获取资源?

时间:2012-04-17 16:43:08

标签: android resources static

我想创建一个静态哈希表,将字符串转换为整数。需要注意的是,我想在 XML文件中的几个列表中使用 strings 我定义为资源

我只能使用资源ID来写这个:

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

这条消息很有意义,但没有意义的是资源无法通过静态块访问,人们会认为静态变量是自定义创建的,以利用资源。
我想我可以在对象构造函数中填充哈希表,但这意味着要在错误的位置执行。

5 个答案:

答案 0 :(得分:11)

getResources()(〜MyActivity.this.getResources()的缩写)需要一个当时未初始化的上下文对象。由于上下文仅在您点击onCreate后才可用,因此您无法在MyActivity的构建时间执行此操作。

原因是实例化MyActivity类的活动管理器必须先确定配置(方向,屏幕大小,语言等),然后才能知道必须从xml中提取哪些资源。 - &GT;资源不是静态的,无法从静态上下文访问。

所以我想在onCreate或更晚的时候没有办法做这些操作。

编辑:虽然您当然可以从Context更新静态HashMap(或静态onCreate),但我不建议您这样做,因为您可能有多个相同Activity的实例,可能不同/更改配置。同时存储静态Context是创建Memory Leak

的好方法

答案 1 :(得分:6)

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

}

获得对Resources的静态引用后,您可以在整个应用程序的任何位置引用它。但是我不确定这是否会引入一个妈妈的泄漏;

答案 2 :(得分:1)

您可以做的一件事是创建一个Application类并在AndroidManifest.xml中注册它。然后重写onCreate方法并将Application类设置为静态引用,然后触摸Activity类以运行静态初始化程序。当apk被加载到内存中时将运行Application类,因此它将始终在任何Activity之前运行。

这有一些明显的缺点。我认为最明显的一个问题是,如果系统语言发生了变化,并且您已经为这些资源添加了翻译;然后你会有不一致的字符串,因为应用程序将使用默认/启动应用程序时的语言。字符串资源受Android资源管理系统的影响,因此对方向,系统语言,屏幕尺寸等内容的更改会影响这些值。这就是为什么在

时重置活动的原因

简而言之,最好为此作业使用常量字符串键值对。如果您需要使用字符串资源,那么您可以更好地处理翻译。我每次活动开始时都会加载它们。否则,您可能会发生内存泄漏和字符串转换不一致的风险。

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);
  }
}

答案 3 :(得分:0)

您始终可以保留对ApplicationContext的静态引用。这里描述了一种可能的方法:Static way to get 'Context' on Android?

答案 4 :(得分:0)

我不知道什么是最好的方式,但是,例如,在我的应用程序中,我有一个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);
}