如何通过 View.onSaveInstanceState() 方法传递自定义对象列表?

How to pass a list of custom object through the method View.onSaveInstanceState()?

我在整个 Internet 上搜索了 "custom object passing" 问题。有几种解决方案,但它们都使用 Intent 进行通信。对于 Intent,有一些方法可以促进这一点,但是方法 public Parcelable View.onSaveInstanceState()

呢?

所以,我的要求是保存视图的状态,因为它是自定义视图,所以我无法在片段中保存状态。相反,我必须覆盖方法 View.onSaveInstanceState()View.onRestoreInstanceState().

这些方法适用于 Parcelable。我有一个名为 BoxDrawingView 的视图和一个包含在视图中的 Box class。

还有一件事 - 我已经尝试将 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);
    }


}

现在,这是应该调用这 2 个生命周期方法来保存状态的自定义视图:

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?
}
}

所以我终于有了:我要保存的 Parcelable 个对象的数组列表。我该怎么做?

P.S:如果我使用方法 Bundle.putParcelableArrayList(String key, ArrayList<? extends Parcelable> value),它不起作用,因为 Box class 实现了 Parcelable 接口而不是扩展它.

我认为你应该使用:

@Override
protected void onSaveInstanceState(Bundle outState) {}

并将 Extra 放入 outState 包中。

保存状态

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

并恢复

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

这应该有效。 bundle.putParcelableArrayList("list", mBoxen); 有什么问题?