2017-02-18 6 views
0

ネットワーク操作を実行するカスタムビューがあります。その操作結果から、ビューはUIを構築します。onRestoreInstanceStateの後にフラグメントから操作を実行します。

ビューには、インターネット経由で取得されたカードのリストが含まれています。このビューは複数の場所で使用されます。彼らのうちの1つが私の断片だと言いましょう。ここで

は、私がフラグメントの内部で何をすべきかです:私のフラグメントができた、別のものに

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、私のアプリから、今のユーザスイッチ:

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

は、ここに私のカスタムビューは、などをどのように見えるかです破壊される。そして私は私のカスタムビューの状態を保存したい。したがって、私の見解はインターネットから情報を再度得る必要はありません。だから私は(this回答に基づいて)次のデータと私のCardHelperを追加します。

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

引数のために、私はこのビュー自体からのビューのデータを保存したいです。したがって、フラグメント/アクティビティや、それがどのように内部で動作するかを知る必要はありません。複数の場所から使用すると、このビューを保存するコードを複製する必要はありません。

[OK]を、今問題へ:CardHelperは、私はいくつかのdataで手動ビューを初期化するためにinitを行う非常に最初の時間に作成され

。私のフラグメントは破棄されますと、アプリがバックグラウンドに行き、その後、復元されます場合は、この方法は、次の優先順位で実行されています

  1. SavedState:プライベートSavedState(小包で){
  2. SavedStateます。public void writeToParcel(小包うち、公共ボイドのinit(データDATA){
  3. CardHelper:ます。public void onRestoreInstanceState(Parcelable状態){

は見ての通り){

  • CardHelperフラグをint型0は、onActivityCreatedの後にのみ実行されます。しかし、その前にinitメソッドでネットワーク操作を実行する必要があるかどうかを知る必要があります。だから私はonRestoreInstanceStateが最初に実行され、その後はinitになりたい。しかし、この後にできるフラグメントLifeCycleにはメソッドがありません。

    onRestoreInstanceStateCardHelperの後にフラグメント内で何らかの操作を呼び出すことができるコードを再フォーマットする方法はありますか? CardHelperが作成されたときに初めてonRestoreInstanceStateが呼び出されないということがもう1つあります。しかし、この場合でも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

    関連する問題