在Fragment附加到FragmentManager之前无法执行onGetLayoutInflater()。

14

有时我会收到以下错误信息:

在Fragment附加到FragmentManager之前,无法执行onGetLayoutInflater()

我的完整堆栈跟踪(使用CompositeAndroid作为父片段):

Fatal Exception: java.lang.IllegalStateException: onGetLayoutInflater() cannot be executed until the Fragment is attached to the FragmentManager.
       at android.support.v4.app.Fragment.getLayoutInflater(Fragment.java:1151)
       at com.pascalwelsch.compositeandroid.fragment.CompositeFragment.super_getLayoutInflater(CompositeFragment.java:1310)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$7.call(FragmentDelegate.java:204)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$7.call(FragmentDelegate.java:197)
       at com.pascalwelsch.compositeandroid.fragment.FragmentPlugin.getLayoutInflater(FragmentPlugin.java:149)
       at com.pascalwelsch.compositeandroid.fragment.FragmentPlugin.getLayoutInflater(FragmentPlugin.java:1269)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$7.call(FragmentDelegate.java:202)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$7.call(FragmentDelegate.java:197)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate.getLayoutInflater(FragmentDelegate.java:208)
       at com.pascalwelsch.compositeandroid.fragment.CompositeFragment.getLayoutInflater(CompositeFragment.java:163)
       at android.support.v4.app.Fragment.onGetLayoutInflater(Fragment.java:1101)
       at com.pascalwelsch.compositeandroid.fragment.CompositeFragment.super_onGetLayoutInflater(CompositeFragment.java:1710)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$32.call(FragmentDelegate.java:769)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$32.call(FragmentDelegate.java:762)
       at com.pascalwelsch.compositeandroid.fragment.FragmentPlugin.onGetLayoutInflater(FragmentPlugin.java:528)
       at com.pascalwelsch.compositeandroid.fragment.FragmentPlugin.onGetLayoutInflater(FragmentPlugin.java:1456)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$32.call(FragmentDelegate.java:767)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate$32.call(FragmentDelegate.java:762)
       at com.pascalwelsch.compositeandroid.fragment.FragmentDelegate.onGetLayoutInflater(FragmentDelegate.java:773)
       at com.pascalwelsch.compositeandroid.fragment.CompositeFragment.onGetLayoutInflater(CompositeFragment.java:538)
       at android.support.v4.app.Fragment.performGetLayoutInflater(Fragment.java:1132)
       at android.support.v4.app.Fragment.getLayoutInflater(Fragment.java:1117)
       at com.my.app.features.event.EventDetailFragment.attachHeader(EventDetailFragment.java:66)
       ...

我们可以看到,在第1117行首先调用了方法getLayoutInflater(),然后在第1151行调用了另一个方法。
第一个方法是这个:
/**
 * Returns the cached LayoutInflater used to inflate Views of this Fragment. If
 * {@link #onGetLayoutInflater(Bundle)} has not been called {@link #onGetLayoutInflater(Bundle)}
 * will be called with a {@code null} argument and that value will be cached.
 * <p>
 * The cached LayoutInflater will be replaced immediately prior to
 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} and cleared immediately after
 * {@link #onDetach()}.
 *
 * @return The LayoutInflater used to inflate Views of this Fragment.
 */
public final LayoutInflater getLayoutInflater() {
    if (mLayoutInflater == null) {
        return performGetLayoutInflater(null);
    }
    return mLayoutInflater;
}

第二个方法会抛出异常并被标记为deprecated

/**
 * Override {@link #onGetLayoutInflater(Bundle)} when you need to change the
 * LayoutInflater or call {@link #getLayoutInflater()} when you want to
 * retrieve the current LayoutInflater.
 *
 * @hide
 * @deprecated Override {@link #onGetLayoutInflater(Bundle)} or call
 * {@link #getLayoutInflater()} instead of this method.
 */
@Deprecated
@NonNull
@RestrictTo(LIBRARY_GROUP)
public LayoutInflater getLayoutInflater(@Nullable Bundle savedFragmentState) {
    if (mHost == null) {
        throw new IllegalStateException("onGetLayoutInflater() cannot be executed until the "
                + "Fragment is attached to the FragmentManager.");
    }
    LayoutInflater result = mHost.onGetLayoutInflater();
    getChildFragmentManager(); // Init if needed; use raw implementation below.
    LayoutInflaterCompat.setFactory2(result, mChildFragmentManager.getLayoutInflaterFactory());
    return result;
}

这里调用了一个被弃用的函数,这正常吗?我认为在调用getLayoutInflater()之前检查isAdded()后不应该抛出异常。
private void init () {
    if(isAdded()) {
        attachHeader();
        updateHeader();
    }
}

private void attachHeader() {
    headerBinding = DataBindingUtil.inflate(getLayoutInflater(), layout.event_detail_header,
            binding.formsContainer, false);
    binding.formsContainer.addView(headerBinding.getRoot(), 0);
}
4个回答

3

针对未来的读者。在我的情况下,我在API响应中的Fragment中使用了getLayoutInflater,当我尝试更改片段时,出现了以下错误:

致命异常:java.lang.IllegalStateException: 在Fragment附加到FragmentManager之前无法执行onGetLayoutInflater()。

所以,我通过在fragmentonDestroy中取消我的API调用来解决这个问题。

 @Override
    public void onDestroy() {
        super.onDestroy();
        disposable.dispose(); //RxJava
    }

可能对其他用户有帮助。

通常建议在调用super.onDestroy之前,在onDestroy中执行所有操作,在调用super.onCreate之后,在onCreate中执行所有操作。 由于父元素可能会在其自身方法结束时通知操作系统onDestroy已完成,如果系统清理得太快,则之后的调用可能永远不会被执行。此外,绑定和视图可能已经不存在了,尽管这不会影响可处理对象。 - Sarah Multitasker

1

在使用mHost.onGetLayoutInflater()之前,必须先确保Fragment已连接到FragmentManager。可以使用以下代码检查Fragment是否已连接:

    Activity activity = getActivity();
    if (isAdded() && activity != null){ // Check the fragment status
        LayoutInflater result = mHost.onGetLayoutInflater();
        getChildFragmentManager(); // Init if needed; use raw implementation below.
        LayoutInflaterCompat.setFactory2(result, 
        mChildFragmentManager.getLayoutInflaterFactory());
    }else{
        LayoutInflater result = null;
    }

1
我觉得这可能仍然有助于某些人。 在绑定视图时从onCreateView中使用inflater似乎可以解决此错误-致命异常:java.lang.IllegalStateException:在Fragment附加到FragmentManager之前无法执行onGetLayoutInflater()
@Override
            public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            render(inflater);
        }
    
    private void render(LayoutInflater inflater) {
    GenericViewBinding genericViewBinding =  GenericViewBinding .inflate(inflater);
    }

在我的情况下,当我尝试在我的片段尚未连接到片段管理器时膨胀视图时(使用默认启用离线缓存的Google firestore,这使响应感觉瞬间),出现了这个错误documentReference.addSnapshotListener(new EventListener() { }

怀着谦卑的心态写下这篇文章,请不要害羞。我只是想帮助。也许还有些事情我没有理解。我仍然很想听听您的意见。谢谢。


0
使用以下代码在使用 Fragment 之前检查它是否已被销毁:
Kotlin:
if (activity?.isFinishing == true ||
     activity?.isChangingConfigurations == true || this.isRemoving ||
     this.activity == null || this.isDetached || !this.isAdded || this.view== null) {
                                return
                            }else{Todo()}

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