SupportFragmentManager的findFragmentById始终返回null

时间:2016-01-12 20:17:01

标签: android android-fragments android-viewpager fragment

我正在尝试使用findFragmentById()获取Fragment引用,但它总是返回一个null对象。我使用了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){}
});

2 个答案:

答案 0 :(得分:4)

请改为:

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相关联的后栈上的所有片段。

你应该调用它来获取片段容器中的哪个片段(例如,如果你正在使用导航抽屉,并且想知道哪个片段在视口中),那么你正在使用{{1它包含多个片段。

我希望,这有帮助。

答案 1 :(得分:2)

如果您未在活动的内容视图(它的.xml文件)中声明您的片段,

findFragmentById()将始终返回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>

这样,使用FragmentManagerfindFragmentById()中查找片段会返回MyFragment的正确实例。

findFragmentById()一种在FragmentManager中查找片段的方式,但在findFragmentByTag()中还有另一种方式。

在您的情况下,您最有可能通过以下方法在PagerAdapter的实例中设置这些片段:

@Override
public Fragment getItem(int position) {}

现在有很多示例和答案鼓励您使用一些反射来从FragmentManager中获取片段。 Android会自动为每个片段生成一个标记,您可以使用以下方法获取此名称:

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

其中viewIdViewPagerid的xml文件中的ID,可以在适配器getItemId(position)的任何位置获取。 这可行,但由于这里使用的反射,这是一个丑陋的解决方案。

这是一个非常简单但难看的解决方案,如果Android团队没有改变他们生成标签的逻辑,那么该解决方案应该有效:)

请参阅this SO响应以获取其他可能解决方案的列表。