【问题标题】:onGetLayoutInflater() cannot be executed until the Fragment is attached to the FragmentManager在 Fragment 附加到 FragmentManager 之前,无法执行 onGetLayoutInflater()
【发布时间】:2018-05-07 12:05:45
【问题描述】:

我有时会收到带有以下消息的异常:

onGetLayoutInflater() 直到 Fragment 被执行 附加到 FragmentManager

我的完整堆栈跟踪(使用 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;
}

第二个是抛出Exception 并标记为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;
}

他们在这里调用deprecated 函数是否正常? 而且我认为它不应该抛出Exception,因为我在调用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);
}

【问题讨论】:

    标签: android android-fragments android-inflate


    【解决方案1】:

    对于未来的读者。就我而言。我在 Api 响应中的 Fragment 中使用getLayoutInflater,当我尝试更改片段时,我收到了这个错误

    致命异常:java.lang.IllegalStateException: onGetLayoutInflater() 直到 Fragment 被执行 附加到 FragmentManager。

    所以我通过取消我的 Api 调用 onDestroy of fragment 解决了这个问题

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

    可能对其他用户有帮助。

    【讨论】:

      【解决方案2】:

      在 mHost.onGetLayoutInflater() 使用它检查 Fragment 是否附加之前,您必须首先确保 Fragment 已附加到 FragmentManager:

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

      【讨论】:

        【解决方案3】:

        我觉得这仍然可以帮助某人。 在绑定视图时使用 onCreateView 中的 inflater 似乎可以解决此错误 - 致命异常:java.lang.IllegalStateException: onGetLayoutInflater() 在 Fragment 附加到 FragmentManager 之前无法执行

        @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() { } 当我尝试当我的片段尚未附加到 FragmentManager 时,膨胀视图。

        我写的很谦虚,请不要害羞。我只是想帮忙。或许还有什么我还是不明白的。我仍然很想收到你的来信。谢谢。

        【讨论】:

          【解决方案4】:

          使用以下代码检查 Fragment 是否在使用前被销毁:

          科特林:

          if (activity?.isFinishing == true ||
               activity?.isChangingConfigurations == true || this.isRemoving ||
               this.activity == null || this.isDetached || !this.isAdded || this.view== null) {
                                          return
                                      }else{Todo()}
          

          【讨论】:

            猜你喜欢
            • 2020-02-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-01
            • 1970-01-01
            • 2019-09-19
            相关资源
            最近更新 更多