ViewPager和片段-什么是存储片段状态的正确方式?

片段似乎非常适合将UI逻辑分离到一些模块中。但是和ViewPager一样,它的生命周期对我来说仍然很模糊。所以我们非常需要大师的思想!

编辑

参见下面的哑巴解决方案;-)

范围

Main活动有一个带有片段的ViewPager。这些片段可以为其他(子主)活动实现稍微不同的逻辑,因此片段的数据是通过活动内部的回调接口填充的。第一次发射时一切正常,但是……

问题

当活动被重新创建时(例如在方向改变时),ViewPager的片段也会被重新创建。代码(你会在下面发现)说,每次创建活动,我尝试创建一个新的ViewPager片段适配器相同的片段(也许这是问题),但FragmentManager已经有所有这些片段存储在某个地方(哪里?),并开始为那些重建机制。因此,重建机制调用“旧”片段的onAttach, onCreateView等与我的回调接口调用,通过活动的实现方法来初始化数据。但是这个方法指向通过Activity的onCreate方法创建的新创建的片段。

问题

也许我使用了错误的模式,但即使是Android 3 Pro书也没有太多关于它的内容。所以,,给我一拳两拳,并指出如何做正确的方式。很多谢谢!

代码

主要活动

public class DashboardActivity extends BasePagerActivity implements OnMessageListActionListener {


private MessagesFragment mMessagesFragment;


@Override
protected void onCreate(Bundle savedInstanceState) {
Logger.d("Dash onCreate");
super.onCreate(savedInstanceState);


setContentView(R.layout.viewpager_container);
new DefaultToolbar(this);


// create fragments to use
mMessagesFragment = new MessagesFragment();
mStreamsFragment = new StreamsFragment();


// set titles and fragments for view pager
Map<String, Fragment> screens = new LinkedHashMap<String, Fragment>();
screens.put(getApplicationContext().getString(R.string.dashboard_title_dumb), new DumbFragment());
screens.put(getApplicationContext().getString(R.string.dashboard_title_messages), mMessagesFragment);


// instantiate view pager via adapter
mPager = (ViewPager) findViewById(R.id.viewpager_pager);
mPagerAdapter = new BasePagerAdapter(screens, getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);


// set title indicator
TitlePageIndicator indicator = (TitlePageIndicator) findViewById(R.id.viewpager_titles);
indicator.setViewPager(mPager, 1);


}


/* set of fragments callback interface implementations */


@Override
public void onMessageInitialisation() {


Logger.d("Dash onMessageInitialisation");
if (mMessagesFragment != null)
mMessagesFragment.loadLastMessages();
}


@Override
public void onMessageSelected(Message selectedMessage) {


Intent intent = new Intent(this, StreamActivity.class);
intent.putExtra(Message.class.getName(), selectedMessage);
startActivity(intent);
}

BasePagerActivity又名助手

public class BasePagerActivity extends FragmentActivity {


BasePagerAdapter mPagerAdapter;
ViewPager mPager;
}

适配器

public class BasePagerAdapter extends FragmentPagerAdapter implements TitleProvider {


private Map<String, Fragment> mScreens;


public BasePagerAdapter(Map<String, Fragment> screenMap, FragmentManager fm) {


super(fm);
this.mScreens = screenMap;
}


@Override
public Fragment getItem(int position) {


return mScreens.values().toArray(new Fragment[mScreens.size()])[position];
}


@Override
public int getCount() {


return mScreens.size();
}


@Override
public String getTitle(int position) {


return mScreens.keySet().toArray(new String[mScreens.size()])[position];
}


// hack. we don't want to destroy our fragments and re-initiate them after
@Override
public void destroyItem(View container, int position, Object object) {


// TODO Auto-generated method stub
}


}

片段

public class MessagesFragment extends ListFragment {


private boolean mIsLastMessages;


private List<Message> mMessagesList;
private MessageArrayAdapter mAdapter;


private LoadMessagesTask mLoadMessagesTask;
private OnMessageListActionListener mListener;


// define callback interface
public interface OnMessageListActionListener {
public void onMessageInitialisation();
public void onMessageSelected(Message selectedMessage);
}


@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// setting callback
mListener = (OnMessageListActionListener) activity;
mIsLastMessages = activity instanceof DashboardActivity;


}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
inflater.inflate(R.layout.fragment_listview, container);
mProgressView = inflater.inflate(R.layout.listrow_progress, null);
mEmptyView = inflater.inflate(R.layout.fragment_nodata, null);
return super.onCreateView(inflater, container, savedInstanceState);
}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);


// instantiate loading task
mLoadMessagesTask = new LoadMessagesTask();


// instantiate list of messages
mMessagesList = new ArrayList<Message>();
mAdapter = new MessageArrayAdapter(getActivity(), mMessagesList);
setListAdapter(mAdapter);
}


@Override
public void onResume() {
mListener.onMessageInitialisation();
super.onResume();
}


public void onListItemClick(ListView l, View v, int position, long id) {
Message selectedMessage = (Message) getListAdapter().getItem(position);
mListener.onMessageSelected(selectedMessage);
super.onListItemClick(l, v, position, id);
}


/* public methods to load messages from host acitivity, etc... */
}

解决方案

愚蠢的解决方案是将碎片保存在onSaveInstanceState(主机活动)与putFragment和获得他们在onCreate通过getFragment。但我仍然有一种奇怪的感觉,事情不应该这样发展……参见下面的代码:

    @Override
protected void onSaveInstanceState(Bundle outState) {


super.onSaveInstanceState(outState);
getSupportFragmentManager()
.putFragment(outState, MessagesFragment.class.getName(), mMessagesFragment);
}


protected void onCreate(Bundle savedInstanceState) {
Logger.d("Dash onCreate");
super.onCreate(savedInstanceState);


...
// create fragments to use
if (savedInstanceState != null) {
mMessagesFragment = (MessagesFragment) getSupportFragmentManager().getFragment(
savedInstanceState, MessagesFragment.class.getName());
StreamsFragment.class.getName());
}
if (mMessagesFragment == null)
mMessagesFragment = new MessagesFragment();
...
}
235085 次浏览

BasePagerAdapter是什么?你应该使用一个标准的寻呼机适配器——FragmentPagerAdapterFragmentStatePagerAdapter,这取决于你是否想要ViewPager不再需要的Fragments被保留(前者)或保存它们的状态(后者),并在再次需要时重新创建。

使用ViewPager的示例代码可以在在这里中找到

的确,跨活动实例管理视图寻呼机中的片段有点复杂,因为框架中的FragmentManager负责保存状态并恢复寻呼机所创建的任何活动片段。这实际上意味着,适配器在初始化时需要确保它与任何恢复的片段重新连接。你可以看看FragmentPagerAdapterFragmentStatePagerAdapter的代码,看看这是如何做到的。

FragmentPagerAdapter将一个片段添加到FragmentManager时,它使用一个基于片段将被放置的特定位置的特殊标记。FragmentPagerAdapter.getItem(int position)只在该位置的片段不存在时调用。在旋转之后,Android会注意到它已经为这个特定的位置创建/保存了一个片段,所以它只是尝试用FragmentManager.findFragmentByTag()重新连接它,而不是创建一个新的片段。当使用FragmentPagerAdapter时,所有这些都是免费的,这就是为什么通常在getItem(int)方法中有你的片段初始化代码。

即使我们没有使用FragmentPagerAdapter,每次在Activity.onCreate(Bundle)中创建一个新的片段也不是一个好主意。正如你所注意到的,当一个片段被添加到FragmentManager时,它将在旋转后为你重新创建,不需要再次添加它。这样做是处理片段时出现错误的常见原因。

在处理片段时,通常的方法是:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


...


CustomFragment fragment;
if (savedInstanceState != null) {
fragment = (CustomFragment) getSupportFragmentManager().findFragmentByTag("customtag");
} else {
fragment = new CustomFragment();
getSupportFragmentManager().beginTransaction().add(R.id.container, fragment, "customtag").commit();
}


...


}

当使用FragmentPagerAdapter时,我们将片段管理交给适配器,并且不必执行上述步骤。默认情况下,它只会在当前位置的前面和后面预加载一个Fragment(尽管它不会销毁它们,除非你使用FragmentStatePagerAdapter)。它由ViewPager.setOffscreenPageLimit (int)控制。因此,不能保证直接调用适配器外部片段上的方法是有效的,因为它们甚至可能不是活动的。

长话短说,你的解决方案使用putFragment能够获得一个引用之后不是那么疯狂,并没有太不像正常的方式使用片段无论如何(上面)。否则很难获得引用,因为片段是由适配器添加的,而不是您个人添加的。只要确保offscreenPageLimit足够高以在任何时候加载你想要的片段,因为你依赖于它的存在。这绕过了ViewPager的惰性加载功能,但似乎是你想要的应用程序。

另一种方法是覆盖FragmentPageAdapter.instantiateItem(View, int),并在返回super调用返回的片段之前保存对它的引用(如果已经存在,则具有查找片段的逻辑)。

要了解更全面的情况,请查看FragmentPagerAdapter(短)和: viewpage(长)的一些源代码。

我想为一个可能略有不同的情况提供一个替代解决方案,因为我对答案的许多搜索一直将我引向这个主题。

< >强劲我的情况 -我动态创建/添加页面,并将它们滑动到ViewPager,但当旋转(onConfigurationChange),我最终会有一个新页面,因为当然OnCreate再次被调用。但是我想保持对旋转之前创建的所有页面的引用

< >强问题 -我没有为我创建的每个片段提供唯一的标识符,所以引用的唯一方法是以某种方式将引用存储在一个数组中,以便在旋转/配置更改后恢复

<强>解决方案 -关键的概念是让Activity(显示片段)也管理现有片段的引用数组,因为这个Activity可以利用onSaveInstanceState

中的Bundles
public class MainActivity extends FragmentActivity

因此,在这个Activity中,我声明了一个私有成员来跟踪打开的页面

private List<Fragment> retainedPages = new ArrayList<Fragment>();

每次onSaveInstanceState被调用时都会更新,并在onCreate中恢复

@Override
protected void onSaveInstanceState(Bundle outState) {
retainedPages = _adapter.exportList();
outState.putSerializable("retainedPages", (Serializable) retainedPages);
super.onSaveInstanceState(outState);
}

...所以一旦它被存储,它就可以被检索…

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


if (savedInstanceState != null) {
retainedPages = (List<Fragment>) savedInstanceState.getSerializable("retainedPages");
}
_mViewPager = (CustomViewPager) findViewById(R.id.viewPager);
_adapter = new ViewPagerAdapter(getApplicationContext(), getSupportFragmentManager());
if (retainedPages.size() > 0) {
_adapter.importList(retainedPages);
}
_mViewPager.setAdapter(_adapter);
_mViewPager.setCurrentItem(_adapter.getCount()-1);
}

这些是对主活动的必要更改,因此我需要FragmentPagerAdapter中的成员和方法来工作,因此在

public class ViewPagerAdapter extends FragmentPagerAdapter

一个相同的构造(如上面的MainActivity中所示)

private List<Fragment> _pages = new ArrayList<Fragment>();

这种同步(如上面在onSaveInstanceState中使用的那样)是由方法特别支持的

public List<Fragment> exportList() {
return _pages;
}


public void importList(List<Fragment> savedPages) {
_pages = savedPages;
}

最后,在fragment类中

public class CustomFragment extends Fragment

为了使这一切顺利进行,有两个改变,首先

public class CustomFragment extends Fragment implements Serializable

然后将其添加到onCreate,这样Fragments就不会被破坏

setRetainInstance(true);

我仍然在思考Fragments和Android生命周期,所以这里需要注意的是,这种方法可能存在冗余/低效率。但它对我有用,我希望它能对其他有类似情况的人有所帮助。

对于你的问题,我找到了另一个相对简单的解决方法。

正如你可以从FragmentPagerAdapter源代码中看到的,由FragmentPagerAdapter管理的片段存储在FragmentManager中,在使用以下方法生成的标记下:

String tag="android:switcher:" + viewId + ":" + index;

viewIdcontainer.getId()container是你的ViewPager实例。index是片段的位置。因此,你可以将对象id保存到outState:

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("viewpagerid" , mViewPager.getId() );
}


@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
if (savedInstanceState != null)
viewpagerid=savedInstanceState.getInt("viewpagerid", -1 );


MyFragmentPagerAdapter titleAdapter = new MyFragmentPagerAdapter (getSupportFragmentManager() , this);
mViewPager = (ViewPager) findViewById(R.id.pager);
if (viewpagerid != -1 ){
mViewPager.setId(viewpagerid);
}else{
viewpagerid=mViewPager.getId();
}
mViewPager.setAdapter(titleAdapter);

如果你想与这个片段通信,你可以从FragmentManager获取If,例如:

getSupportFragmentManager().findFragmentByTag("android:switcher:" + viewpagerid + ":0")

我的解决方案非常粗鲁,但有效:从保留的数据动态创建我的片段,我只是在调用super.onSaveInstanceState()之前从PageAdapter中删除所有片段,然后在活动创建时重新创建它们:

@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("viewpagerpos", mViewPager.getCurrentItem() );
mSectionsPagerAdapter.removeAllfragments();
super.onSaveInstanceState(outState);
}

你不能在onDestroy()中删除它们,否则你会得到这个异常:

java.lang.IllegalStateException:onSaveInstanceState之后不能执行此操作

下面是页面适配器中的代码:

public void removeAllfragments()
{
if ( mFragmentList != null ) {
for ( Fragment fragment : mFragmentList ) {
mFm.beginTransaction().remove(fragment).commit();
}
mFragmentList.clear();
notifyDataSetChanged();
}
}

我只保存当前页面并在onCreate()中恢复它,在片段创建之后。

if (savedInstanceState != null)
mViewPager.setCurrentItem( savedInstanceState.getInt("viewpagerpos", 0 ) );

添加:

   @SuppressLint("ValidFragment")

在你上课之前。

如果它不起作用,可以这样做:

@SuppressLint({ "ValidFragment", "HandlerLeak" })

我想提供一个解决方案,扩展antonyt<强>精彩回答< / >强,并提到重写FragmentPageAdapter.instantiateItem(View, int)以保存对已创建的Fragments的引用,以便以后可以对它们进行处理。这也适用于FragmentStatePagerAdapter;详情见注释。


下面是一个简单的例子,说明如何获取由FragmentPagerAdapter返回的Fragments的引用,该引用不依赖于Fragments上的内部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 (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的引用,你也可以用同样的方式获取FragmentPagerAdapter设置的tags: 注意:这并不适用于FragmentStatePagerAdapter,因为它在创建Fragments时没有设置tags
@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来检索它们。这样,即使tagSupportLibrary的未来版本中发生了变化,你仍然是安全的。


不要忘记,根据你的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...
}

我想出了这个简单而优雅的解决方案。它假设活动负责创建片段,而适配器只是为它们服务。

这是适配器的代码(这里没有什么奇怪的,除了mFragments是由Activity维护的片段列表)

class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {


public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}


@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}


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


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


@Override
public CharSequence getPageTitle(int position) {
TabFragment fragment = (TabFragment)mFragments.get(position);
return fragment.getTitle();
}
}

这个线程的整个问题是获得“旧”片段的引用,所以我在活动的onCreate中使用这段代码。

    if (savedInstanceState!=null) {
if (getSupportFragmentManager().getFragments()!=null) {
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
mFragments.add(fragment);
}
}
}

当然,如果需要,您还可以进一步优化此代码,例如确保片段是特定类的实例。

要获得方向改变后的片段,必须使用. gettag()。

    getSupportFragmentManager().findFragmentByTag("android:switcher:" + viewPagerId + ":" + positionOfItemInViewPager)

为了更多的处理,我为我的PageAdapter写了我自己的数组列表,通过viewPagerId和FragmentClass在任何位置获得片段:

public class MyPageAdapter extends FragmentPagerAdapter implements Serializable {
private final String logTAG = MyPageAdapter.class.getName() + ".";


private ArrayList<MyPageBuilder> fragmentPages;


public MyPageAdapter(FragmentManager fm, ArrayList<MyPageBuilder> fragments) {
super(fm);
fragmentPages = fragments;
}


@Override
public Fragment getItem(int position) {
return this.fragmentPages.get(position).getFragment();
}


@Override
public CharSequence getPageTitle(int position) {
return this.fragmentPages.get(position).getPageTitle();
}


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




public int getItemPosition(Object object) {
//benötigt, damit bei notifyDataSetChanged alle Fragemnts refrehsed werden


Log.d(logTAG, object.getClass().getName());
return POSITION_NONE;
}


public Fragment getFragment(int position) {
return getItem(position);
}


public String getTag(int position, int viewPagerId) {
//getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.shares_detail_activity_viewpager + ":" + myViewPager.getCurrentItem())


return "android:switcher:" + viewPagerId + ":" + position;
}


public MyPageBuilder getPageBuilder(String pageTitle, int icon, int selectedIcon, Fragment frag) {
return new MyPageBuilder(pageTitle, icon, selectedIcon, frag);
}




public static class MyPageBuilder {


private Fragment fragment;


public Fragment getFragment() {
return fragment;
}


public void setFragment(Fragment fragment) {
this.fragment = fragment;
}


private String pageTitle;


public String getPageTitle() {
return pageTitle;
}


public void setPageTitle(String pageTitle) {
this.pageTitle = pageTitle;
}


private int icon;


public int getIconUnselected() {
return icon;
}


public void setIconUnselected(int iconUnselected) {
this.icon = iconUnselected;
}


private int iconSelected;


public int getIconSelected() {
return iconSelected;
}


public void setIconSelected(int iconSelected) {
this.iconSelected = iconSelected;
}


public MyPageBuilder(String pageTitle, int icon, int selectedIcon, Fragment frag) {
this.pageTitle = pageTitle;
this.icon = icon;
this.iconSelected = selectedIcon;
this.fragment = frag;
}
}


public static class MyPageArrayList extends ArrayList<MyPageBuilder> {
private final String logTAG = MyPageArrayList.class.getName() + ".";


public MyPageBuilder get(Class cls) {
// Fragment über FragmentClass holen
for (MyPageBuilder item : this) {
if (item.fragment.getClass().getName().equalsIgnoreCase(cls.getName())) {
return super.get(indexOf(item));
}
}
return null;
}


public String getTag(int viewPagerId, Class cls) {
// Tag des Fragment unabhängig vom State z.B. nach bei Orientation change
for (MyPageBuilder item : this) {
if (item.fragment.getClass().getName().equalsIgnoreCase(cls.getName())) {
return "android:switcher:" + viewPagerId + ":" + indexOf(item);
}
}
return null;
}
}

所以只要用这些片段创建一个MyPageArrayList:

    myFragPages = new MyPageAdapter.MyPageArrayList();


myFragPages.add(new MyPageAdapter.MyPageBuilder(
getString(R.string.widget_config_data_frag),
R.drawable.ic_sd_storage_24dp,
R.drawable.ic_sd_storage_selected_24dp,
new WidgetDataFrag()));


myFragPages.add(new MyPageAdapter.MyPageBuilder(
getString(R.string.widget_config_color_frag),
R.drawable.ic_color_24dp,
R.drawable.ic_color_selected_24dp,
new WidgetColorFrag()));


myFragPages.add(new MyPageAdapter.MyPageBuilder(
getString(R.string.widget_config_textsize_frag),
R.drawable.ic_settings_widget_24dp,
R.drawable.ic_settings_selected_24dp,
new WidgetTextSizeFrag()));

并将它们添加到viewPager:

    mAdapter = new MyPageAdapter(getSupportFragmentManager(), myFragPages);
myViewPager.setAdapter(mAdapter);

在此之后,你可以通过使用它的类来获得正确的方向改变片段:

        WidgetDataFrag dataFragment = (WidgetDataFrag) getSupportFragmentManager()
.findFragmentByTag(myFragPages.getTag(myViewPager.getId(), WidgetDataFrag.class));

如果有人有问题与他们的FragmentStatePagerAdapter不正确地恢复其碎片的状态…新的片段是由FragmentStatePagerAdapter创建的,而不是它从状态恢复它们…

确保在调用ViewPager.setAdapter(fragmentStatePagerAdapter)之前调用ViewPager.setOffscreenPageLimit()

调用ViewPager.setOffscreenPageLimit()…ViewPager将立即查找它的适配器并尝试获取它的片段。这可能发生在ViewPager有机会从savedInstanceState恢复片段之前(因此创建的新片段不能从savedInstanceState重新初始化,因为它们是新的)。

有一点不同的意见,不要自己存储碎片,而是把它留给FragmentManager,当你需要对碎片做一些事情时,在FragmentManager中查找它们:

//make sure you have the right FragmentManager
//getSupportFragmentManager or getChildFragmentManager depending on what you are using to manage this stack of fragments
List<Fragment> fragments = fragmentManager.getFragments();
if(fragments != null) {
int count = fragments.size();
for (int x = 0; x < count; x++) {
Fragment fragment = fragments.get(x);
//check if this is the fragment we want,
//it may be some other inspection, tag etc.
if (fragment instanceof MyFragment) {
//do whatever we need to do with it
}
}
}

如果你有很多fragment, instanceof check的成本可能不是你想要的,但是记住FragmentManager已经记录了Fragments,这是一件好事。