Is there any way I can add items in code to a String-Array resource? For instance, if I want to create a spinner that shows the user values, and I want to allow the user to add their own custom values.
问题:
回答1:
No. this is not supported because resources are packaged in the binary .apk and as such cannot be changed.
Don't follow this design pattern, change your approach.
回答2:
probably JoxTraex has no idea on android framework or as they are saying:
when someone says this can't be done - there always is someone who doesn't know that and will do it :)
so to the point:
Resources is an open class is just a wrapper around ResourcesImpl class
(with depreciated constructor - but is available)
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config)
in app every call to it is made via Context
so:
1) you always can provide your own Resources implementation
2) or (when its enough) your own Context implementation (so sky is the limit)
... i now feel eyes on "Context implementation" - yeah you can even replace top most context in LoadedApk, Activity, etc.. yeah cool? but when, how? how: via reflections, when: good app designer knows that this place is where (before) first/any call to such object is made ...
But there is one dangerous catch here - in one case android straight unwrap Context to ContextImp and then you need to return those Context instead yours - where is the place that i'll keep as secret for those who like riddles :)
there is also in Resources
a) a hidden constructor (best entry point as it is not making any ReourceImpl (which can be set by method mentioned bellow)
public Resources(@Nullable ClassLoader classLoader)
b) hidden method
setResImpl(ResourcesImpl)
sum up:
so by calling
Resources.getStringArray(**not existing in APK resource id here**);
on our own implementation we could get whatcha want :)
even better we can add to our implementation
addResourceById(int,Object)
method and add new resources :) then with assign ability check on resource we will use and do a up casting to our implementation :) to use our newly added method :)
btw: if someone says to you "you shouldn't do it - blablabla" this is the best reason to do it! - if not permitted by law :)
enough the theory go to a practice:
example Context implementation forwards calls to getString:
public class MyContext extends Context {
....
// override context get resources method
@Override
public android.content.res.Resources getResources() {
// get super resources
android.content.res.Resources resources = super.getResources();
// pull assets
android.content.res.AssetManager assets = resources.getAssets();
// pull metrics
android.util.DisplayMetrics displayMetrics = resources.getDisplayMetrics();
// pull configuration
android.content.res.Configuration configuration = resources.getConfiguration();
// construct new anon resource implementation
return new android.content.res.Resources(assets, displayMetrics, configuration) {
// overrride interesting method
@android.support.annotation.NonNull
@Override
public String getString(int id) throws android.content.res.Resources.NotFoundException {
return id == pl.ceph3us.base.common.R.string.my_sweet_google
? "fck_you_google";
: super.getString(id);
}
};
}
}