Конфигурация контекста приложения Android не обновляется с новой локалью - PullRequest
3 голосов
/ 12 марта 2019

Мне нужен доступ к локализованным строкам приложения, когда я не использую Context связанные классы (Activites, Fragments, Services, Views и т. Д.) В ViewModel или пользовательских классах, где я храню всю свою бизнес-логику. Например, отправка String на UI с помощью LiveData:

toastMessageLiveData.value = buildLastLoginToastMessage()

fun buildLastLoginToastMessage() {
   val lastLoginDiff = (System.currentMillis() - getLastLogin()) / DateUtils.HOURS_IN_MILLIS

   return MyApp.instance.getString(R.string.last_login_txt, lastLoginDiff)
}

Сейчас в Activity я наблюдаю за изменением LiveData и показываю сообщение Toast.

Это работает нормально, но проблема возникает, если пользователь меняет язык приложения . Макеты обновлены, и я вижу, что используется язык новой локали, но функция MyApp.instance.getString(R.string....) все еще использует старую локаль . Если я принудительно убиваю приложение и перезагружаю его, оно работает, потому что приложение attachBaseContext вызывается снова и применяется новый язык. Однако я не хочу принудительно уничтожать приложение, мне нужно решение для обновления конфигурации приложения.

Утилита для создания или обновления Context

fun buildLocalizedContext(context: Context): Context {
   // From preferences, load the saved Language and Country codes
   val language = getSavedLanguage()
   val country = getSavedCountry()

   // Create the new locale
   val locale = Locale(language, country)
   Locale.setDefault(locale)

   val resources = context.resources
   val configuration = Configuration(resources.configuration)

   // Create a new configration or update the existing one if the API is less than 17
   if (Build.VERSION.SDK_INT >= 17) {
      configuration.setLocale(locale)
      return context.createConfigurationContext(configuration)
   } else {
      configuration.locale = locale
      resources.updateConfiguration(configuration, resources.getDisplayMetrics())
   }

   return context
}

Когда приложение запустится, примените новую локаль

class MyApp: Application {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(LocaleHelper.instance.buildLocalizedContext(base))
    }
}

Класс BaseActivity, который используется другими активами:

class BaseActivity: AppCompatActivity {
    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(LocaleHelper.instance.buildLocalizedContext(newBase))
    }
}

Это то, что мне удалось сделать до сих пор, однако это тоже не работает:

fun changeLocale(locale: Locale, app: Application) {
    Locale.setDefault(locale)

    val resources = app.resources
    val configuration = resources.configuration

    if (Build.VERSION.SDK_INT >= 17) {
        configuration.setLocale(locale)
    }
    else {
        configuration.locale = locale
        resources.updateConfiguration(configuration, resources.displayMetrics)
    }
}

Приведенный выше фрагмент кода не работает, он не меняет локаль приложения, только если я принудительно перезапущу приложение.

...