我有一个布局,只需按一下按钮即可动态添加自定义视图。这些布局扩展了LinearLayout,每个布局都带有自己独特的Action对象。
但是,如果再次调用onCreate,当用户导航或旋转屏幕时,视图将消失。我想在那里保留这些自定义ActionHolder视图。要添加问题,ActionHolder对象包含敏感信息。 Action对象本身存储一个实时计时器(即使应用程序关闭也应该保持计时),以及其他信息。
根据下面的答案,我做了以下,但无济于事。以下是我到目前为止的情况:
public class ActionHolder extends LinearLayout implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2271402255369440088L;
private Action action;
private String timer;
public static final int ACTION_TITLE = 0, ACTION_TIMER = 1,
PAUSEANDPLAY_BTN = 2, FINISH_BTN = 3;
public ActionHolder(Context context) {
super(context);
}
public ActionHolder(Context context, AttributeSet attr) {
super(context, attr);
}
public ActionHolder(Context context, AttributeSet attr, int defStyle) {
super(context, attr, defStyle);
}
public void initiate(Action input) {
// int hashedID = input.getActionName().hashCode();
// if (hashedID < 0)
// hashedID *= -1;
// this.setId(hashedID);
this.setOrientation(LinearLayout.VERTICAL);
this.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
action = input;
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.action_holder_layout, this, true);
TextView actionTitle = (TextView) view
.findViewById(com.tonimiko.mochi_bean.R.id.action_holder_title);
actionTitle.setText(action.getActionName());
actionTitle.setId(ActionHolder.ACTION_TITLE);
TextView actionTimer = (TextView) view
.findViewById(R.id.action_holder_timer);
actionTimer.setId(ActionHolder.ACTION_TIMER);
Button pauseBtn = (Button) view
.findViewById(com.tonimiko.mochi_bean.R.id.pause_and_play_timer_btn);
pauseBtn.setId(ActionHolder.PAUSEANDPLAY_BTN);
Button finishBtn = (Button) view
.findViewById(com.tonimiko.mochi_bean.R.id.finish_activity_button);
finishBtn.setId(ActionHolder.FINISH_BTN);
action.setActivityStartTime();
}
public Action finishAction() {
action.setActivityStopTime();
return action;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
public String toString() {
return "Action stored: " + action.getActionName();
}
@Override
public boolean equals(Object other) {
ActionHolder otherObj = (ActionHolder) other;
if (this.action.getActionName().toUpperCase()
.equals(otherObj.action.getActionName().toUpperCase()))
return true;
return false;
}
@Override
public int hashCode() {
return action.getActionName().hashCode();
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
Bundle data = new Bundle();
data.putString("Timer", timer);
data.putSerializable("Action", action);
Log.e("debug", "View onSaveInstanceState called!"); // TODO
Parcelable test = new ActionHolderSavedState(superState, data);
if(test==null)
Log.e("debug", "NULL PARCELABLE"); // TODO
return new ActionHolderSavedState(superState, data);
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
Log.e("debug", "View onRestore called!");
if (state instanceof ActionHolderSavedState) {
final ActionHolderSavedState savedState = (ActionHolderSavedState) state;
this.action = savedState.getAction();
this.timer = savedState.getTimer();
// this.initiate(action);
super.onRestoreInstanceState(savedState.getSuperState());
Log.e("debug", "View onRestoreInstanceState finished"); // TODO
}
}
static class ActionHolderSavedState extends BaseSavedState {
private Action storedAction;
private String storedTimer;
public ActionHolderSavedState(Parcelable superState, Bundle data) {
super(superState);
storedTimer = data.getString("Timer");
storedAction = (Action) data.getSerializable("Action");
}
private ActionHolderSavedState(Parcel in) {
super(in);
storedTimer = in.readString();
storedAction = in.readParcelable(ActionHolder.class.getClassLoader());
}
public Action getAction() {
return storedAction;
}
public String getTimer() {
return storedTimer;
}
@Override
public void writeToParcel(final Parcel out, final int flags) {
super.writeToParcel(out, flags);
out.writeString(storedTimer);
out.writeSerializable(storedAction);
}
// required field that makes Parcelables from a Parcel
public static final Parcelable.Creator<ActionHolderSavedState> CREATOR = new Parcelable.Creator<ActionHolderSavedState>() {
public ActionHolderSavedState createFromParcel(final Parcel in) {
return new ActionHolderSavedState(in);
}
public ActionHolderSavedState[] newArray(int size) {
return new ActionHolderSavedState[size];
}
};
}
}
有没有我做错了?我已经花了将近4天的时间。
答案 0 :(得分:2)
我的情况与您的情况非常相似,自定义视图会动态添加到屏幕上,例如,当活动被操作系统杀死并稍后重新创建时需要保存状态。
我在自定义视图上覆盖了onSaveInstanceState
。它需要返回一个Parcelable
对象。关键是要创建一个扩展BaseSavedState
的自定义类,并将您的数据存储到Parcelable
中。看起来有点像这样:
@Override protected Parcelable onSaveInstanceState() { final Parcelable state = super.onSaveInstanceState(); return new ContainerLayoutSavedState(state, data); } @Override protected void onRestoreInstanceState(final Parcelable state) { if (state instanceof ContainerLayoutSavedState) { final ContainerLayoutSavedState savedState = (ContainerLayoutSavedState)state; this.data = savedState.getData(); super.onRestoreInstanceState(savedState.getSuperState()); } } public static class ContainerLayoutSavedState extends BaseSavedState { private String data; ContainerLayoutSavedState(final Parcelable superState, final String data) { super(superState); // Here in this constructor you inject whatever you want to get saved into the Parcelable object. In this contrived example, we're just saving a string called data. this.data = data; } private ContainerLayoutSavedState(final Parcel in) { super(in); data = in.readString(); } public String getData() return data; } @Override public void writeToParcel(final Parcel out, final int flags) { super.writeToParcel(out, flags); out.writeString(data); } // required field that makes Parcelables from a Parcel public static final Parcelable.Creator<ContainerLayoutSavedState> CREATOR = new Parcelable.Creator<ContainerLayoutSavedState>() { @Override public ContainerLayoutSavedState createFromParcel(final Parcel in) { return new ContainerLayoutSavedState(in); } @Override public ContainerLayoutSavedState[] newArray(final int size) { return new ContainerLayoutSavedState[size]; } }; } }
另外,不要忘记将ID设置为动态添加的视图,以便在您返回时将它们重新添加到视图树中。