2017-02-18 14 views
0

У меня есть пользовательский вид, который выполняет некоторые сетевые операции. Из результата этой операции в представлении создается пользовательский интерфейс.Выполнять операцию из фрагмента после 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 
    } 
} 

ОК, теперь, когда пользователь переключается из моего приложения к другому, мой фрагмент мог быть уничтожен. И я хочу сохранить состояние своего пользовательского представления. Таким образом, мне не нужно снова получать информацию из Интернета. Поэтому я прилагаю мой 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]; 
        } 
       }; 
    } 
} 

Ради аргумента, я хочу сохранить данные зрения от самой этой точки зрения. Таким образом, фрагменты/действия или использование w/e не должны знать ничего, как это работает внутри. И если я использую его из нескольких мест, мне не нужно будет дублировать код, который сохраняет \ восстанавливает это представление.

Хорошо, к проблеме в настоящее время:

Когда CardHelper создан самый первый раз, когда я выполнить init, чтобы инициализировать представление вручную с некоторым data. Когда мой фрагмент разрушается и приложение переходит в фоновый режим, а затем получает восстановлены, методы выполняются в следующей очередности:

  1. SavedState: частный SavedState (участок в) {
  2. SavedState: общественная пустота writeToParcel (дробить, ИНТ флаги) {
  3. CardHelper: общественного недействительными инициализации (данные Data) {
  4. CardHelper: общественная пустота onRestoreInstanceState (Parcelable состояние) {

Как вы видите onRestoreInstanceState выполняется только после onActivityCreated. Но мне нужно знать, должен ли я выполнять сетевую операцию в методе init до этого. Поэтому я хочу выполнить onRestoreInstanceState и только тогда init. Но нет фрагментов LifeCycle, которые можно было бы сделать после этого.

Как переформатировать мой код, который я могу назвать некоторой операцией внутри моего фрагмента после того, как onRestoreInstanceState на CardHelper получил вызов? Еще одна вещь, что onRestoreInstanceState не будет вызываться в первый раз, когда создается CardHelper. Но в этом случае мне также нужно инициализировать CardHelper.

ответ

1

Легкое исправление должно быть опубликовано на этапе init() после того, как cardHelper был выложен, поэтому onRestoreInstanceState уже был вызван. Для этого вам просто нужно выполнить init() в post(...):

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

Не проверял, я предполагаю, что это будет работать.

+0

Да, это работает. Наверное, есть более элегантное решение. – deathangel908

+0

Проблема в вашем коде заключается в том, что 'View' знает о бизнес-логике. Обычно этого не должно быть. Элегантным решением было бы не сохранить данные в поле зрения, подумайте об изменении своей архитектуры. – azizbekian

+0

Не могли бы вы предложить, как это должно быть сделано? Идея заключалась в том, чтобы инкапсулировать логику, чтобы ее рассматривать. Поэтому людям, которые используют мой взгляд, не нужно будет беспокоиться ни о чем, кроме проспекта «layout.xml». Если я переведу логику в сторону от своего представления, пользователь должен знать, что он ДОЛЖЕН сохранить пакет вручную. – deathangel908

 Смежные вопросы

  • Нет связанных вопросов^_^