在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时不会设置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; }
请注意,此方法不依赖于模仿由FragmentPagerAdapter
设置的内部tag
,而是使用适当的API来检索它们。 这样,即使tag
在未来版本的SupportLibrary
发生变化,您仍然是安全的。
不要忘记 ,根据您的Activity
的devise,您尝试处理的Fragments
可能还可能不存在,因此您必须在使用引用之前通过执行null
检查来解决这个问题。
另外,如果你正在使用FragmentStatePagerAdapter
,那么你不想保留对你的Fragments
硬引用,因为你可能拥有很多引用,而且硬引用会不必要地将它们留在内存中。 而是将Fragment
引用保存在WeakReference
variables中而不是标准引用中。 喜欢这个:
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
完成了这个任务。 只需要发送一个广播,当你需要做一些可见的片段,并将其捕获在片段中。
如果您还需要某种回应,也可以通过广播发送。
干杯