Cannot restore Object from Instance state: parsing error - android

I am trying to restore an array of Objects from a savedInstanceState. I added each one to the Bundle individually here: (rhythm is the array of Objects)
#Override
public void onSaveInstanceState(Bundle outState){
outState.putInt("numParts",rhythm.length);
for(int index = 0;index<rhythm.length;++index){
outState.putSerializable(""+index,rhythm[index].beat);
}
super.onSaveInstanceState(outState);
}
When the onRestoreInstanceState() method is called, I try to assign my rhythm array with the Objects from the Instance State here: (it isn't null)
#Override
public void onRestoreInstanceState(Bundle savedInstanceState){
rhythm = new Part[savedInstanceState.getInt("numParts")];
for(int index = 0; index<rhythm.length;++index){
Object middleMan =savedInstanceState.getSerializable(""+index);
if(middleMan==null){
System.out.println("It's null...");
}
rhythm[index]=(Part) middleMan;
}
}
It throws a ClassCastException when I parse to a Part every time. Part implements Serializable. Why is it not allowing me to parse? Will I need to do custom serialization?
Please help!

I am guessing that Part is a type that you have created? So instead of treating Part as an array
rhythm = new Part[savedInstanceState.getInt("numParts")];
You want to instantiate a new Part object like so:
rhythm = new Part(savedInstanceState.getInt("numParts"));
Other assumptions:
rhythm is a member variable
The constructor for Part takes a single integer

Okay I just did it as the whole array and it worked... I don't really know why, but it did. Thanks for giving me the idea to just pass the whole array. #Error 454

Related

Get variable value from method to outside

private String u_id;
private String u_name;
#Override
public void onSuccess(LoginResult loginResult) {
if(Profile.getCurrentProfile() == null) {
mProfileTracker = new ProfileTracker() {
#Override
public void onCurrentProfileChanged(Profile profile, Profile profile2) {
// profile2 is the new profile
u_id = profile2.getId().toString();
u_name = profile2.getName().toString();
mProfileTracker.stopTracking();
}
};
// no need to call startTracking() on mProfileTracker
// because it is called by its constructor, internally.
}
else {
Profile profile = Profile.getCurrentProfile();
u_id = profile.getId().toString();
u_name = profile.getName().toString();
}
/*new CreateNewProduct().execute();*/
/*updateFacebookButtonUI();*/
}
I want get value u_id and u_name to add arraylist, but it return null. I tried log have result. I need way resolve. Thanks :(
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("u_id", u_id)); // return null
params.add(new BasicNameValuePair("u_name", u_name)); // return null
Yes, adding "" results will not be null, but I want to get the value of the variable inside the onSuccess method to pass to the List below. The list below is in another class in same file with on Success
Variables u_id and u_name can be null only if they were not initialised. You don't set their value when adding the field to the class.
private String u_id; //only type and name set, not the value
I think if you're sure their value have to be set somewhere in the inner methods (doesn't matter in if or else either), it's not so dangerous to leave it like this. Also I would bet you're calling params.add(...)... after the above lines, unless it would cause the variables being null too...
But if you really want to get something back from your variables, you can initialise them as plain empty strings (""),
private String u_id = ""; //the variable's value is set too
and maybe later handle the "empty-string" checking before adding their value to your List<NameValuePair> variable; however it's not necessary. The main thing is: this way you can be 100% sure your variables won't be null...
EDIT #1: I don't know much about the structure of your file which contains onSuccess() method and the class with your list inside of it, but I would say it's another Java class file (MyClass.java or similar). I'm not an expert in Android multithreading, but I would say there is not anything that could block your inner class with your list to access the fields in the outer base class. You can reach fields anytime and anywhere in a class, no matter you want to do it in that very class or in the 10th nested inner class or method.
So unless your code does not look similar to this, I would think my first answer (above the edit) should be the solution. Maybe you should provide the code of your full class(es) to find the best solution, not just parts like you did first time.

How to fetch object and array fields with Parse?

I'm unable to properly fetch a ParseObject that contains a field of type 'Object' : after changing manually the 'Object' field value in the Parse DataBrowser and then fetch the ParseObject from the app, the fetched ParseObject still provide the old value for the 'Object' field, but provide the right new value for the 'String' field.
Here is the sample code I use :
public class MainActivity extends ActionBarActivity {
ParseObject object;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
object = ParseObject.createWithoutData("Test", "tvgTg8jAXz");
}
#Override
protected void onResume() {
super.onResume();
object.fetchInBackground().onSuccess(new Continuation<ParseObject, Object>() {
#Override
public Object then(Task<ParseObject> task) throws Exception {
JSONObject data = task.getResult().getJSONObject("data");
String name = task.getResult().getString("name");
Log.d("OBJECT", data.toString());
Log.d("OBJECT", name);
return null;
}
}).continueWith(new Continuation<Object, Object>() {
#Override
public Object then(Task<Object> task) throws Exception {
if (task.getError() != null) {
Log.e("OBJECT", task.getError().getLocalizedMessage());
}
return null;
}
});
}
}
After I change both 'data' and 'name' fields in the DataBrowser, if 'onResume()' is called without a previous call to 'onCreate()' (after locking/unlocking screen for example) then the logs shows the old value for 'data' and the new value for 'name'.
This is a simple code example to highlight the problem I encounter in a bigger project.
Is this a known issue of the Parse Android SDK ? Is there a workaround ?
Thanks
Now that I learned that you have turned on the local datastore I can come with an, at least partial, answer.
Turning on the local datastore has some side effects. One being that only one instance of each object exists locally. So when you call fetchInBackground the second time, object is already populated with data. The problem then (i think) is that the API no longer override 'complex' types (pointers, objects, arrays), perhaps because it could mess up internal relationships in the data store. Since the fact that the data store will recursively save an object (and pointers) so suddenly swapping a pointer might leave objects 'hanging'. (again, only guessing).
Now I must admit that it still confuses me a bit looking at your code, cause it does not seem that you at any point write your object to the data store, however..
What should work is to unpin the object before 'refreshing' it:
object.unpinInBackground.onSuccess(new Continuation<>{
...
// when done call fetch
});
According to Parse, this is a known issue that they will not fix for now : https://developers.facebook.com/bugs/1624269784474093/
We must use the following methods to retrieve JSON objects/arrays fields from a ParseObject :
getMap() instead of getJSONObject()
getList() instead of getJSONArray()
These methods will return Map and List objects respectively.
I found that managing Map and List in my project instead of JSONObjet and JSONArray is not a problem and is even clearer.

NullPointerException after resuming the application

Ok, this annoying problem is probably quite familiar, but I don't know what its being called and how to solve it. When I open my app and go to the menu and after a meanwhile, when resuming the app, I loose all my data. It seems that android likes to clean data in order to keep the OS as fast and stable as possible. Which method is recommended in saving data in the internal memory and retrieving it back when any kind of variable is cleaned/null before resuming the app? I tried setSharedPreferences to parse an ArrayList to an Object and parse the Object as a String to save the data and retrieve it, but I get cannot parse Object to String exception. There has to be a better alternative.
Any help will be appreciated.
Edit:
This is how I retrieve and store data:
JSONObject data = (JSONObject) new JSONTokener(result).nextValue();
Helper.RAW_PEOPLE_INFO = data.getJSONArray("people");
Helper.PEOPLE_CONTAINER = new ArrayList<PeopleInfoStorage>();
for( int i = 0; i < Helper.RAW_PEOPLE_INFO.length(); i++ ){
Helper.PEOPLE_CONTAINER.add( new PeopleInfoStorage(Helper.RAW_PEOPLE_INFO.getJSONObject(i)) );
}
I use the PEOPLE_CONTAINER ArrayList to use it later for when I need it. The PEOPLE_CONTAINER ArrayList gets probably cleaned before I resume my application, so can someone help me giving an example on how to store this ArrayList in the internal memory so I can retrieve the data from the internal memory and put it back to the PEOPLE_CONTAINER ArrayList for when it's null again.
It needs to be something like this:
#Override
protected void onPause() {
if( Helper.PEOPLE_CONTAINER != null ){
//save the Helper.PEOPLE_CONTAINER ArrayList to the internal memory
}
super.onPause();
}
#Override
protected void onResume() {
if( Helper.PEOPLE_CONTAINER == null ){
//retrieve the data and store it back to Helper.PEOPLE_CONTAINER ArrayList
}
super.onResume();
}
There are many methods to persist data in your application; I'm not going to go into great detail here, but you should check out these resources:
http://developer.android.com/guide/topics/data/data-storage.html
If you have an array list, it sounds like it might be worth SQLite.

Android Can't save to an array

I have global array. When i want to save something in some method and after that show it from that array it has error NullPointerException. Array is Object type. Code is like this
class Something {
public CoordinatesObject[] coordinates;
Something() {
coordinates = new CoordinatesObject[4];
}
public String myMethod() {
if (coordinates.length==0){
coordinates[0] = new CoordinatesObject(0,0);
}
}
return Integer.toString(coordinates[0].getX());
}
What's wrong?
Sorry I have updated the code. I've created a new array in constructor
You created an array with this line:
coordinates = new CoordinatesObject[4];
and then you're trying to create CoordinatesObject like that:
if (coordinates.length==0){
coordinates[0] = new CoordinatesObject(0,0);
}
but coordinates.length is going to be equal to 4 which means an object of CoordinatesObject class won't be created.
You need to actually allocate space for the array, right now you just have a reference to nothing.
Also note that arrays are fixed-length, you may want to consider using a collection (like a list) instead, depending on your needs.
You have to create the Array with new as well.
Currently, you have a NULL reference. As the previous poster points out, you need to define and create some space for your array.

Bundle of array of arraylist

How can I put an array of arrayList into a Bundle?
ArrayList < myObjects >[] mElements;
Make YourObject implement the Parcelable interface, then use bundle.putParcelableArraylist(theParcelableArraylist).
Edit: whoops misread the question. Why do you want to save an array of arraylist? If its for persisting in an orientation change, maybe you want to use onRetainNonConfigurationInstance instead?
Edit 2: Ok, here goes. Create a new Wrapper class that implements Parcelable (note that myObjects also have to be parcelable). The writeToParcel method will look something like this:
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mElements.length);
for(ArrayList<MyObject> element : mElements) {
dest.writeParcelableArray(element.toArray(new MyObject[0]), flags);
}
}
And the constructor:
private Wrapper(Parcel in) {
int length = in.readInt();
//Declare list
for (int i = 0; i < length; i++) {
MyObject[] read = in.readParcelableArray(Wrapper.class.getClassLoader());
//add to list
}
}
Not possible using bundle, as bundle allows arraylist of primitives only...
Try to use parcleable or application level data or static variable (bad practice).
If your objects support serialization, marked with the Serializable interface, then you should be able to use bundle.putSerializable.
ArrayList supports Serializable , but I'm not sure about a plain array.
I just use putSerializable(myarraylistofstuff) and then I get back with a cast using get(), you just need to silence the unchecked warning. I suspect (correct me if wrong) you can pass any object faking it as Serializable, as long you stay in the same process it will pass the object reference. This approach obviously does not work when passing data to another application.
EDIT: Currently android passes the reference only between fragment, I've tried to pass an arbitrary object to an Activity, it worked but the object was different, same test using arguments of Fragment showed same Object instead.
Anyway it deserializes and serializes fine my Object, if you have a lot of objects it's better to use Parcel instead

Categories

Resources