Challenge 1: my solution


#1

So, I was able to solve challenge 1 this way. I added two new methods to BoxDrawingVies:

@Override
	protected Parcelable onSaveInstanceState() {
		Parcelable savedState = super.onSaveInstanceState();
		JSONArray array = new JSONArray();
		try {
			for (Box box : mBoxes)
				array.put(box.toJSON());
		}
		catch (JSONException je) {	
			Log.e(TAG, "JSON Exception ocurred", je);
		}
	 
		Bundle state = new Bundle();
		state.putParcelable("savedState", savedState);
		state.putString("Boxes", array.toString());
		return state;
	}
	
	@Override
	protected void onRestoreInstanceState(Parcelable state) {
		Parcelable savedState = ((Bundle) state).getParcelable("savedState");
		super.onRestoreInstanceState(savedState);
		
		String jsonString = ((Bundle) state).getString("Boxes");
		try {
			JSONArray array = (JSONArray) new JSONTokener(jsonString)
				.nextValue();
			for (int i = 0; i < array.length(); i++)
				mBoxes.add(new Box(array.getJSONObject(i)));
			
		} catch (JSONException je) {
			Log.e(TAG, "Json Exception", je);
		}
	}

I also added a new constructor and a toJSON method to Box (btw I chose JSON after reading up on serialization methods in the Android docs. They recommend JSON since it is terse yet human-readable.)

	public Box(JSONObject json) throws JSONException {
		if (json.get("orig_x") != null);
			mOrigin = new PointF(
					(float) json.getDouble("orig_x"),
					(float) json.getDouble("orig_y")
			);
			
			if (json.get("curr_x") != null);
			mCurrent = new PointF(
					(float) json.getDouble("curr_x"),
					(float) json.getDouble("curr_y")
			);
	}

    public JSONObject toJSON() throws JSONException {
        JSONObject json = new JSONObject();
        if (mOrigin != null) {
        	json.put("orig_x", mOrigin.x);
        	json.put("orig_y", mOrigin.y);
        }
        if (mCurrent != null) {
        	json.put("curr_x", mCurrent.x);
        	json.put("curr_y", mCurrent.y);
        }
        return json;
    }

That did it!

Oops, almost forgot to say that I created a resource file view_id.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item type="id" name="view_id"></item>
</resources>

and set the id in the BoxDrawingView constructor:

public BoxDrawingView(Context context, AttributeSet attrs){
		super(context, attrs);
...
// Set id
		setId(R.id.view_id);
}

I suppose it could be nicer/neater if I created a BoxModel class that held the Boxes and included saveToJson and restoreFromJson methods, or something like that.


#2

My solution using bundles and parcelables.

[code] @Override
protected Parcelable onSaveInstanceState(){
Bundle onSaveInstanceState = new Bundle();
onSaveInstanceState.putParcelable(KEY_INDEX, super.onSaveInstanceState());
onSaveInstanceState.putSerializable(KEY_INDEX, mBoxes);

	return onSaveInstanceState;
}

@Override
protected void onRestoreInstanceState(Parcelable state){
	
	Bundle onSaveInstanceState = (Bundle)state;
	mBoxes = (ArrayList<Box>)onSaveInstanceState.getSerializable(KEY_INDEX);
	super.onRestoreInstanceState(onSaveInstanceState.getParcelable(KEY_INDEX));
	invalidate();
}

[/code]

Important to set the View_id in the constructor
The View Id is just some static int with an arbitrary value under 1000 that I set earlier.

[code]//Used when inflating the view from XML
public BoxDrawingView(Context context, AttributeSet attrs){
super(context,attrs);

	this.setId(VIEW_ID);
	
	//Paint the boxes a nice semitransparent red(ARGB)
	mBoxPaint = new Paint();
	mBoxPaint.setColor(0x22ff0000);
	
	//Paint the background off-white
	mBackgroundPaint = new Paint();
	mBackgroundPaint.setColor(0xfff8efe0);
}
[/code]