findFragmentById返回null

时间:2014-04-29 00:15:03

标签: android android-fragments nullpointerexception

当我用我的片段的id调用findFragmentById()时,它返回null。让我告诉你代码。

activity_main.xml

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

        <fragment android:name="com.madduck.test.app.fragment.MainFragment"
                  android:id="@+id/main_fragment"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />

        <fragment android:name="com.madduck.test.app.fragment.LoginFragment"
                  android:id="@+id/login_fragment"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />
</LinearLayout>

MainActivity.java

private static final int LOGIN = 0;
private static final int MAIN = 1;
private static final int FRAGMENT_COUNT = MAIN +1;
private Fragment[] fragments = new Fragment[FRAGMENT_COUNT]

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentManager fm = getSupportFragmentManager();
    fragments[LOGIN] = fm.findFragmentById(R.id.login_fragment);
    fragments[MAIN] = fm.findFragmentById(R.id.main_fragment);

    FragmentTransaction transaction = fm.beginTransaction();
    for (Fragment f : fragments) {
        if (f != null)
            transaction.hide(f);
        else
            Log.e(TAG, "???");
    }

    transaction.commit();
}

问题在于,当我打电话给fm.findFragmentById(R.id.login_fragment);时,我得到了空,但当我打电话给fm.findFragmentById(R.id.main_fragment);时,我得到了片段。

6 个答案:

答案 0 :(得分:82)

答案Kar0t完全没问题,但这可能有助于某人。在我的情况下,我在片段内部有一个片段,我得到了错误的FragmentManager。我只需要打电话:

getChildFragmentManager()

然后像往常一样找到片段:

fm.findFragmentById(R.id.fragment)

答案 1 :(得分:33)

刚刚发现我的错误。

在我的MainActivity.java中,我导入了android.support.v4.app.Fragment;,在我的LoginFragment.java中导入了android.app.Fragment;。我把它改成了同样的东西,fm.findFragmentById(R.id.login_fragment)现在返回正确的片段。

答案 2 :(得分:4)

与特定问题并不完全相关,但与在null上接收findFragmentById有关,如果在提交后立即调用findFragmentById,它将返回null或最后一个片段(在提交之前),原因是因为commit会执行异步请求。

来自文档:

  

计划此事务的提交。提交不会发生   立即;它将被安排为主线程上的工作   下次线程准备就绪时完成。

如果您需要立即findFragmentById,例如在添加片段后更改状态栏文本颜色,请在executePendingTransactions()之后调用commit()

getSupportFragmentManager().executePendingTransactions();
//call findFragmentById 

答案 3 :(得分:1)

我遇到了此问题,因为我的项目具有两个具有相同文件名的布局。例如。就您而言,我在不同的模块中有两个activity_main.xml

所以以某种方式编译它以及在您运行时

fm.findFragmentById(R.id.login_fragment)

然后它正在另一个activity_main.xml中查找该片段,该片段为空。

在这种情况下,只需检查布局的文件名,确保它们是唯一的即可。

希望这对与我有相同问题的所有人有所帮助。 :)

答案 4 :(得分:0)

科特林

我也遇到了问题,因为我身处儿童碎片中。我可以使用:

    supportFragmentManager.fragments.forEach {
        it.childFragmentManager.fragments.forEach { fragment ->
            if (fragment is HomeFragment) {
                //do something
            } 
        }

但是一位同事使用进行了优化:

     if( findNavController(R.id.nav_host_fragment).currentDestination?.id == R.id.homeFragment) {
       // do something
   }

答案 5 :(得分:0)

Android 生活每天都是一些被贬低的东西,我们正在寻找示例和手册,但它们已经不起作用)

我的问题是混合“import android.app.Fragment;”与现代“androidx.fragment.app.Fragment”。下面是androidx的示例

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

            Fragment myFrag = getSupportFragmentManager().findFragmentById(R.id.frgmContainer);
            if(myFrag==null)
                return;
            ((TextView) myFrag.getView().findViewById(R.id.textView))
                    .setText("Access to Fragment 2 from Activity");