0

I have searched the, "custom object passing" issue all over the Internet. There are several solutions but they are all using an Intent to communicate. With Intent, there are methods to facilitate that but what about the method public Parcelable View.onSaveInstanceState()

So, my requirement is saving the state of the view and because it is a custom view, I cannot save the state in the fragment. Rather, I have to override the methods View.onSaveInstanceState() and View.onRestoreInstanceState().

These methods work with Parcelable. I have a view called, BoxDrawingView and a Box class that is contained inside the view.

One more thing - I have tried to Parcelize the Box class.

import android.graphics.PointF;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by Manish Sharma on 9/6/2016.
 */
public class Box implements Parcelable{
    private PointF mOrigin;
    private PointF mCurrent;
    public Box(PointF origin) {
        mOrigin = origin;
        mCurrent = origin;
    }
    public PointF getCurrent() {
        return mCurrent;
    }
    public void setCurrent(PointF current) {
        mCurrent = current;
    }
    public PointF getOrigin() {
        return mOrigin;
    }

    @Override
    public int describeContents() {
        return 0;
    }
    public static final Parcelable.Creator<Box> CREATOR
            = new Parcelable.Creator<Box>() {
        public Box createFromParcel(Parcel in) {
            return new Box(in);
        }

        public Box[] newArray(int size) {
            return new Box[size];
        }
    };
    private Box(Parcel in) {
        mOrigin = (PointF)in.readValue(ClassLoader.getSystemClassLoader());
        mCurrent = (PointF)in.readValue(ClassLoader.getSystemClassLoader());
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeValue(mOrigin);
        out.writeValue(mCurrent);
    }


}

Now, here is the custom view that is supposed to call those 2 lifecycle methods for saving the state:

package com.example.manishsharma.draganddraw;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Manish Sharma on 9/5/2016.
 */
public class BoxDrawingView extends View {
    private static final String TAG = "BoxDrawingView";

private Box mCurrentBox;
private List<Box> mBoxen = new ArrayList<>();
private Paint mBoxPaint;
private Paint mBackgroundPaint;

// Used when creating the view in code
public BoxDrawingView(Context context) {
    this(context, null);
}
// Used when inflating the view from XML
public BoxDrawingView(Context context, AttributeSet attrs) {
    super(context, attrs);

    // 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);
}

@Override
protected void onDraw(Canvas canvas) {
    // Fill the background
    canvas.drawPaint(mBackgroundPaint);
    for (Box box : mBoxen) {
        float left = Math.min(box.getOrigin().x, box.getCurrent().x);
        float right = Math.max(box.getOrigin().x, box.getCurrent().x);
        float top = Math.min(box.getOrigin().y, box.getCurrent().y);
        float bottom = Math.max(box.getOrigin().y, box.getCurrent().y);
        canvas.drawRect(left, top, right, bottom, mBoxPaint);
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    PointF current = new PointF(event.getX(), event.getY());
    String action = "";
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            action = "ACTION_DOWN";
            // Reset drawing state
            mCurrentBox = new Box(current);
            mBoxen.add(mCurrentBox);
            break;
        case MotionEvent.ACTION_MOVE:
            action = "ACTION_MOVE";
            if (mCurrentBox != null) {
                mCurrentBox.setCurrent(current);
                invalidate();
            }
            break;
        case MotionEvent.ACTION_UP:
            action = "ACTION_UP";
            mCurrentBox = null;
            break;
        case MotionEvent.ACTION_CANCEL:
            action = "ACTION_CANCEL";
            mCurrentBox = null;
            break;
    }
    Log.i(TAG, action + " at x=" + current.x +
            ", y=" + current.y);
    return true;
}

@Override
public Parcelable onSaveInstanceState(){
    super.onSaveInstanceState();
    //How do I proceed here?
}
}

So finally I have: An arraylist of Parcelable objects that I want to save. How do I do that?

P.S: If I use the method Bundle.putParcelableArrayList(String key, ArrayList<? extends Parcelable> value), it doesn't work because the Box class implements the Parcelable interface not extend it.

Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
Manish Kumar Sharma
  • 12,982
  • 9
  • 58
  • 105

2 Answers2

1

save state

@Override
public Parcelable onSaveInstanceState(){
    Parcelable superState = super.onSaveInstanceState();
    Bundle bundle = new Bundle();
    bundle.putParcelable("super", superState);
    bundle.putParcelableArrayList("list", mBoxen);
    return bundle;
}

and restore

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if (state instanceof  Bundle) {
        super.onRestoreInstanceState(((Bundle) state).getParcelable("super"));
        mBoxen = ((Bundle) state).getParcelableArrayList("list");
    } else {
        super.onRestoreInstanceState(state);
    }
}

this should work. what is the problem with bundle.putParcelableArrayList("list", mBoxen);?

AssIstne
  • 466
  • 4
  • 13
  • It worked! I was gonna do this initially but I got entangled in the parameter asked vs parameter supplied. So, the method bundle.putParcelableArrayList(); demands extends Parcelable> but I thought since my class implemented Parcelable, there would be problem in type compatibility. But when I tried casting the list to ArrayList in the parameter, it worked. It was rust on my Java basics. Actually, it should work because any type that extends Parcelable has got a "is-a" relationship with Parcelable and any type that extends this type has also got an "is-a" relationship with Pacelable. – Manish Kumar Sharma Sep 07 '16 at 09:46
-1

I think you should use:

@Override
protected void onSaveInstanceState(Bundle outState) {}

and putExtra into outState bundle.

matejko219
  • 1,601
  • 10
  • 14