为什么Resources.getString()会间歇性地从错误的语言环境返回字符串?

时间:2011-02-11 01:45:44

标签: android localization locale getstring

我有一个Android应用程序,在values / strings.xml中有英文字符串。对于该文件中的每个字符串,我在values-ja / strings.xml中有一个条目,其中包含该字符串的日语翻译。如果我将模拟器,Nexus One或Nexus S设置为日语,则UI会显示日语文本。大部分时间都是。

有时,UI的某些部分将以英语显示,即使当前区域设置为ja-JP。例如,我在我的一个活动的onCreate()方法中编写了这个测试代码:

Log.e(TAG, "Default locale = '" + Locale.getDefault().toString() + "'");
Log.e(TAG, "My string = '" + getResources().getString(R.string.my_string) + "'");

有时我会在LogCat中看到:

Default locale is 'ja_JP'
My string is '日本'

其他时候我会看到:

Default locale is 'ja_JP'
My string is 'English'

有时通过旋转手机可以解决此问题。有时它会通过退出并重新启动应用程序来解决。有时只有一个屏幕的一部分是英文的。有时,通过代码从资源中提取的字符串会出现此问题,有时会出现仅由布局引用的字符串。我的应用程序中没有任何地方可以调用Locale.setDefault(),因此不会导致问题。

更新

我找到了一种方法来纠正特定活动的问题。在那个活动的onCreate():

Log.e(TAG, "getString: '" + getString(R.string.my_string) + "'");
Log.e(TAG, "getResources().getConfiguration(): '" +
      getResources().getConfiguration().toString() + "'");
Log.e(TAG, "getResources().getDisplayMetrics(): '" +
      getResources().getDisplayMetrics().toString() + "'");

Log.e(TAG, "Setting configuration to getConfiguration()");
getResources().updateConfiguration(getResources().getConfiguration(),
     getResources().getDisplayMetrics());

Log.e(TAG, "getString: '" + getString(R.string.my_string) + "'");
Log.e(TAG, "getResources().getConfiguration(): '" +
      getResources().getConfiguration().toString() + "'");
Log.e(TAG, "getResources().getDisplayMetrics(): '" +
      getResources().getDisplayMetrics().toString() + "'");

这导致LogCat中的以下内容:

getString: 'English'
getResources().getConfiguration(): '{ scale=1.0 imsi=0/0 loc=ja_JP touch=3 keys=1/1/2 nav=3/1 orien=1 layout=34 uiMode=17 seq=8}'
getResources().getDisplayMetrics(): 'DisplayMetrics{density=1.5, width=480, height=800, scaledDensity=1.5, xdpi=254.0, ydpi=254.0}'
Setting configuration to getConfiguration()
getString: '日本'
getResources().getConfiguration(): '{ scale=1.0 imsi=0/0 loc=ja_JP touch=3 keys=1/1/2 nav=3/1 orien=1 layout=34 uiMode=17 seq=8}'
getResources().getDisplayMetrics(): 'DisplayMetrics{density=1.5, width=480, height=800, scaledDensity=1.5, xdpi=254.0, ydpi=254.0}'

从日志中可以看出,当前配置中没有任何内容发生变化,但getString()会产生不同的结果。

在我的应用程序中可能使用资源的每个地方使用此变通方法是不切实际的,但希望这提供了一个关于出错的提示。

3 个答案:

答案 0 :(得分:1)

这只是一个理论,但you could be leaking a Context.基本上,旧活动可能是报告字符串值而不是新创建的。

测试方法是:

  1. 将TAG更改为成员变量(NOT STATIC!)。
  2. OnCreate,设置TAG = this.toString(),这会将活动的内存地址作为标记。
  3. 让活动使用初始区域设置打印出来。
  4. 做任何改变语言环境的事情。这应该(从未验证过)重新启动活动并获得新活动。如果你这样做。然后查看日志并查看标记的内存地址是否正在更改。如果内存地址与上下文泄漏之前的内存地址相同。

答案 1 :(得分:0)

您是否在应用程序运行时更改区域设置?如果是这样,您是否正确实施了活动生命周期的各种元素(包括onSaveInstanceState()onRestoreInstanceState())?

根据http://developer.android.com/guide/topics/resources/runtime-changes.html,运行时配置的更改应该导致Activity被销毁&重新启动。听起来您的应用程序注意到新配置但未正确重新启动(直到重新启动整个应用程序或更改方向)。

你在onSaveInstanceStateonDestroy做了什么时髦吗?

P.S。如果它仅针对某些方向变化进行自我修正,您是否可以建议这些方向更改是否发生在具有不同垂直和方向的布局上。水平布局文件?

答案 2 :(得分:0)

我遇到了同样的问题。

对我来说,我试图从共享首选项(在onCreate()中完成)导入语言设置之前,先获取字符串(在onResume()中。)