为什么 Resources.getString() 可能会间歇性地从错误的区域设置返回字符串?

发布于 2024-10-16 19:12:43 字数 2400 浏览 6 评论 0原文

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

有时,即使当前区域设置是 ja-JP,UI 的某些部分也会以英语显示。例如,我在其中一项活动的 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() 给出了不同的结果。

在我的应用程序中可能使用资源的每个地方使用此解决方法是不切实际的,但希望这可以提供有关出现问题的提示。

I have an Android application with English strings in values/strings.xml. For each string in that file, I have an entry in values-ja/strings.xml with the Japanese translation of that string. If I set the emulator, a Nexus One or Nexus S to Japanese, the UI shows Japanese text throughout. Most of the time.

Sometimes, some portion of the UI will appear in English, even though the current locale is ja-JP. For instance, I wrote this test code in the onCreate() method of one of my activities:

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

Sometimes I will see in LogCat:

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

Other times I will see:

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

Sometimes this issue is resolved by rotating the phone. Sometimes it's resolved by exiting and restarting the app. Sometimes only a portion of a single screen is in English. Sometimes this issue occurs with strings that are pulled out of the resources via code, and sometimes it occurs with strings that are only referenced by a layout. Nowhere in my application do I call Locale.setDefault(), so that's not causing the issue.

UPDATE

I've found a way to correct the issue for a specific activity. In that activity's 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() + "'");

This results in the following in 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}'

As you can see from the log, nothing in the current configuration changes, but getString() gives different results.

It's impractical to use this workaround in every place in my application where a resource might be used, but hopefully this provides a hint about what's going wrong.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

救赎№ 2024-10-23 19:12:43

这只是一个理论,但你可能会泄漏上下文。 基本上,旧活动可能会报告字符串值,而不是新创建的活动。

测试这一点的方法是:

  1. 将 TAG 更改为成员变量(非静态!)。
  2. OnCreate时,设置TAG = this.toString(),这会将活动的内存地址作为标签。
  3. 让活动使用初始区域设置打印出内容。
  4. 尽一切努力改变语言环境。这应该(从未验证过)重新启动活动,并且您会得到一个新活动。如果你这样做的话。然后查看日志并查看标签的内存地址是否发生变化。如果内存地址与上下文泄漏之前相同。

This is just a theory but you could be leaking a Context. Basically, the old activity might be reporting the string values rather than the newly created on.

A way to test this is:

  1. Change TAG to a member variable (NOT STATIC!).
  2. OnCreate, set TAG = this.toString(), this will put the memory address of the activity as the tag.
  3. Have the activity print out stuff using the initial locale.
  4. Do whatever to change the locale. This should (never verified this) restart the activity and you get a new activity. If you do. THen look at the log and see if the memory address is changing for the tag. If the memory address is the same as before the context was leaked.
听,心雨的声音 2024-10-23 19:12:43

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

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

您在 onSaveInstanceStateonDestroy 中做了什么奇怪的事情吗?

Ps 如果它仅在某些方向变化时自行纠正,您能否建议这些方向变化是否发生在具有不同垂直方向和垂直方向的布局上?水平布局文件?

Are you changing Locale while the application is running? If so, have you properly implemented the various elements of the Activity lifecycle (including onSaveInstanceState() and onRestoreInstanceState())?

According to http://developer.android.com/guide/topics/resources/runtime-changes.html, a change in configuration at runtime should cause the Activity to be destroyed & restarted. It sounds like your app is noticing the new configuration but is not restarting properly (until restarting the whole App, or changing orientation).

Are you doing anything funky in onSaveInstanceState or onDestroy?

P.s. If it corrects itself only on certain orientation changes, can you advise if those orientation changes occur on layouts that have different vertical & horizontal layout files?

情释 2024-10-23 19:12:43

我遇到了同样的问题。

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

I faced the same issue.

For me, I was trying to get the string (in the onCreate()) before importing language settings from shared preferences (done in the onResume()).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文