Android SupportFragmentManager';s findFragmentById始终返回空值

Android SupportFragmentManager';s findFragmentById始终返回空值,android,android-fragments,android-viewpager,fragment,Android,Android Fragments,Android Viewpager,Fragment,我试图使用findFragmentById()获取片段引用,但它总是返回空对象。我使用了FragmentPagerAdapter并在页面更改侦听器上附加了一个OnPageChangeListener,这样每当我滚动到一个特定的片段,比如FragmentB,都应该触发FragmentB的方法 我有以下代码: mPager.addOnPageChangeListener(new OnPageChangeListener() { @Override public void onPage

我试图使用
findFragmentById()
获取片段引用,但它总是返回空对象。我使用了
FragmentPagerAdapter
并在页面更改侦听器上附加了一个
OnPageChangeListener
,这样每当我滚动到一个特定的片段,比如
FragmentB
,都应该触发
FragmentB
的方法

我有以下代码:

mPager.addOnPageChangeListener(new OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        if (position == 1) {
            FragmentB fb = (FragmentB) getSupportFragmentManager().findFragmentById(R.id.fragment_b);

            fb.refreshList(); 
            //fb is always null

            Toast.makeText(MainActivity.this,"Scrolled", Toast.LENGTH_SHORT).show();                                                                         
            //Toast is working fine
        }
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2){}

    @Override
    public void onPageScrollStateChanged(int arg0){}
});
只需这样做:

mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        PagerAdapter pagerAdapter = (PagerAdapter) mPager.getAdapter();
        if (position == 1) {
            FragmentB fragmentB = (FragmentB)pagerAdapter.getItem(position);
            fragmentB.refreshList();
        }
    }

    @Override
    public void onPageSelected(int position) {}

    @Override
    public void onPageScrollStateChanged(int state) {}
});
findFragmentById
的问题不打算以这种方式使用:

查找在从XML膨胀时由给定id标识的片段,或在事务中添加时作为容器id标识的片段。首先搜索当前添加到经理活动中的片段;如果没有找到这样的片段,那么将搜索与此ID关联的后堆栈上当前的所有片段

当您使用承载多个片段的
ViewPager
时,应该调用它来获取片段容器中的片段(例如,如果您使用的是导航抽屉,并且您想知道哪个片段在视口中)

我希望这会有所帮助。

findFragmentById()
如果您没有在活动的内容视图(它是.xml文件)中声明您的片段,那么它将始终返回null,因为您无法以编程方式设置片段的ID

如果您对此感兴趣,下面是您的代码在活动的xml文件中的外观:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment
        android:id="@+id/my_id"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.mypackage.MyFragment"/>
</LinearLayout>
现在有很多示例和答案鼓励您使用一些反射从FragmentManager获取片段。Android会自动为每个片段生成一个标记,您可以通过以下方法获得此名称:

@Override
public Fragment getItem(int position) {}
private static String getFragmentName(int viewId, int id) {
    return "android:switcher:" + viewId + ":" + id;
} 
然后您可以构建一个getter方法来获得如下片段:

public Fragment getFragmentForPosition(int position) { 
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(getFragmentName(mViewPager.getId(), getItemId(position)));
    return fragment; // May be null if the fragment is not found. Handle that case too wherever you call this method.
}
其中
viewId
ViewPager
的xml文件中的ID,并且
ID
可以通过
getItemId(position)
在适配器的任何位置获得。 这将是可行的,但这是一个有点丑陋的解决方案,因为这里使用的反射

这是一个非常简单但丑陋的解决方案,如果安卓团队不改变他们生成标签的逻辑,它应该可以工作:)


有关其他可能的解决方案列表,请参阅SO回复。

谢谢。你的解决方案有效。但是,您能告诉我是否要获取MainActivity的onCreate()或onCreateView()内部的
片段吗?我尝试了他们的方法,但总是得到一个NullPointerException。@MrShadow为什么要在
onCreate()
中调用fragment,即在创建适配器之后?它还没有附加到活动中。但无论如何,在初始化适配器之后,几乎从类的任何一点都可以执行:
((PagerAdapter)mPager.getAdapter()).getItem(mPager.getCurrentItem())我想向片段添加一个自定义接口侦听器,以便片段可以相互通信。我在FragmentA中有一个recyclerview,在FragmentB中有另一个recyclerview。我想在FragmentA中发生任何事情时更新FragmentB的RecyclerView。为了实现这一点,我必须使用接口实现片段间通信。这就是我所指的@MrShadow,我可以建议你更高级一点,但要像一个魅力解决方案一样在片段(比如片段活动)之间进行通信吗?i、 为了在片段之间使用发布-订阅方式的通信,我一定会尝试这种方式。非常感谢。但是,如果我在以后执行此操作时遇到任何问题,请帮助我。