2017-02-18 42 views
0

我有一個執行一些網絡操作的自定義視圖。從該操作結果中,視圖構建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。

回答

1

簡易修復應在發佈cardHelper後發佈init()步驟,因此onRestoreInstanceState已被調用。要做到這一點,你只需要在post(...)執行init()

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

沒有測試過,我相信它會工作。

+0

是的,這個工程。那裏可能有更優雅的解決方案。 – deathangel908

+0

你的代碼中的問題是,'View'知道業務邏輯。通常情況下,這不應該發生。優雅的解決方案不是將數據保存在視圖中,而是考慮更改架構。 – azizbekian

+0

你能否建議它應該怎麼做?這個想法是封裝邏輯來查看自己。因此,使用我的視圖的人不需要擔心任何剛剛過去'layout.xml'的視圖。如果我將邏輯從我的視圖移開,用戶應該意識到他必須手動保存包。 – deathangel908