14

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

我可以写这个,只使用资源 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

该消息是有道理的,但没有意义的是静态块无法访问资源,人们会认为静态变量是自定义创建的以利用资源。
我想我可以在对象构造函数期间填充哈希表,但这意味着在错误的地方进行。

4

5 回答 5

12

getResources()(简称 ~ MyActivity.this.getResources())需要一个当时未初始化的上下文对象。由于上下文仅在您点击后才可用,您onCreate甚至无法在MyActivity.

原因是实例化您的MyActivity类的活动管理器必须在知道必须从 xml 中提取哪些资源之前确定配置(方向、屏幕大小、语言……)。-> 资源不是静态的,不能从静态上下文中访问。

onCreate所以我想在以后或以后做这些操作是没有办法的。

编辑:虽然您当然可以更新静态 HashMap (或 static Context),onCreate但我不建议这样做,因为您可以拥有相同 Activity 的多个实例,但配置可能不同/更改。存储静态Context也是创建内存泄漏的好方法

于 2012-04-17T16:55:14.073 回答
8
public Static Resources mResources;
public MyApplication extends Application
{
     @Override
     public void onCreate()
     {
           mResources = getResources();
     }

}

一旦获得对资源的静态引用,就可以在整个应用程序的任何位置引用它。但是我不确定这是否会引入内存泄漏;

于 2015-03-07T10:32:10.793 回答
1

您可以做的一件事是创建一个Application类并将其注册到您的 AndroidManifest.xml 中。然后重写 onCreate 方法并将 Application 类设置为静态引用,然后触摸 Activity 类以运行静态初始化程序。该类Application将在 apk 加载到内存时运行,因此它将始终在任何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);
  }
}
于 2012-04-17T17:09:39.377 回答
0

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

于 2012-04-17T16:57:52.837 回答
0

我不知道最好的方法是什么,但是,例如,在我的应用程序中,我有一个 Singleton(称为 GuiaUtil),它可以保留我当前的 Activity 和 Context。

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);
}
于 2012-04-17T16:58:01.340 回答