42

I am trying to create helper method that would iterate through all Bundle objects, in a generic manner.

By "generic" I mean:

  1. Doesn't need to know the names (keys) of the objects in the Bundle passed as a parameter.
  2. Doesn't need to change if another member (key) was added to the Bundle in the future.

So far, I figure out the following outline to accomplish that:

  private void bundleToSharedPreferences(Bundle bundle) {
    Set<String> keys = bundle.keySet();
    for (String key : keys) {
        Object o = bundle.get(key);
        if (o.getClass().getName().contentEquals("int")) {
            // save ints
        }
        else if (o.getClass().getName().contentEquals("boolean")) {
            // save booleans
        }
        else if (o.getClass().getName().contentEquals("String")) {
            // save Strings
        }
        else {
            // etc.
        }
    } 
  }

Does this approach make sense at all?

Is there a better way of accomplishing this?

Community
  • 1
  • 1
ateiob
  • 9,016
  • 10
  • 44
  • 55
  • 2
    I don't think this design makes any sense. Your preferences and what comes in a bundle shouldn't necesarrily always go into the bundle as you have specific keys that need to be mapped into the preference. These are identified via keys, which you should have hardcoded. – JoxTraex Aug 10 '12 at 17:15
  • I think you are right. But is there any **sane** way to save a Bundle to (local) persistent storage? – ateiob Aug 10 '12 at 17:20
  • Trying using an SQLite database. – JoxTraex Aug 10 '12 at 17:21
  • 3
    @JoxTraex **How?** [Parcel.marshall()](http://developer.android.com/reference/android/os/Parcel.html#marshall%28%29) documentation explicitly warns that *"The data you retrieve here must not be placed in any kind of persistent storage (on local disk, across a network, etc)"*. Which makes the task of generalizing the saving of any Bundle to local Android persistent storage daunting... Ideas? – ateiob Aug 10 '12 at 17:27
  • 1
    Why is this data in a `Bundle` in the first place? – CommonsWare Aug 10 '12 at 23:05
  • I think it's not as crazy of an idea as others are suggesting. In fact, I find a similar helper method for preferences in my own similar research ;) Look at the replaceValues method of https://github.com/googledrive/appdatapreferences-android/blob/master/src/com/google/drive/appdatapreferences/Utils.java – RoundSparrow hilltx Jan 12 '14 at 11:12

2 Answers2

89

Could you save everything as String using the toString() method? Don't know if primitive types are mapped to their Object equivalents (e.g. int to class Integer), but if they are, then you might be able to do something like this, instead of laboriously checking each possible class.

 for (String key : bundle.keySet()) {
        saveKeyValueInPrefs(key, bundle.get(key).toString()); //To Implement
 }

Not sure if this would work for your needs, but I'm trying to do something similar to convert a bundle into a JSON string right now.

Daniel
  • 1,789
  • 17
  • 15
3

I would do it through reflection, if I were to do it at all. Store a static Map such that String.class maps to SharedPreference.putString(), etc. Then, when you're looping through the items check their class against the map. If it doesn't exist, check the superclass, etc. That will either give you the proper method to call or will let you know that the requested object's type isn't something that can be put into the preferences.

So the basic algorithm is:

  1. Get the object from the bundle
  2. Get its class
  3. See if the class is in the map
  4. If it is, invoke the specified method to put it in the SharedPreferences
  5. If it isn't, get it's superclass and return to step 3.
  6. If you get all the way up to java.lang.Object then you've got a bundled object that can't immediately be stored in SharedPreferences. Depending on what classes you've hit along the way you might want to try to handle this as well or you might just want to record the error and move on. Without knowing why you're doing this, it's impossible to guess how you should react when the method fails. It invariably will unless you've got total control over both the bundle and the preferences, but if you've got that amount of control there's no need to jump through all of these hoops because you could be much more straightforward and simply define your own keys.

Note: reflection isn't fast and it isn't the easiest thing to code and maintain. If at all possible I'd recommend finding a less generic method that fits your use case.

Ginger McMurray
  • 1,275
  • 2
  • 20
  • 42
  • 1
    I interpret this as "*Do **not** iIterate through all Bundle objects!*". Accepting since no one else provided a better answer. – ateiob Aug 21 '12 at 15:10