Archive

Android

During my current personal project I needed so do something I have never done before, try and store an object as a string.

If you have ever developed for Android then you know the annoying fact that Bundles can’t store Objects. In my project, I wanted to save an object for when your Activity/Fragment is restored (onSaveInstanceState). But, I didn’t want to have 20 lines of disgusting code that said

bundle.putString("thisArgument","thisValue");

and I didn’t want to hardcode each variable’s assignment. In case I wanted to change the structure of my Class later on, I didn’t want to have to change the hardcoding for the putting AND retrieval of the variables. Now all I have to do is change how my fragment reads in the JSON data.

I accomplished this with the following code:


public static String objectToJson(Object obj) throws IllegalAccessException, IllegalArgumentException{
    String json = obj.getClass().getName() + " {";

    Field[] fields = obj.getClass().getDeclaredFields();
    for(int i = 0; i < fields.length; i++){
        String before = i > 0 ? ", " : "";
        fields[i].setAccessible(true);
        json += before + fields[i].getName() + ":" + fields[i].get(obj);
    }
    json += "}";
    return json;
}

This code will return the Object’s variables with the following structure:

ClassName {
    variable1:value1,
    variable2:value2,
    variable3:value3
}

The value of each variable will be the String representation of the variable, so if this variable happens to be another Object, just override the toString() function with the data you want to store as the value.

 

So I was able to use this onSaveInstanceState function to store my Object for when the Fragment restores:

MyClass myObject;
public void onSaveInstanceState(Bundle savedState) {
    super.onSaveInstanceState(savedState);

    savedState.putString("MySavedObject",objectToJSON(myObject));
}

Then, later on in my onCreateView function (onCreate if it is an activity, but I am using a fragment) you just check for a savedInstance then restore the data accordingly, just use any JSON parsing library to help out with the parsing.


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    //All the View creation code and stuff...

    if(savedInstanceState != null){
        String savedJSON = savedInstanceState.getString("MySavedObject");

        //Here you would parse the JSON and construct the object again (A lot of libraries for that, but it is a simple enough method)
    }
}

This method is NOT all encompassing, it still only works amazingly with String values and other values like integers or booleans (just use casting), but if you have custom classes it can also be useful because you have the ability to override the toString function and return maybe some JSON data that you can then use to reconstruct that Object too.

It works for what I want, and I think it looks a million times cleaner than dealing with tens of put methods.

 

If you guys wanted a super simple method that parses the JSON data for you straight out, here is what I made to work with this:

public static ArrayList<HashMap<String,String>> parseSimpleJSON(String json) {
    ArrayList<HashMap<String,String>> data = new ArrayList<HashMap<String,String>>();
    String[] objects = json.split("\\}");
    for(int i = 0, len = objects.length; i < len; i++){
        String obj = objects[i];
        String[] parts = obj.split("\\{");
        HashMap<String,String> variables = new HashMap<String,String>();
        for(String variable : parts[1].split(",")) {
            String[] variableData = variable.split(":");
            variables.put(variableData[0].trim(), variableData[1].trim());
        }
        data.add(variables);
    }

    return data;
}

And here is what my reconstruction looks like:

//get 0th because there is only one object in this JSON string
HashMap<String,String> data= Utils.parseSimpleJSON(savedJSON).get(0);
myObject = new Object(data.get("variable1"),data.get("variable2"),data.get("variable3"));

 

-Brandon