Ссылка на фрагменты внутри ViewPager
У меня проблема с ссылкой на мои фрагменты внутри ViewPager. Я хотел бы сделать это, потому что из своей активности я хотел бы обновить фрагмент в указанной позиции (например, в настоящее время отображаемый фрагмент).
В настоящее время у меня есть что-то вроде этого:
public static class MyPagerAdapter extends FragmentPagerAdapter {
private static final String TAG = "MyPagerAdapter";
private static HashMap<Integer, EventListFragment> mPageReferenceMap = new HashMap<Integer, EventListFragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return NUM_ITEMS;
}
@Override
public Fragment getItem(int position) {
Log.i(TAG, "getItem: "+position);
int dateOffset = position-1;
EventListFragment mFragment = EventListFragment.newInstance(dateOffset);
mPageReferenceMap.put(position, mFragment);
return mFragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Log.i(TAG, "destroyItem: "+position);
mPageReferenceMap.remove(position);
super.destroyItem(container, position, object);
}
public EventListFragment getFragment(int key) {
Log.i(TAG, "Size of pager references: "+mPageReferenceMap.size());
return mPageReferenceMap.get(key);
}
}
Проблема в том, что destroyItem()
получает вызов чаще, чем getItem()
, поэтому я остаюсь с нулевыми ссылками. Если я не использую destroyItem()
, чтобы очистить ссылки на уничтоженные фрагменты... ну, я ссылаюсь на фрагменты, которые не существуют.
Есть ли хороший способ ссылки на фрагменты, созданные с помощью EventListFragment mFragment = EventListFragment.newInstance(dateOffset);
? Или что мне делать, чтобы обновить фрагмент внутри ViewPager из моей активности (из меню опций, чтобы быть точным)?
Ответы
Ответ 1
Мне удалось это решить. Хитрость заключалась в том, чтобы сделать список ссылок внутри Activity, а не PagerAdapter. Это происходит следующим образом:
List<WeakReference<EventListFragment>> fragList = new ArrayList<WeakReference<EventListFragment>>();
@Override
public void onAttachFragment (Fragment fragment) {
Log.i(TAG, "onAttachFragment: "+fragment);
if(fragment.getClass()==EventListFragment.class){
fragList.add(new WeakReference<EventListFragment>((EventListFragment)fragment));
}
}
public EventListFragment getFragmentByPosition(int position) {
EventListFragment ret = null;
for(WeakReference<EventListFragment> ref : fragList) {
EventListFragment f = ref.get();
if(f != null) {
if(f.getPosition()==position){
ret = f;
}
} else { //delete from list
fragList.remove(f);
}
}
return ret;
}
Конечно, ваш фрагмент должен реализовать функцию getPosition()
, но мне все равно нужно что-то подобное, поэтому это не проблема.
Спасибо Alex Lockwood за ваше предложение с WeakReference
!
Ответ 2
Две вещи:
-
Добавьте следующую строку в свой метод Activity onCreate
(или где бы вы не инициализировали ViewPager):
mPager.setOffscreenPageLimit(NUM_ITEMS-1);
Это приведет к тому, что дополнительные дополнительные страницы в памяти (т.е. не будут уничтожены), даже если они не отображаются на экране.
-
Возможно, вы захотите реализовать свой HashMap
, чтобы он содержал WeakReference<Fragment>
вместо самих Fragment
. Обратите внимание, что для этого вам потребуется изменить свой метод getFragment
следующим образом:
WeakReference<Fragment> weakRef = mPageReferenceMap.get(position);
return (weakRef != null) ? weakRef.get() : null;
Это не имеет ничего общего с вашей проблемой... это просто что-то, что я заметил, и подумал, что приму вашему вниманию. Сохранение WeakReferences
вашего Fragment
позволит вам использовать способность сборщика мусора определять доступность для вас, поэтому вам не нужно делать это самостоятельно.