onRestoreInstanceState后执行片段操作

onRestoreInstanceState后执行片段操作

问题描述:

我有一个执行一些网络操作的自定义视图。从该操作结果中,视图构建UI。onRestoreInstanceState后执行片段操作

该视图包含通过互联网获取的卡片列表。这个视图在多个地方使用。可以说,其中之一是我的片段。

这是我做的片段里面:

class MyFragment extends Fragment { 
    // same as findViewById 
    @BindView(R.id.card_list) CardHelper cardHelper; 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     // init my element with some data before it initializes 
     cardHelper.init(data); 
    } 
} 

这里是我的自定义视图的样子:

public class CardHelper extends ListView { 

    // some info that is built from internet data 
    private List<HashMap<String, String>> cardElements = new ArrayList<>(); 

    public void init(Data data) { 
     // does async network and then build a view based on results 
     // Network operations could depend on data param 
    } 
} 

OK,现在当用户切换从我的应用程序到另一个,我的部分可被销毁。我想拯救我的习俗的状态。因此我的观点不需要再从互联网上获取信息。所以我附上我的CardHelper数据如下(根据this答案):

public class CardHelper extends ListView { 
    // some info that is built from internet data 
    private List<HashMap<String, String>> cardElements = new ArrayList<>(); 

    public void init(Data data) { 
     // does async network and then build a view based on results 
    } 

    @Override 
    public Parcelable onSaveInstanceState() { 
     Parcelable superState = super.onSaveInstanceState(); 
     SavedState ss = new SavedState(superState); 
     ss.cardElements = this.cardElements; 
     return ss; 
    } 

    @Override 
    public void onRestoreInstanceState(Parcelable state) { 
     if(state instanceof SavedState) { 
      SavedState ss = (SavedState)state; 
      super.onRestoreInstanceState(ss.getSuperState()); 
      this.cardElements = ss.cardElements; 
     } else { 
      super.onRestoreInstanceState(state); 
     } 
    } 

    private static class SavedState extends BaseSavedState { 
     private List<HashMap<String, String>> cardElements = new ArrayList<>(); 

     SavedState(Parcelable superState) { 
      super(superState); 
     } 

     private SavedState(Parcel in) { 
      super(in); 
      this.cardElements = new ArrayList<>(); 
      in.readList(this.cardElements, null); 
     } 

     @Override 
     public void writeToParcel(Parcel out, int flags) { 
      super.writeToParcel(out, flags); 
      out.writeList(this.cardElements); 
     } 

     public static final Parcelable.Creator<SavedState> CREATOR = 
       new Parcelable.Creator<SavedState>() { 
        public SavedState createFromParcel(Parcel in) { 
         return new SavedState(in); 
        } 

        public SavedState[] newArray(int size) { 
         return new SavedState[size]; 
        } 
       }; 
    } 
} 

为了讨论的方便,我想从这个观点本身保存视图的数据。因此,片段/活动或使用它不需要知道它是如何工作的。如果我从多个地方使用它,我不需要复制存储\恢复此视图的代码。

确定,到现在的问题

当CardHelper创建非常第一次执行init与一些data手动初始化视图。当我的片段被破坏,应用程序切换到后台,然后得到恢复,方法是在以下优先执行:

  1. SavedState:私人SavedState(包裹中){
  2. SavedState:公共无效writeToParcel(包裹出来,诠释标志){
  3. CardHelper:公共无效的init(数据数据){
  4. CardHelper:公共无效onRestoreInstanceState(Parcelable状态){

正如你看到onRestoreInstanceState仅在onActivityCreated后执行。但在此之前,我需要知道我是否应该在init方法中执行网络操作。所以我想onRestoreInstanceState被执行第一个,然后只有init。但是在LifeCycle的片段中没有可以在此之后完成的方法。

如何重新格式化我的代码,我可以在onRestoreInstanceStateCardHelper被调用后调用我的片段中的某些操作?当CardHelper创建时,onRestoreInstanceState第一次不会被调用。但是我也需要在这种情况下初始化我的CardHelper。

简易修复应在发布cardHelper后发布init()步骤,因此onRestoreInstanceState已被调用。要做到这一点,你只需要在post(...)执行init()

cardHelper.post(new Runnable() { 
        public void run() { 
         cardHelper.init(); 
        } 
       }); 

没有测试过,我相信它会工作。

+0

是的,这个工程。那里可能有更优雅的解决方案。 – deathangel908

+0

你的代码中的问题是,'View'知道业务逻辑。通常情况下,这不应该发生。优雅的解决方案不是将数据保存在视图中,而是考虑更改架构。 – azizbekian

+0

你能否建议它应该怎么做?这个想法是封装逻辑来查看自己。因此,使用我的视图的人不需要担心任何刚刚过去'layout.xml'的视图。如果我将逻辑从我的视图移开,用户应该意识到他必须手动保存包。 – deathangel908