保存动态添加LinearLayouts不使用savedInstanceState? [英] Saving dynamically added LinearLayouts without using savedInstanceState?

查看:383
本文介绍了保存动态添加LinearLayouts不使用savedInstanceState?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我已经在按一下按钮动态添加自定义视图的布局。这些布局扩展的LinearLayout和各自携带自己独特的Action对象。

的意见将消失,但是,如果是的onCreate再次调用,当用户导航离开或旋转屏幕。我想保持这些自定义ActionHolder意见那里。为了增加问题,ActionHolder对象包含敏感信息。该行动对象本身存储的实时计时器(即应该保持在滴答作响,即使应用程序关闭时),以及其他信息。

根据下面的答案,我已经做以下,但无济于事。以下是我迄今为止:

 公共类ActionHolder扩展的LinearLayout实现Serializable {   / **
    *
    * /
   私有静态最后的serialVersionUID长= 2271402255369440088L;
   私人诉讼行动;
   私人字符串定时器;
   公共静态最终诠释ACTION_TITLE = 0,ACTION_TIMER = 1,
         PAUSEANDPLAY_BTN = 2,FINISH_BTN = 3;   公共ActionHolder(上下文的背景下){
      超级(上下文);
   }   公共ActionHolder(上下文的背景下,ATTR的AttributeSet){
      超(背景下,ATTR);
   }   公共ActionHolder(上下文的背景下,ATTR的AttributeSet,诠释defStyle){
      超(背景下,ATTR,defStyle);
   }   公共无效启动(动作输入){
      // INT hashedID = input.getActionName()哈希code();
      //如果(hashedID℃,)
      // hashedID * = -1;
      // this.setId(hashedID);
      this.setOrientation(LinearLayout.VERTICAL);
      this.setLayoutParams(新LinearLayout.LayoutParams(
            LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
      行动=输入;
      LayoutInflater充气= LayoutInflater.from(的getContext());
      查看查看= inflater.inflate(R.layout.action_holder_layout,这一点,真正的);      TextView的actionTitle =(TextView的)查看
            .findViewById(com.tonimiko.mochi_bean.R.id.action_holder_title);
      actionTitle.setText(action.getActionName());
      actionTitle.setId(ActionHolder.ACTION_TITLE);      TextView的actionTimer =(TextView的)查看
            .findViewById(R.id.action_holder_timer);
      actionTimer.setId(ActionHolder.ACTION_TIMER);      按钮pauseBtn =(按钮)查看
            .findViewById(com.tonimiko.mochi_bean.R.id.pause_and_play_timer_btn);
      pauseBtn.setId(ActionHolder.PAUSEANDPLAY_BTN);      按钮finishBtn =(按钮)查看
            .findViewById(com.tonimiko.mochi_bean.R.id.finish_activity_button);
      finishBtn.setId(ActionHolder.FINISH_BTN);      action.setActivityStartTime();
   }   公益行动finishAction(){
      action.setActivityStopTime();
      返回行动;
   }   @覆盖
   保护无效onLayout(布尔变化,诠释L,INT T,INT R,INT B){
      super.onLayout(改,L,T,R,B);
   }   公共字符串的toString(){
      回归行动储存:+ action.getActionName();
   }   @覆盖
   公共布尔等于(对象除外){
      ActionHolder otherObj =(ActionHolder)等;
      如果(this.action.getActionName()。与toUpperCase()
            .equals(otherObj.action.getActionName()。与toUpperCase()))
         返回true;
      返回false;
   }   @覆盖
   公众诠释哈希code(){
      返回action.getActionName()哈希code()。
   }   @覆盖
   保护Parcelable的onSaveInstanceState(){
      Parcelable超级大国= super.onSaveInstanceState();
      捆绑数据=新包();
      data.putString(定时器,定时器);
      data.putSerializable(行动,行动);
      Log.e(调试,观叫的onSaveInstanceState!); // 去做
      Parcelable测试=新ActionHolderSavedState(超级大国,数据);
      如果(测试== NULL)
         Log.e(调试,空PARCELABLE); // 去做
      返回新ActionHolderSavedState(超级大国,数据);
   }   @覆盖
   保护无效onRestoreInstanceState(Parcelable状态){
      Log.e(调试,查看OnRestore中所谓的!);
      如果(州的instanceof ActionHolderSavedState){
         最后ActionHolderSavedState savedState =(ActionHolderSavedState)状态;
         this.action = savedState.getAction();
         this.timer = savedState.getTimer();
         // this.initiate(动作);
         super.onRestoreInstanceState(savedState.getSuperState());
         Log.e(调试,查看onRestoreInstanceState完成); // 去做
      }
   }   静态类ActionHolderSavedState扩展BaseSavedState {      私人诉讼storedAction;
      私人字符串storedTimer;      公共ActionHolderSavedState(Parcelable超级大国,捆绑数据){
         超(超状态);
         storedTimer = data.getString(计时器);
         storedAction =(动作)data.getSerializable(行动);
      }      私人ActionHolderSavedState(包裹中){
         超级(在);
         storedTimer = in.readString();
         storedAction = in.readParcelable(ActionHolder.class.getClassLoader());
      }      公益行动的getAction(){
         返回storedAction;
      }      公共字符串的getTimer(){
         返回storedTimer;
      }      @覆盖
      公共无效writeToParcel(最终包裹出来,最终诠释标志){
         super.writeToParcel(出,旗);
         out.writeString(storedTimer);
         out.writeSerializable(storedAction);
      }      //必填字段,使Parcelables并从包裹
      公共静态最终Parcelable.Creator< ActionHolderSavedState> CREATOR =新Parcelable.Creator< ActionHolderSavedState>(){         公共ActionHolderSavedState createFromParcel(以最终地块){
            返回新ActionHolderSavedState(中);
         }         公共ActionHolderSavedState [] newArray(INT大小){
            返回新ActionHolderSavedState【尺寸】;
         }
      };
   }
}

是不是我做错了什么?我已经花费近4天这一点。


解决方案

我有非常类似你的情况,与正在动态添加到屏幕和需要保存状态自定义视图时,该活动是由OS死亡,后来重建,例如。

我重写的onSaveInstanceState 在自定义视图。它需要返回一个 Parcelable 对象。关键是要创建一个扩展 BaseSavedState 和您的数据存储到该 Parcelable 自定义类。它看起来有点像这样的:


  @覆盖
保护Parcelable的onSaveInstanceState(){
    最终Parcelable状态= super.onSaveInstanceState();
    返回新ContainerLayoutSavedState(状态数据);
}@覆盖
保护无效onRestoreInstanceState(最终Parcelable州){
    如果(州的instanceof ContainerLayoutSavedState){
        最后ContainerLayoutSavedState savedState =(ContainerLayoutSavedState)状态;
        this.data = savedState.getData();
        super.onRestoreInstanceState(savedState.getSuperState());
    }
}公共静态类ContainerLayoutSavedState扩展BaseSavedState {
    私人字符串数据;    ContainerLayoutSavedState(最终Parcelable超级大国,最终字符串数据){
        超(超状态);
        //在这里,在此构造你注入任何你想要得到保存到Parcelable对象。在这种人为的例子,我们只是保存了一个名为数据串。
        this.data =数据;
    }
    私人ContainerLayoutSavedState(以最终地块){
        超级(在);        数据= in.readString();
    }    公共字符串的getData()
        返回的数据;
    }    @覆盖
    公共无效writeToParcel(最终包裹出来,最终诠释标志){
        super.writeToParcel(出,旗);        out.writeString(数据);
    }    //必填字段,使Parcelables并从包裹
    公共静态最终Parcelable.Creator< ContainerLayoutSavedState> CREATOR =新Parcelable.Creator< ContainerLayoutSavedState>(){
        @覆盖
        公共ContainerLayoutSavedState createFromParcel(以最终地块){
            返回新ContainerLayoutSavedState(中);
        }        @覆盖
        公共ContainerLayoutSavedState [] newArray(最终诠释大小){
            返回新ContainerLayoutSavedState【尺寸】;
        }
    };
}}


另外,不要忘记的ID设置为您的动态添加的意见,所以他们得到重新添加到视图树时,你回来了。

I have a layout in which I have dynamically added custom views at a push of a button. These layouts extend LinearLayout and each carry their own unique Action objects.

The views will disappear, however, if onCreate is called again, when the user navigates away or rotates the screen. I want to keep these custom ActionHolder views there. To add to the problem, the ActionHolder objects contain sensitive information. The Action objects themselves store a live timer(that is supposed to keep on ticking even if the app is off), as well as other information.

According to an answer below, I have done the following, but to no avail. Here is what I have so far:

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];
         }
      };
   }
}

Is there SOMETHING I am doing wrong? I've spend almost 4 days already on this.

解决方案

I have a situation very similar to yours, with custom views being added dynamically to the screen and that need to save state when the activity is killed by the OS and recreated later, for example.

I'm overriding onSaveInstanceState on the custom view. It needs to return a Parcelable object. The key is to create a custom class that extends BaseSavedState and stores your data into that Parcelable. It would look somewhat like this:

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

Also, don't forget to set IDs to your dynamically added views, so they get re-added to the View tree when you come back.

这篇关于保存动态添加LinearLayouts不使用savedInstanceState?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆