Как правильно переписать класс Resource для реализации динамической системы перевода? - PullRequest
0 голосов
/ 04 июля 2019

Привет всем разработчикам Android, мне нужно прояснить сомнение в отношении управления динамическими ресурсами в приложениях Android.

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

Я хотел элегантно реализовать его, работая над пользовательским LayoutInflater , который применяет ViewTransformer в зависимости от типа графического компонента.

Каждый ViewTransformer будет собирать только идентификатор (например, @ id / landing_welcome_text) и делать следующий вызов:

 val value = attrs.getAttributeValue(index)
 if (value != null && value.startsWith("@")) {
      val text = view.context.resources.getString(attrs.getAttributeResourceValue(index, 0))
     setTextForView(view, text)
 }

Был реализован ContextWrapper, который возвращает мой пользовательский LayoutInflater и реализацию ресурса

override fun getSystemService(name: String): Any {
   return if (Context.LAYOUT_INFLATER_SERVICE == name)
      CustomLayoutInflater(
          LayoutInflater.from(baseContext),
                this,
                viewTransformerManager
            )
      else
            super.getSystemService(name)
}

override fun getResources(): Resources = customResources

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

Как сказано в документации:

Этот конструктор устарел. Ресурсы не должны создаваться Программы. См. Context.createConfigurationContext (Configuration).

class CustomResourcesWrapper constructor(
    res: Resources,
    private val languageStringRepo: ILanguageStringRepo
): Resources(res.assets, res.displayMetrics, res.configuration) {


    @Throws(Resources.NotFoundException::class)
    override fun getString(id: Int): String {
        val value = getStringFromRepository(id)
        return value ?: super.getString(id)
    }

}

Кто-нибудь знает, как я могу получить такую ​​же функциональность, не перезаписывая класс Resources?

Большое спасибо за помощь:)

1 Ответ

1 голос
/ 05 июля 2019

Некоторое время назад я изучал то же самое, и в конце концов наша команда решила использовать Lokalise SDK .

Из того, что я узнал, переопределение ресурсов - единственный способ сделать это. И даже тогда это все еще не охватывает все случаи, как упомянуто в документации Lokalise:

Некоторые представления не поддерживаются при накачивании из XML (Панель действий, Меню пункты, настройки Android, могут быть и другие), но вы все равно можете получить последние переводы через getString (), getText (), getQuantityString () и другие системные методы, и установите содержание этих представлений программным способом.

Я видел похожую реализацию в этой библиотеке https://github.com/hamidness/restring, хотя она была не такой полной, как Lokalise. Вы можете увидеть, как реализован Lokalise, если включить их библиотеку и переключиться на представление Project в Android Studio, развернуть External Libraries и найти com.lokalise.android, а затем увидеть декомпилированные файлы .class:

Decompiled sources

Что касается устаревшего конструктора - он устарел с целью воссоздания Resources, когда он вам нужен для другого Configuration. Но Context.createConfigurationContext не позволяет переопределить источник строк, предоставляемых ресурсами, поэтому я не вижу альтернативы.

...