在fragmentpageradapter中重用片段

我有一个浏览器,通过片段。 我的FragmentPagerAdapter子类在getItem方法中创build一个新的片段,这看起来很浪费。 是否有一个FragmentPagerAdapter相当于listAdapter中的convertView ,使我能够重用已经创build的片段? 我的代码如下。

 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)); } } 

FragmentPagerAdapter已经为你cachingFragments 。 每个片段分配一个标签,然后FragmentPagerAdapter尝试调用findFragmentByTag 。 如果findFragmentByTag的结果为null ,它只调用getItem 。 所以你不应该自己caching片段。

Geoff的post附录:

您可以使用findFragmentByTag()FragmentPagerAdapter获取对Fragment引用。 标签的名称是这样生成的:

 private static String makeFragmentName(int viewId, int index) { return "android:switcher:" + viewId + ":" + index; } 

其中viewId是ViewPager的ID

看看这个链接: http : //code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104

似乎很多查看此问题的人正在寻找一种方法来引用由FragmentPagerAdapter / FragmentStatePagerAdapter创build的FragmentStatePagerAdapter 。 我想提供我的解决scheme,而不依赖于其他答案在这里使用内部创build的tags

作为奖励,这个方法也应该与FragmentStatePagerAdapter工作。 更多细节见下面的注释。


目前的解决scheme的问题:依靠内部代码

我在这个和类似的问题上看到的很多解决scheme都是通过调用FragmentManager.findFragmentByTag()和模仿内部创build的标签来获得对现有Fragment的引用"android:switcher:" + viewId + ":" + id 。 与此相关的问题是您依赖内部源代码,因为我们都知道这是不能保证永远保持不变的。 Google的Android工程师可以轻松地决定更改tag结构,这会破坏您的代码,从而无法find对现有Fragments的引用。

不依赖于内部tag替代解决scheme

下面是一个简单的例子,介绍如何获得对Fragments返回的FragmentPagerAdapter的引用,而不依赖FragmentPagerAdapter上设置的内部tags 。 关键是覆盖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 (ie 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而不是类成员variables/对Fragments引用,那么您也可以按照相同的方式获取由FragmentPagerAdapter设置的tags :注意:这不适用于FragmentStatePagerAdapter因为它在创build时不会设置tagsFragments

 @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; } 

请注意,此方法不依赖于模仿由FragmentPagerAdapter设置的内部tag ,而是使用适当的API来检索它们。 这样,即使tag在未来版本的SupportLibrary发生变化,您仍然是安全的。


不要忘记 ,根据您的Activity的devise,您尝试处理的Fragments可能还可能不存在,因此您必须在使用引用之前通过执行null检查来解决这个问题。

另外,如果你正在使用FragmentStatePagerAdapter ,那么你不想保留对你的Fragments硬引用,因为你可能拥有很多引用,而且硬引用会不必要地将它们留在内存中。 而是将Fragment引用保存在WeakReferencevariables中而不是标准引用中。 喜欢这个:

 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... } 

如果片段仍然在内存中,您可以使用此functionfind它。

 public Fragment findFragmentByPosition(int position) { FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter(); return getSupportFragmentManager().findFragmentByTag( "android:switcher:" + getViewPager().getId() + ":" + fragmentPagerAdapter.getItemId(position)); } 

v4支持api的示例代码。

我知道这(理论上)不是对这个问题的回答,而是一个不同的方法。

我有一个问题,我需要刷新可见的碎片。 无论我尝试了什么,都失败了,失败了…

尝试了很多不同的东西之后,我终于用BroadCastReceiver完成了这个任务。 只需要发送一个广播,当你需要做一些可见的片段,并将其捕获在片段中。

如果您还需要某种回应,也可以通过广播发送。

干杯