Issue
Hello to all Android Developers, I need to clarify a doubt in relation to the management of dynamic resources in Android applications.
I need my application to use the translations returned by my backend depending on the language configured on the phone.
I wanted to implement it in an elegant way working on a custom LayoutInflater that applies a ViewTransformer depending on the type of graphic component.
Each ViewTransformer will only collect the identifier (for example @id/landing_welcome_text) and make the next call:
val value = attrs.getAttributeValue(index)
if (value != null && value.startsWith("@")) {
val text = view.context.resources.getString(attrs.getAttributeResourceValue(index, 0))
setTextForView(view, text)
}
A ContextWrapper has been implemented that returns my custom LayoutInflater and a Resource implementation
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
The problem is that overwriting the behavior of the Resources class is considered a deprecated strategy.
As the documentation says:
This constructor is deprecated. Resources should not be constructed by apps. See 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)
}
}
Does anyone know how I can get the same functionality without overwriting the Resources class?
Thank you very much for your help :)
Solution
I was looking into the same thing some time ago, in the end our team decided to go with Lokalise SDK.
From what I found out, overriding resources is the only way to do it. And even then it still doesn't cover all the cases, like mentioned in Lokalise documentation:
Some views are not supported when inflating from XML (Action bar, Menu items, Android preferences, may be others), but you can still get the latest translations via getString(), getText(), getQuantityString() and other system methods, and set the content of these views programmatically.
I saw a similar implementation in this library https://github.com/hamidness/restring although it wasn't nearly as complete as Lokalise. You can see how Lokalise is implemented if you include their library and switch to Project
view in Android Studio, expand External Libraries
and find com.lokalise.android
, then you can see the decompiled .class
files:
As for the constructor being deprecated - they deprecated it for the purpose of recreating the Resources
when you need them for a different Configuration
. But Context.createConfigurationContext
doesn't let you override the source of the strings provided by resources, so I don't see any alternative.
Answered By - arekolek
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.