Android Dynamically Add Item to Array XML Resource

2019-06-21 06:08发布

问题:

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);
            }
        };
    }

}