报错引发的LayoutInflater使用上的思考
今天在开发过程中无意间收获了这么一个崩溃:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:4937)
at android.view.ViewGroup.addView(ViewGroup.java:4768)
at android.view.ViewGroup.addView(ViewGroup.java:4708)
at androidx.fragment.app.FragmentStateManager.addViewToContainer(FragmentStateManager.java:840)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:529)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1808)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:538)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
崩溃的意思是某个View已经存在父View,如果要重复添加的话就得先执行removeView()把
它从父View中移除,这是一个很常见的错误,一个View只能存在一个父View。同理:同一个鸡蛋不可能同时被放在两个篮子中。
报错代码在一个Fragment->onCreateView()
声明周期回调中:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_me, container)
}
只需要将 inflater.inflate(R.layout.fragment_me, container)
这行改成 inflater.inflate(R.layout.fragment_me, container, false)
即可正常运行。
LayoutInflater原理解析
这个inflate方法旨在获取某个指定的View
进去翻了翻这段代码的源码,简单记录一下,如果不感兴趣可直接翻到末尾总结中查看使用时的注意事项:
首先不管它如何创建,直接从报错代码切入,inflate方法总共有4个重载:
// 方法1
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
// 方法2
public View inflate(XmlPullParser parser, @Nullable ViewGrou