views:

63

answers:

2
public class XPBN extends Activity{
private Map _map;

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);

    final Map data = (Map)getLastNonConfigurationInstance();
    if (data == null) {
        Toast.makeText(this, "New Map", Toast.LENGTH_SHORT).show();
        _map = new Map(this);
    } else {
        Toast.makeText(this, "Old Map", Toast.LENGTH_SHORT).show();
        _map = (Map)data;
    }

    setContentView(_map);
}

@Override
public Object onRetainNonConfigurationInstance() {
    Toast.makeText(this, "Saving Configuration...", Toast.LENGTH_LONG).show();
    return _map;
}

}

I am going to suppose that the title I gave this forum-thread states the problem I am experiencing pretty thoroughly. I have also edited the code to try to save a string object and then recover the string object through the getLastNonConfigurationInstance(), just to see to what extent I could get it to work for me, but it still seemed to return null. I have not tried calling it from onStart() or onRestart() or onResume(), but from what I have read, it is usually only called from onCreate(Bundle) anyways. This has got me really confused... :/

I figured it may be of some help to know a little about my Map class object, so here's (some of) the code from it:

public class Map extends SurfaceView implements SurfaceHolder.Callback{
private MapThread _mapThread;
private int _terrain[][];
private ArrayList<Player> playerList;
private Bitmap _blueback;
private Bitmap _bluefront;
private Bitmap _blueleft;
private Bitmap _blueright;
private Bitmap _greenback;
private Bitmap _greenfront;
private Bitmap _greenleft;
private Bitmap _greenright;
private Bitmap _redfront;
private Bitmap _redback;
private Bitmap _redleft;
private Bitmap _redright;
private Bitmap _robot1;
private Bitmap _forest;
private Bitmap _grass;
private Bitmap _mountain;
private Bitmap _tree;
@SuppressWarnings("unused")
private boolean _mapLoaded = false;
private int _viewX = 0;
private int _viewY = 0;

Map(Context context){
    super(context);
    getHolder().addCallback(this);
    _mapThread = new MapThread(this);
    setFocusable(true);

    _terrain = new int[100][100];
    playerList = new ArrayList<Player>();
    addPlayer(0, 0, 0);

    _blueback = BitmapFactory.decodeResource(context.getResources(), R.drawable.blueback);
    _bluefront = BitmapFactory.decodeResource(context.getResources(), R.drawable.bluefront);
    _blueleft = BitmapFactory.decodeResource(context.getResources(), R.drawable.blueleft);
    _blueright = BitmapFactory.decodeResource(context.getResources(), R.drawable.blueright);
    _greenback = BitmapFactory.decodeResource(context.getResources(), R.drawable.greenback);
    _greenfront = BitmapFactory.decodeResource(context.getResources(), R.drawable.greenfront);
    _greenleft = BitmapFactory.decodeResource(context.getResources(), R.drawable.greenleft);
    _greenright = BitmapFactory.decodeResource(context.getResources(), R.drawable.greenright);
    _redback = BitmapFactory.decodeResource(context.getResources(), R.drawable.redback);
    _redfront = BitmapFactory.decodeResource(context.getResources(), R.drawable.redfront);
    _redleft = BitmapFactory.decodeResource(context.getResources(), R.drawable.redleft);
    _redright = BitmapFactory.decodeResource(context.getResources(), R.drawable.redright);
    _robot1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.robot1);
    _forest = BitmapFactory.decodeResource(context.getResources(), R.drawable.forest);
    _grass = BitmapFactory.decodeResource(context.getResources(), R.drawable.grass);
    _mountain = BitmapFactory.decodeResource(context.getResources(), R.drawable.mountain);
    _tree = BitmapFactory.decodeResource(context.getResources(), R.drawable.tree);

    TouchScreenHandler handler = new TouchScreenHandler(); // This includes 2 other nested-class threads
    this.setOnTouchListener(handler);
}

Perhaps there lies something in the complexity of the Object returned by onRetainNonConfigurationInstance() that might be contributing to my problems?

Or lastly is there something (like a Activity or Application property) in my Manifest.xml file that is the problem?

If any further information is required, please let me know, as I will be checking back on this post frequently until I can get past this little bump in the road.
PS: I have this problem with both ADB and my device.
PSS: most importantly, a big THANKS to this community for the help and support, as it is greatly appreciated! :D

+1  A: 

Not sure about the solution to your problem there is another problem with your code. You shouldn't use onRetainNonConfigurationInstance for anything like that holds a reference to the activity context, otherwise you will leak the activity later.

Al
I just need the state to be maintained after it returns to the top of the task stack. Should I consider making this an android service type application then? Or should I compact all the specifically required data and objects into an ArrayList object and use that, and try to get the onRetainNonConfigurationInstance to work? btw, are there any common circumstances under which onRetainNonConfigurationInstance does not function properly? I would assume not...
sduffy89
A: 

Have you confirmed that onRetainNonConfigurationInstance() is actually being called? I see you have a toast being displayed in it, but you don't actually say it is being shown. (And why a toast instead of just a Log.i()?)

As the documentation says, "this function is called purely as an optimization, and you must not rely on it being called." You can't rely on this actually happening. The only time it will happen in fact is when a configuration change happens while your activity is in the foreground, in which case the framework will in one feel swoop call onRetainNonConfigurationInstance() and destroy the current instance and immediately create a new instance with the retained object available to it. There should be pretty much nothing you can do that would prevent the object you return from appearing in the new instance... though I guess if you call finish() or such on the old one, that might do it.

Working code that uses this feature can be found here: http://android.git.kernel.org/?p=platform/packages/apps/Settings.git;a=blob;f=src/com/android/settings/RunningServices.java

For reference, the framework function that does the retain/destroy/recreate is:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/app/ActivityThread.java;h=773c344bb3f69985a046c67ade9806b6c1d061a5;hb=HEAD#l3714

hackbod