findFragmentById总是返回null

60

我正在xml布局中为我的片段定义一个ID:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/test_fragment"
...

然后我在活动的onCreate方法中添加了这个片段:

MyFragment myFragment = new MyFragment();
fragmentTransaction.add(R.id.fragment_container, myFragment);
fragmentTransaction.commit();

这一切都运行良好。替换片段也能正常工作。

稍后,我尝试在其中一个活动的方法中通过其ID检索此片段:

MyFragment myFragment = (MyFragment) getFragmentManager().findFragmentById(R.id.test_fragment);

这样做会导致 null 的 myFragment,总是如此。

当我尝试使用标签而不是 ID 时,可以轻松地通过其标签检索片段,没有任何问题:

MyFragment myFragment = new MyFragment();
fragmentTransaction.add(R.id.fragment_container, myFragment, "testfragment");
fragmentTransaction.commit();
抱歉,我无法提供您所要求的服务。
MyFragment myFragment = (MyFragment) getFragmentManager().findFragmentByTag("testfragment");
为什么 findFragmentById 找不到 fragment,但是 findFragmentByTag 可以找到?我有什么遗漏吗?

尝试使用 (MyFragment) getFragmentManager().findFragmentById(R.id.container); - offset
9个回答

44

R.id.test_fragment 不是您片段的 ID,而是LinearLayout的ID。

调用add(int containerViewId, Fragment fragment)将添加没有标签的片段。 因此,您可以使用add(int containerViewId, Fragment fragment, String tag)并使用标签(作为ID)获取片段。


20
这是一个有效的解决方法,但并没有回答问题。请查看文档以获取正确的描述。文档中说,ID 要么在从 XML 填充片段时分配,要么在使用事务添加时是容器 ID... http://developer.android.com/reference/android/app/FragmentManager.html#findFragmentById(int) - speedynomads
请参考此答案,了解如何通过编程方式分配ID:https://dev59.com/questions/NGoy5IYBdhLWcg3wkO-h#13241629 - speedynomads
6
如果一个Fragment没有指定id,你不能使用它所在容器的id来找到它吗?我很确定这是可以做到的。 - Mike T
5
Mike T是正确的。文档明确表示,您应该能够在getFragmentById()中使用片段容器的ID。 - Timmmm
1
你不必使用带有标签的 add(...)。文档是正确的。你只需要使用正确的 FragmentManager 实例,以使 getFragmentById() 按照你期望的方式工作。请查看下面的答案获取更多信息。 - vir us

9

在你的布局文件中使用<FrameLayout>标签作为容器。稍后,要动态替换活动中的片段,可以使用<FrameLayout>容器的ID来替换活动中的片段。

<FrameLayout
            android:id="@+id/test_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

4
我在布局中使用了android.support.v4.app.Fragment,同时调用getFragmentManager(),它实际上搜索的是android.app.Fragment子类,导致返回null。解决方法是改用getSupportFragmentManager()
通常情况下,请确保您在布局中使用的片段的包与由执行搜索的相应FragmentManager返回的包相同。

4
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/test_fragment"

应该使用片段而不是线性布局
<fragment android:name="com.example.yourfragment"
            android:id="@+id/test_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

那我需要改变什么?我不能使用<fragment>作为顶级节点来定义我的布局。我也不能在活动的XML布局中添加片段,因为我之后必须将它们移除。 - Viper
好的,那么您不能在布局中定义片段。如果您需要检索LinearLayout,则必须在onCreateView中使用inflater参数。 - Blackbelt

3

或者,你应该使用:

(MyFragment) getFragmentManager().findFragmentById(R.id.fragment_container);

2
上述提到的原因是有效的,但另一个可能的原因是您正在尝试在片段中查找片段,这也会导致fragmentManager.findFragmentById返回null。我们应该使用childFragmentManager.findFragmentById来查找片段中的片段。根据官方文档。 public final androidx.fragment.app.FragmentManager getChildFragmentManager() 返回私有FragmentManager,以便在此片段内放置和管理片段。

我知道这违反了stackoverflow的规定,但仅仅点赞是不够的,你是传奇。 - Amr

2

1
FragmentB fragmentB = 
(FragmentB) getSupportFragmentManager().findFragmentById(R.id.containerb);

if(fragmentB != null)
{
   fragmentB.showuserResponse(msg);
}

使用容器ID作为片段ID。然后检查是否存在空引用。

0

fragmentTransaction.add(R.id.fragment_container, myFragment);

MyFragment myFragment = (MyFragment) getFragmentManager().findFragmentById(R.id.test_fragment);

请注意区别。

应该将R.id.fragment_container作为参数传递给findFragmentById函数,就像你传递给add函数一样,而不是R.id.test_fragment

顺便说一下,根据这两个函数的内部实现,它的id可以是其容器视图的id。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接