向所有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,该ContextWrapper返回我的自定义LayoutInflater和Resource实现
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类的情况下获得相同的功能吗?
非常感谢您的帮助:)
答案 0 :(得分:1)
前段时间我一直在研究同一件事,最终我们的团队决定选择Lokalise SDK。
从我发现的结果来看,覆盖资源是唯一的方法。即便如此,它仍然不能涵盖所有情况,如Lokalise文档中所述:
从XML扩展时不支持某些视图(操作栏,菜单 项,Android偏好设置,可能是其他),但您仍然可以 通过getString(),getText(),getQuantityString()的最新翻译 和其他系统方法,并设置这些视图的内容 以编程方式。
我在该库https://github.com/hamidness/restring中看到了类似的实现,尽管它不如Lokalise完整。如果您包括Lokalise的库并切换至Android Studio中的Project
视图,展开External Libraries
并找到com.lokalise.android
,则可以看到Lokalise的实现方式,然后可以看到反编译的.class
文件:
关于不赞成使用的构造函数-为了在需要其他Resources
时重新创建Configuration
的目的,他们不赞成使用它。但是Context.createConfigurationContext
不允许您覆盖资源提供的字符串的来源,因此我看不到任何替代方法。