Previously i wrote an app that used reflection to serialize data from json to objects and that solution worked fine. Now i am working on V2.0 of this app and i am now trying to isolate all the model logic in a service and make the activity layer separate from that. The purpose of this being that the service can live in the background and run periodical updates against the web service.
My problem is that as soon as i try to use reflection to instantiate an object that implements the parcelable interface it throws an InstantiationException. My guess is that the parcelable interface in some way interferes whit the default constructor of the object.
One solution is to make an intermediary object that i build and then send that object to the constructor of the correct parcelable object and send that object in the IPC. But i feel that there might be a simpler solution involving the use of parcelable in some way that i have not thought of yet.
public class ManagedObjectWrapper {
private Object anObject;//the instance of the object itself
private Class<?> theClass;//Metadata
private Field[] declaredFields;//Metadata
public ManagedObjectWrapper(Class<?> c){
theClass=c;
declaredFields = c.getDeclaredFields();
try {
//this is where it crashes
anObject = c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e){
e.printStackTrace();
}
}
public Object GetObject(){return this.anObject;}
public Class<?> GetClass(){return this.theClass;}
public Field[] GetDeclaredFields(){return this.declaredFields;}
}
This is how i use reflection to get my objects from the json
private ArrayList<ManagedObjectWrapper> getObjectsFromJSON(String pluralizedColumn,JSONArray array) throws Exception
{
ArrayList<ManagedObjectWrapper> returnList = new ArrayList<ManagedObjectWrapper>();
String packageName = extContext.getPackageName();
String singularObjectName = pluralizedColumn.substring(0, pluralizedColumn.length()-1);//remove the plural s
String canonicalClassName = packageName.concat(".").concat(singularObjectName);
Class<?> theClass = Class.forName(canonicalClassName);
for(int i = 0;i < array.length(); i++){
ManagedObjectWrapper mow = new ManagedObjectWrapper(theClass);
JSONObject obj = array.getJSONObject(i);
for(Field field : mow.GetDeclaredFields()){
Class<?>[] params = {field.getType()
};
if(!field.getName().contentEquals("CREATOR")){
Method setterMethod = mow.GetClass().getDeclaredMethod(SET_METHOD_PREFIX.concat(field.getName()),params);
Object nullTest = obj.get(field.getName());
if(nullTest.equals(null)){
}else{
setterMethod.invoke(mow.GetObject(), obj.get(field.getName()));
}
}
}
returnList.add(mow);
}
Yes it can. Just implement a default constructor on the class , other more deeply hidden errors in the code made me think it was not that simple. But circling back to this issue made me try it again and voila now it works just like before