2013-07-17 2 views
1

У меня странная проблема с просмотром фрагментов, не освежающим должным образом, но это происходит только после закрытия приложения и повторного открытия после некоторого количества время.Фрагменты Android, хранящиеся в виде массива в FragmentPagerAdapter, не обновлены после выхода и возвращения в приложение

У меня есть TabSwitcherActivity который содержит ViewPager. ViewPager переключает между 3 фрагментами, и каждый фрагмент представляет собой другой вид той же информации. Существуют определенные события, которые могут произойти, что приведет к устареванию информации, поэтому фрагменты должны быть уведомлены для обновления представления. Для этого у моего TabSwitcherActivity есть метод notifyDataSetChanged(), который будет перебирать 3 фрагмента и сообщать им об обновлении. Вот (я думаю) наиболее подходящий код:

public class TabSwitcherActivity extends FragmentActivity { 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Used to keep track of the child fragments of this activity so we can update their list adapters. 
     mFragments = new ArrayList<Fragment>(); 

     // Set up the view pager and tab adapter. 
     setContentView(R.layout.pager_layout); 
     mViewPager = (ViewPager) super.findViewById(R.id.pager); 

     mFragments.add(Fragment.instantiate(this, FragmentOne.class.getName())); 
     mFragments.add(Fragment.instantiate(this, FragmentTwo.class.getName())); 
     mFragments.add(Fragment.instantiate(this, FragmentThree.class.getName())); 
     mViewPager.setAdapter(new ListPagerAdapter(super.getSupportFragmentManager(), mFragments)); 
    } 

    public void notifyDataSetChanged() { 
     for (Fragment fragment : mFragments) { 
     if (fragment instanceof IDataSetChangedListener) { 
      ((IDataSetChangedListener) fragment).notifyDataSetChanged(); 
     } 
     } 
    } 
} 

Теперь это работает по назначению при первом запуске приложения. Проблема в том, что после закрытия приложения и повторного открытия через некоторое время вызов TabSwitcherActivity.notifyDataSetChanged() во время работы приложения не обновляет представления фрагментов (это работает при первом запуске приложения после перезагрузки). Это заставляет меня думать, что существует ситуация жизненного цикла с фрагментами, которые я неправильно обрабатываю. Любая идея, что это может быть? Мне приходит в голову, что если фрагменты уничтожаются и воссоздаются, они, вероятно, неправильно хранятся в моем массиве mFragments.

ответ

3

Я отвечаю на свой вопрос в случае, если другие имеют подобную проблему к тому, что я имел. Я смог решить проблему на основе комментариев от инвертирования. Я опубликую некоторые обобщенные части важных частей кода.

Как я подозревал, фрагменты, хранящиеся в массиве, были неправильно обновлены, если они были уничтожены и повторно созданы приложением. (Иногда это случалось, когда приложение было закрыто и повторно открывалось.) Было немного сложно удалить массив, так как я использовал его для хранения фрагментов для своих вкладок в моей реализации FragmentPagerAdapter.

Вот мой старый ListPagerAdapter класс:

public class ListPagerAdapter extends FragmentPagerAdapter { 
    private List<Fragment> mFragments; 

    public ListPagerAdapter(FragmentManager fm, List<Fragment> fragments) { 
     super(fm); 
     mFragments = fragments; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return mFragments.get(position); 
    } 

    @Override 
    public int getCount() { 
     return mFragments.size(); 
    } 

    @Override 
    public String getPageTitle(int position) { 
     return ((ITitledFragment) mFragments.get(position)).getTitle(); 
    } 
} 

Вот моя новая реализация, которая устраняет проблему, связанную с массивом держит плохие ссылки фрагмент:

public class ListPagerAdapter extends FragmentPagerAdapter {  
    private static final int FRAGMENT_ONE_POSITION = 0; 
    private static final int FRAGMENT_TWO_POSITION = 1; 
    private static final int FRAGMENT_THREE_POSITION = 2; 
    private static final int COUNT = 3; 

    public ListPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     switch (position) { 
     case FRAGMENT_ONE_POSITION: 
      return new FragmentOne(); 
     case FRAGMENT_TWO_POSITION: 
      return new FragmentTwo(); 
     case FRAGMENT_THREE_POSITION: 
      return new FragmentThree(); 
     } 
     return null; 
    } 

    @Override 
    public int getCount() { 
     return COUNT; 
    } 

    @Override 
    public String getPageTitle(int position) { 
     switch (position) { 
     case 0: 
      return FragmentOne.getTitle(); 
     case 1: 
      return FragmentTwo.getTitle(); 
     case 2: 
      return FragmentThree.getTitle(); 
     } 
     return null; 
    } 
} 

Затем Остающаяся проблема как мой класс TabSwitcherActivity обновляет все фрагменты, когда они устарели. Как указывал Инвертиго, это можно сделать с помощью тегов. Тем не менее, я решил использовать подход, в котором каждый фрагмент регистрируется с активностью, когда он создается, и отбрасывает себя до того, как он будет уничтожен. Эта активность может перебирать зарегистрированные фрагменты для их обновления.

Соответствующий код из TabSwitcherActivity:

class TabSwitcherActivity extends FragmentActivity { 
    private List<Fragment> mFragments; 

    private void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Used to keep track of the child fragments of this activity so we can update their list adapters. 
     mFragments = new ArrayList<Fragment>(); 

     // Set up the view pager and tab adapter. 
     setContentView(R.layout.pager_layout); 
     mViewPager = (ViewPager) super.findViewById(R.id.pager); 

     mViewPager.setAdapter(new ListPagerAdapter(super.getSupportFragmentManager())); 
    } 

    public void startTrackingFragment(Fragment f) { 
     mFragments.add(f); 
    } 

    public void stopTrackingFragment(Fragment f) { 
     mFragments.remove(f); 
    } 

    public void notifyDataSetChanged() { 
     for (Fragment fragment : mFragments) { 
      if (fragment instanceof IDataSetChangedListener) { 
       ((IDataSetChangedListener) fragment).notifyDataSetChanged(); 
      } 
     } 
    } 
} 

При том, что все, что остается, чтобы фрагменты регистрируются обновления:

public class FragmentOne extends Fragment implements IDataSetChangedListener { 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     ((TabSwitcherActivity) getActivity()).startTrackingFragment(this); 
    } 

    public void onDestroy() { 
     ((TabSwitcherActivity) getActivity()).stopTrackingFragment(this); 
     super.onDestroy(); 
    } 
} 
1

Вы всегда можете просто обновить данные в onResume() ваших фрагментов или вызвать notifyDataSetChanged() в onResume() вашей активности.

re: «Мне кажется, что если фрагменты уничтожены и воссозданы, они, вероятно, неправильно хранятся в моем массиве mFragments». Вместо того, чтобы хранить фрагменты в массиве, используйте диспетчер фрагментов для извлечения фрагментов по тегу или идентификатору.

http://developer.android.com/guide/components/fragments.html#Managing

http://developer.android.com/reference/android/app/FragmentManager.html#findFragmentByTag(java.lang.String)

+0

Я должен был быть более ясным - мнения, возможно, потребуется для обновления, пока приложение используется. Иногда вызывается 'notifyDataSetChanged()', пока приложение активно. Полезный совет менеджера фрагментов - я рассмотрю это. – mkasberg

+0

Мое предложение состоит в том, чтобы обновить данные в onResume() ваших фрагментов * в дополнение к * любым обновлениям вручную, которые вы хотите выполнить через notifyDataSetChanged() – invertigo

+0

Ahh - извините за путаницу, я не должен был хорошо описывать проблему в моем первом после. Проблема заключается не в том, что представления устарели, когда приложение запускается во второй раз. Скорее, после того, как приложение запускается во второй раз, вызов 'TabSwitcherActivity.notifyDataSetChanged()' во время работы приложения не приводит к обновлению представлений фрагментов. Я отредактирую свое оригинальное сообщение, чтобы быть более ясным. – mkasberg

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