2013-11-17 2 views
0

Моя проблема в том, что у меня есть ViewPager, который отображает 4 фрагмента (скажем: A, B, C, D). Но иногда, когда пользователь нажимает на что-то, мне нужно заменить, например, A другим фрагментом (скажем, E). Я сделал это, переопределив getItemPosition и создав собственный метод setCurrentItem в моем ViewPager. Вот мои классы:Android ViewPager заменит текущий фрагмент, но при отклонении первоначального значения не перезагружается

MyFragmentStatePagerAdapter:

public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter { 

    private Map<Integer, Fragment> overrides; 

    public void setOverride(int position, Fragment fragment) { 
     overrides.put(position, fragment); 
    } 

    ... 

    @Override 
    public final Fragment getItem(final int position) { 
     Fragment fragment = overrides.remove(position); 
     if (fragment != null) { 
      return fragment; 
     } else { 
      ... // return corresponding base Fragment (A, B, C, D) 
     } 
    } 

    @Override 
    // this is overrideden to ensure 
    public final int getItemPosition(final Object object) { 
     return PagerAdapter.POSITION_NONE; 
    } 

} 

И мой MyViewPager:

public class MyViewPager extends ViewPager { 

    ... 

    public MyAdapter adapter() { 
     return (MyAdapter) this.getAdapter(); 
    } 

    public void setCurrentItem(final int item, final Fragment fragment) { 
     if (this.getAdapter() == null) { 
      return; 
     } 

     this.adapter().setOverride(item, fragment); 

     if (item == this.getCurrentItem()) { 
      this.getAdapter().notifyDataSetChanged(); 
     } else { 
      this.setCurrentItem(item); 
     } 
    } 

} 

Так что это работает безупречно, но когда я красть назад от фрагмента и красть назад я хочу снова увидеть отображение, но я все еще вижу E.

Кто-нибудь получил решение этой проблемы?

Спасибо.

+0

Стик точку останова на GetItem и посмотреть, если он попадает снова. Если вы отбросьте первый фрагмент и вернетесь к нему, вы увидите, что getItem вызывается для третьего элемента, где он предварительно загружает содержимое вне экрана. См. Здесь для получения более подробной информации - http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit%28int%29 –

+0

Попробуйте вызвать 'notifyDataSetChanged()' каждый раз на вашем 'setCurrentItem' , –

+0

Переопределение setCurrentItem и вызов notifyDataSetChanged перед запуском super.setCurrentItem, но это действительно замедляет работу. Возможно, существует способ аннулировать только фрагмент, который получил переопределение. – ffddani

ответ

0

Прохладный, мне удалось заставить его работать без потери производительности. В основном я вызываю notifyDataSetChanged в переопределенном setCurrentItem, но только если текущий фрагмент не является базовым фрагментом. Если кому интересно вот мои классы:

MyPageAdapter:

public abstract class MyPageAdapter extends FragmentStatePagerAdapter { 

    private final Context context; 

    private final Map<Integer, Fragment> fragmentOverrides; 

    private final Map<Integer, Fragment> fragmentReferences; 

    private final Map<Integer, Class<? extends Fragment>> fragments; 

    public MyPageAdapter(final Context context, final FragmentManager fragmentManager, final Map<Integer, Class<? extends Fragment>> fragments) { 
     super(fragmentManager); 
     this.context = context; 
     this.fragmentOverrides = new HashMap<Integer, Fragment>(); 
     this.fragmentReferences = new HashMap<Integer, Fragment>(); 
     this.fragments = new HashMap<Integer, Class<? extends Fragment>>(fragments); 
    } 

    private Fragment getItemAt(final int position) { 
     final Fragment overrideFragment = this.fragmentOverrides.remove(position); 

     if (overrideFragment != null) { 
      return overrideFragment; 
     } 

     return Fragment.instantiate(this.context, this.fragments.get(position).getName()); 
    } 

    @Override 
    public final Fragment getItem(final int position) { 
     final Fragment fragment = this.getItemAt(position); 
     this.fragmentReferences.put(position, fragment); 
     return fragment; 
    } 

    public final Class<? extends Fragment> getInitialFragmentClass(final int position) { 
     return this.fragments.get(position); 
    } 

    @Override 
    public final int getItemPosition(final Object object) { 
     return PagerAdapter.POSITION_NONE; 
    } 

    public final Fragment getFragment(final int position) { 
     return this.fragmentReferences.get(position); 
    } 

    public final boolean isInitialFragment(final Class<? extends Fragment> fragmentClass) { 
     return this.fragments.values().contains(fragmentClass); 
    } 

    public final void setOverride(final int position, final Fragment fragment) { 
     this.fragmentOverrides.put(position, fragment); 
    } 

    @Override 
    public final void destroyItem(final ViewGroup container, final int position, final Object object) { 
     this.fragmentReferences.remove(position); 
     super.destroyItem(container, position, object); 
    } 

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

} 

И MyViewPager:

public class MyViewPager extends ViewPager { 

    public MyViewPager(final Context context) { 
     super(context); 
    } 

    public MyViewPager(final Context context, final AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public final MyPageAdapter adapter() { 
     if (this.getAdapter() == null) { 
      return null; 
     } 

     if (!(this.getAdapter() instanceof MyPageAdapter)) { 
      throw new IllegalStateException("Invalid adapter! The adapter must extend MyPageAdapter!"); 
     } 

     return ((MyPageAdapter) this.getAdapter()); 
    } 

    public final Fragment getCurrentFragment() { 
     if (this.getAdapter() == null || this.getCurrentItem() < 0) { 
      return null; 
     } 

     return this.adapter().getFragment(this.getCurrentItem()); 
    } 

    public final void reselectCurrentItem() { 
     if (this.getAdapter() != null) { 
      this.getAdapter().notifyDataSetChanged(); 
     } 
    } 

    private void forceRefreshIfNeeded() { 
     if (this.getAdapter() != null && 0 <= this.getCurrentItem() && this.getCurrentItem() < this.getAdapter().getCount()) { 
      final Fragment currentFragment = this.adapter().getFragment(this.getCurrentItem()); 

      if (currentFragment != null && !currentFragment.getClass().equals(this.adapter().getInitialFragmentClass(this.getCurrentItem()))) { 
       this.getAdapter().notifyDataSetChanged(); 
      } 
     } 
    } 

    @Override 
    public void setCurrentItem(final int item) { 
     this.forceRefreshIfNeeded(); 
     super.setCurrentItem(item); 
    } 

    @Override 
    public void setCurrentItem(final int item, final boolean smoothScroll) { 
     this.forceRefreshIfNeeded(); 
     super.setCurrentItem(item, smoothScroll); 
    } 

    public void setCurrentItem(final int item, final Fragment fragment) { 
     if (this.getAdapter() == null) { 
      return; 
     } 

     if (!this.adapter().isInitialFragment(fragment.getClass())) { 
      this.adapter().setOverride(item, fragment); 
     } 

     if (item == this.getCurrentItem()) { 
      this.getAdapter().notifyDataSetChanged(); 
     } else { 
      this.setCurrentItem(item); 
     } 
    } 

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