повторно использовать фрагменты в fragmentpageradapter
у меня есть viewpager, который просматривает фрагменты. Мой FragmentPagerAdapter подкласс создает новый фрагмент getItem метод, который кажется расточительным. Есть ли FragmentPagerAdapter эквивалентно convertView на listAdapter это позволит мне повторно использовать фрагменты, которые уже были созданы? Мой код приведен ниже.
public class ProfilePagerAdapter extends FragmentPagerAdapter {
ArrayList<Profile> mProfiles = new ArrayList<Profile>();
public ProfilePagerAdapter(FragmentManager fm) {
super(fm);
}
/**
* Adding a new profile object created a new page in the pager this adapter is set to.
* @param profile
*/
public void addProfile(Profile profile){
mProfiles.add(profile);
}
@Override
public int getCount() {
return mProfiles.size();
}
@Override
public Fragment getItem(int position) {
return new ProfileFragment(mProfiles.get(position));
}
}
5 ответов:
The
FragmentPagerAdapterуже кэшируетFragmentsдля вас. Каждому фрагменту присваивается тег, а затемFragmentPagerAdapterпытается вызватьfindFragmentByTag. Он только вызываетgetItemесли результатfindFragmentByTag- этоnull. Так что вам не придется кэшировать фрагменты самостоятельно.
приложение к сообщению Джеффа:
вы можете получить ссылку на свой
FragmentinFragmentPagerAdapterиспользуяfindFragmentByTag(). Имя тега генерируется следующим образом:private static String makeFragmentName(int viewId, int index) { return "android:switcher:" + viewId + ":" + index; }где viewId-это идентификатор ViewPager
посмотрите на эту ссылку: http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104
кажется, многие люди, просматривающие этот вопрос, ищут способ ссылаться на
FragmentsсозданоFragmentPagerAdapter/FragmentStatePagerAdapter. Я хотел бы предложить свое решение для этого, не полагаясь на внутри созданоtagsчто другие ответы на здесь использовать.в качестве бонуса этот метод также должен работать с
FragmentStatePagerAdapter. См. Примечания ниже для получения более подробной информации.
проблема с текущими решениями: полагаясь на внутренний код
A многие решения, которые я видел по этому и подобным вопросам, основаны на получении ссылки на существующий
Fragmentпо телефонуFragmentManager.findFragmentByTag()и передразнивать внутренне созданный тег:"android:switcher:" + viewId + ":" + id. Проблема в том, что вы полагаетесь на внутренний исходный код, который, как мы все знаем, не гарантированно останется неизменным навсегда. Инженеры Android в Google могут легко решить изменитьtagструктура, которая сломает ваш код, оставив вас неспособным найдите ссылку на существующийFragments.альтернативное решение, не полагаясь на внутренние
tagвот простой пример, как получить ссылку на элемент
FragmentsвозвращеноFragmentPagerAdapterэто не зависит от внутреннегоtagsустановить наFragments. Ключ должен переопределитьinstantiateItem()и сохранить ссылки там вместо внутриgetItem().public class SomeActivity extends Activity { private FragmentA m1stFragment; private FragmentB m2ndFragment; // other code in your Activity... private class CustomPagerAdapter extends FragmentPagerAdapter { // other code in your custom FragmentPagerAdapter... public CustomPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { // Do NOT try to save references to the Fragments in getItem(), // because getItem() is not always called. If the Fragment // was already created then it will be retrieved from the FragmentManger // and not here (i.e. getItem() won't be called again). switch (position) { case 0: return new FragmentA(); case 1: return new FragmentB(); default: // This should never happen. Always account for each position above return null; } } // Here we can finally safely save a reference to the created // Fragment, no matter where it came from (either getItem() or // FragmentManger). Simply save the returned Fragment from // super.instantiateItem() into an appropriate reference depending // on the ViewPager position. @Override public Object instantiateItem(ViewGroup container, int position) { Fragment createdFragment = (Fragment) super.instantiateItem(container, position); // save the appropriate reference depending on position switch (position) { case 0: m1stFragment = (FragmentA) createdFragment; break; case 1: m2ndFragment = (FragmentB) createdFragment; break; } return createdFragment; } } public void someMethod() { // do work on the referenced Fragments, but first check if they // even exist yet, otherwise you'll get an NPE. if (m1stFragment != null) { // m1stFragment.doWork(); } if (m2ndFragment != null) { // m2ndFragment.doSomeWorkToo(); } } }или если вы предпочитаете работы с
tagsвместо переменных-членов класса / ссылки наFragmentsвы также можете захватитьtagsset byFragmentPagerAdapterтаким же образом: Примечание: это не относится кFragmentStatePagerAdapterтак как он не поставилtagsпри созданииFragments.@Override public Object instantiateItem(ViewGroup container, int position) { Fragment createdFragment = (Fragment) super.instantiateItem(container, position); // get the tags set by FragmentPagerAdapter switch (position) { case 0: String firstTag = createdFragment.getTag(); break; case 1: String secondTag = createdFragment.getTag(); break; } // ... save the tags somewhere so you can reference them later return createdFragment; }обратите внимание, что этот метод не зависит от имитации внутреннего
tagset byFragmentPagerAdapterи вместо этого использует правильные API для их извлечения. Таким образом, даже еслиtagизменения в будущих версияхSupportLibraryвы все равно быть безопасным.
не забудьте, что в зависимости от дизайна вашего
ActivityнаFragmentsвы пытаетесь работать на может или не может существовать, так что вы должны учитывать, чтоnullпроверяет перед использованием ссылки.также, если вместо вы работаете с
FragmentStatePagerAdapter, то вы не хотите сохранять жесткие ссылки на вашFragmentsпотому что у вас может быть много из них, и жесткие ссылки будут излишне держать их в памяти. Вместо этого сохранитеFragmentссылокWeakReferenceпеременные вместо стандартных. Вот так:WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment); // ...and access them like so Fragment firstFragment = m1stFragment.get(); if (firstFragment != null) { // reference hasn't been cleared yet; do work... }
Если фрагмент остается в памяти, вы можете найти его с помощью этой функции.
public Fragment findFragmentByPosition(int position) { FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter(); return getSupportFragmentManager().findFragmentByTag( "android:switcher:" + getViewPager().getId() + ":" + fragmentPagerAdapter.getItemId(position)); }пример кода для api поддержки v4.
Я знаю, что это (теоретически) не ответ на вопрос, а другой подход.
У меня была проблема, когда мне нужно было обновить видимые фрагменты. Что бы я ни пытался, мне это не удавалось и не удавалось с треском...
после попытки так много разных вещей, я, наконец, закончить это с помощью
BroadCastReceiver. Просто отправьте трансляцию, когда вам нужно что-то сделать с видимыми фрагментами и захватить его во фрагменте.Если вам нужен какой-то ответ ну, вы также можете отправить его через эфир.
ура