返回

从区域设置更改中拯救你的 AndroidViewModel

Android

区域设置更改与 AndroidViewModel:揭开隐患

当涉及到应用程序开发时,管理不同语言和区域设置可能是一项艰巨的任务。对于 Android 来说,ViewModel 充当视图层和模型层之间的桥梁,在数据绑定中发挥着至关重要的作用。然而,在处理区域设置更改时,将资源(如字符串、可绘制文件和颜色)包含在 ViewModel 中会导致一些潜在的陷阱。

ViewModel 中的区域设置反面模式

区域设置更改:AndroidViewModel 的陷阱

在 Android 中,区域设置的更改会触发活动重新创建。虽然这对于更新 UI 以反映新设置至关重要,但它却给 ViewModel 带来了一个意想不到的后果:它不会被重新创建

后果:

  • 数据不一致: ViewModel 中的数据可能与用户的当前区域设置不一致,导致 UI 中出现错误的信息。
  • 潜在的崩溃: 如果 ViewModel 依赖于特定区域设置的资源,它可能会在区域设置更改后尝试访问不存在的资源,导致崩溃。

解决方案:重新思考 ViewModel

为了绕开这个反面模式,我们需要重新考虑 ViewModel 的设计:

  • 避免在 ViewModel 中使用区域设置相关的资源: 尽可能将与区域设置相关的资源移出 ViewModel。可以将它们存储在单独的资源类或外部文件中,然后在需要时从 ViewModel 中加载。
  • 使用 LiveData 观察资源更改: LiveData 是一个可观察对象,它允许我们观察资源的更改。我们可以将 LiveData 对象存储在 ViewModel 中,并在区域设置更改时更新 LiveData,从而触发 UI 更新。
  • 利用其他数据源: 除了 LiveData 之外,我们还可以使用其他数据源来存储区域设置相关的资源,例如 Room 数据库或 SharedPreferences。

示例:使用 LiveData 观察字符串资源更改

class MainActivityViewModel : ViewModel() {

    private val _name = MutableLiveData<String>()
    val name: LiveData<String> = _name

    init {
        // 获取当前区域设置下的字符串资源
        val nameString = resources.getString(R.string.name)
        _name.value = nameString

        // 注册一个观察者,监听区域设置更改
        val observer = Observer<Configuration> { newConfig ->
            // 当区域设置更改时,更新字符串资源
            val newString = resources.getString(R.string.name, newConfig.locale)
            _name.value = newString
        }
        application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
            override fun onConfigurationChanged(newConfig: Configuration) {
                observer.onChanged(newConfig)
            }
        })
    }
}

在示例中,我们使用 MutableLiveData 对象来存储字符串资源。当区域设置更改时,观察者将被触发并使用新的区域设置更新字符串资源。然后,UI 可以观察 LiveData 对象并自动更新以反映区域设置更改。

结论

在 AndroidViewModel 中避免区域设置更改的反面模式非常重要。通过重新考虑 ViewModel 的设计并使用 LiveData 或其他技术,我们可以确保我们的应用程序在区域设置更改时仍能正常运行。遵循本文中的指南,您可以编写健壮可靠的数据绑定应用程序,即使面对区域设置更改也能无缝处理。

常见问题解答

  • 为什么区域设置更改不会重新创建 ViewModel?
    ViewModel 旨在跨活动状态保持不变,因此在区域设置更改后不会重新创建。

  • 除了 LiveData,我还可以使用哪些其他技术来观察资源更改?
    其他选项包括 RxJava、Flow 和 Android KTX 中的 collectFlow() 函数。

  • 为什么将区域设置相关的资源移出 ViewModel 很重要?
    这可以防止 ViewModel 中的数据与用户的当前区域设置不一致,从而导致 UI 中出现错误。

  • 我如何避免在 ViewModel 中使用区域设置相关的资源?
    可以将它们存储在单独的资源类或外部文件中,然后在需要时从 ViewModel 中加载。

  • 在处理区域设置更改时,使用 ViewModel 的最佳实践是什么?
    最佳实践包括避免在 ViewModel 中使用区域设置相关的资源、使用 LiveData 或其他技术来观察资源更改,以及重新考虑 ViewModel 的设计。