1

When my app goes into background I see onSavedInstanceState is called and I try to save an instance of an object using Parcelable. However, when my app returns to foreground, only onResume is called, never onCreate or onRestoreInstanceState although I save data in onSavedInstanceState. When I continue to use the app, the data is indeed lost and it crashes. Hence I need to make sure the state is recreated.

According to the documentation:

"The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null."

I see that onSavedInstanceState is called by the printout -----Saving Session-----.

The app crashes because some counters to positions in arrays are lost when entering pause-mode. So that is not really a problem, just shows I need to restore that state of the Session-instance.

EDIT: The app crashed due to a silly mistake by me. The data actually did not need to be saved. However, onSaveInstanceState is called, but never onRestoreInstanceState despite the documentation says so. I still do not understand that.

The life-cycle looks like:

OnPause
OnSaveInstanceState
OnStop
OnStart
OnResume

This is how I save the object:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putParcelable(SESSION_KEY, mSession);
    System.out.println(" -----  Saving Session  --------");
}

Restore:

@Override
protected void onRestoreInstanceState(Bundle bundle) {
    System.out.println("OnRestoreInstanceState");
    super.onRestoreInstanceState(bundle);
    String tmp = bundle.getString("TEST_KEY");
    System.out.println(tmp);
}

Implementing Parcelable in Session:

protected Session(Parcel in) {
    mFinalists = in.readArrayList(Finalist.class.getClassLoader());
    shootingOrder = in.readParcelable(ShootingOrder.class.getClassLoader());
    nbrshots = in.readInt();
    nextSession = in.readArrayList(Integer.class.getClassLoader());
    remaining = in.readArrayList(Integer.class.getClassLoader());
    eliminated = in.readArrayList(Integer.class.getClassLoader());
    circleIndex = in.readArrayList(Integer.class.getClassLoader());
    mOldStations = in.readArrayList(OldStations.class.getClassLoader());
}

public static final Creator<Session> CREATOR = new Creator<Session>() {
    @Override
    public Session createFromParcel(Parcel in) {
        System.out.println("Restoring Session");
        return new Session(in);
    }

    @Override
    public Session[] newArray(int size) {
        return new Session[size];
    }
};

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeList(mFinalists);
    dest.writeParcelable(shootingOrder, flags);
    dest.writeInt(nbrshots);
    dest.writeList(nextSession);
    dest.writeList(remaining);
    dest.writeList(eliminated);
    dest.writeList(circleIndex);
    dest.writeList(mOldStations);
    dest.writeList(mCurrentStation);
    dest.writeList(mCurrentColors);
    boolean tmp[] = {isShootOff, isInitilized};
    dest.writeBooleanArray(tmp);
    dest.writeInt(sOffShots);

}

I also implement Finalist, ShootingOrder and OldStation as Parcelable:

protected Finalist(Parcel in) {
    int tmp[] = new int[100];
    in.readIntArray(tmp);
    mName = in.readString();
    mPosition = in.readInt();
    int resultSize = in.readInt();
    result = new ArrayList<>();
    for (int i = 0; i < resultSize; i++){
        result.add(tmp[i]);
    }
    System.out.println("Restoring Finalist");
}

public static final Creator<Finalist> CREATOR = new Creator<Finalist>() {
    @Override
    public Finalist createFromParcel(Parcel in) {
        return new Finalist(in);
    }

    @Override
    public Finalist[] newArray(int size) {
        return new Finalist[size];
    }
};

private int[] getResultArray(){
    int tmp[] = new int[result.size()];
    for (int i = 0; i < result.size(); i++){
        tmp[i] = result.get(i);
    }
    return tmp;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
    int tmp[] = getResultArray();
    dest.writeIntArray(tmp);
    dest.writeString(mName);
    dest.writeInt(mPosition);
    dest.writeInt(result.size());
}
El_Loco
  • 1,716
  • 4
  • 20
  • 35
  • You need to study activity life cycle in detail :). When application goes in background it doesn't exited it only goes into pause state. So when it comes to foreground `onResume()` method is called not `onRestoreInstanceState()`. – Umair Jul 16 '18 at 07:14
  • From the documentation: `The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null`. `--Saving Session--` is called, so something should be saved to the `bundle`. – El_Loco Jul 16 '18 at 07:17
  • It is not necessary that everytime onRestoreInstanceState() is called. You should try getting saved object in onResume() method instead of getting through onRestoreInstanceState(). – Umair Jul 16 '18 at 07:21
  • You mentioned that your app crashes. Can you post the stacktrace? – Iulian Popescu Jul 16 '18 at 07:21
  • It crashes because of that I cannot restore the state of some counters to position in arrays, so that is not really a problem. Just a confirmation of that I need to save some data. – El_Loco Jul 16 '18 at 07:23
  • @Umair onRestoreInstanceState() is always called if a onSaveInstanceState() is made. However, I like to restore the state in `onCreate`, I think that it's easier this way. – Iulian Popescu Jul 16 '18 at 07:24
  • @lucian nope it does not. I have been through this and trust me it's quite frustrating :). – Umair Jul 16 '18 at 07:29
  • @El_Loco why don't you use shared_preferences instead ? – Umair Jul 16 '18 at 07:29
  • @El_Loco Correct if I'm wrong, but this what I think it's happening: you save the data you need, in `onCreate` you get the data you saved, but for some reason the data associated with the arrays is not saved properly and crashes the app when used, right? – Iulian Popescu Jul 16 '18 at 07:31
  • Well, I try to save it in `onSavedInstanceState`, then neither `onCreate` or `onRestoreInstanceState` is called. Since none of those methods are called, I never get the data back. I do not understand why `onRestoreInstanceState` is not called, when the documentation says it should. – El_Loco Jul 16 '18 at 07:34
  • Well, if the current activity is destroyed and should be recreated, then `onCreate` should definitely be called. If it's not called, then the activity is not created again because it is actually in memory (no need to do extra work). Something is really weird here: how is it that `onSaveInstanceState` is called and the others are not? Can you describe the scenario and if you have any developers settings activated (especially `Don't keep activities`)? – Iulian Popescu Jul 16 '18 at 07:40
  • @Umair Is not `sharedPreferences` intended for saving data over longer time, like settings? According to the documentation it is expensive and it does not save objects. – El_Loco Jul 16 '18 at 07:41
  • I discovered I had made a very silly mistake, so the data was already saved. However, it does not answer why `onRestoreInstanceState` is not called although `onSaveInstanceState` is. Further, I still need to save the data when it is actually destroyed. I will check that now. – El_Loco Jul 16 '18 at 08:00
  • my solution [here](https://stackoverflow.com/a/62966140/2828651) to get it called. – صلي علي محمد - Atef Farouk Jul 18 '20 at 08:08

0 Answers0