1. 关于使用butterknife出现的fragment重复添加的问题
出现此问题时,实际上仅从错误信息是无法看出是由于butterknife引起的。但是由于前后修改的内容中最重要的就是butterknife所以只能是由于他引起的。
这个地方就以下出现的异常信息进行说明并记录,注意使用的场景可能需要相同才会出现此问题。
12-17 12:08:09.988 11459-11459/cn.xxxx.xxx E/CrashReport: java.lang.IllegalStateException: Fragment already added: HomeFragment{14c82c9} (ca93c917-7e5b-44da-94a3-f14c9d437125) id=0x7f09043a android:switcher:2131297338:0}
at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5490)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-17 12:08:09.988 11459-11459/cn.xxxx.xxx E/CrashReport: #++++++++++++++++++++++++++++++++++++++++++#
12-17 12:08:10.195 11459-11459/cn.xxxx.xxx E/CrashReport: sys default last handle start!
12-17 12:08:10.196 11459-11459/cn.xxxx.xxx E/CrashReport: sys default last handle end!
12-17 12:08:10.202 11459-11494/cn.xxxx.xxx E/EveriskLog-Loader-UncaughtExceptionAction: start write UncaughtException to everisk_jcrash.txt
12-17 12:08:10.203 11459-11494/? E/EveriskLog-Loader-UncaughtExceptionAction: java.lang.IllegalStateException: Fragment already added: HomeFragment{14c82c9} (ca93c917-7e5b-44da-94a3-f14c9d437125) id=0x7f09043a android:switcher:2131297338:0}
at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at
12-17 12:08:10.204 11459-11494/? E/EveriskLog-Loader-UncaughtExceptionAction: android.app.ActivityThread.main(ActivityThread.java:5490)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-17 12:08:10.204 11459-11494/? E/EveriskLog-Loader-UncaughtExceptionAction: start write UncaughtException to everisk_jcrash.txt
12-17 12:08:10.204 11459-11494/? E/EveriskLog-Loader-UncaughtExceptionAction: java.lang.IllegalStateException: Fragment already added: HomeFragment{14c82c9} (ca93c917-7e5b-44da-94a3-f14c9d437125) id=0x7f09043a android:switcher:2131297338:0}
at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at
12-17 12:08:10.204 11459-11494/? E/EveriskLog-Loader-UncaughtExceptionAction: android.app.ActivityThread.main(ActivityThread.java:5490)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
--------- beginning of crash
12-17 12:08:10.205 11459-11494/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: cn.xxxx.xxx, PID: 11459
java.lang.IllegalStateException: Fragment already added: HomeFragment{14c82c9} (ca93c917-7e5b-44da-94a3-f14c9d437125) id=0x7f09043a android:switcher:2131297338:0}
at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5490)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
1.1. 使用场景
在使用HomeFragment显示首页时,由于控件会通过butterKnife的@BindView
绑定显示,这个是很常见的操作,但是在实际业务中,存在相同的页面业务逻辑完全一样(调用接口或处理逻辑都一样),仅仅区别只是UI不一样的情况。
这里的UI是指整个页面的UI如风格、配色、按钮位置、样式等。在这种情况下选择了将UI显示抽象出接口,通过接口提供业务数据,由具体的UI表现去展示和处理数据(通过加载不同的xml及处理)。
UI抽象接口的通过IDisplay
类似的接口去实现,并在实现类中使用butterknife绑定了相应页面的控件。最终是通过同一个fragment页面调用IDisplay
的接口进行UI展示的。
1.2. 问题原因
在不同的UI抽象接口实现类中,在初始时使用的UI控件的名称是一致的(从旧xml中创建并修改了样式,ID未进行修改),该问题就是直接导致了以上的异常。
猜测原因是butterknife绑定时相同的ID会被与绑定的页面关联,导致了加载时由于使用了相同的ID,该页面可能会通过不同的IDisplay
进行加载,所以出现重复添加fragment的情况。
大概的问题情况与原因如上。解决方案是很明确的:使用不同的xml页面时,强烈建议使用不同的页面ID,至少将可能用于同一页面的xml中的控件命名一致。
1.3. 其它注意事项
解决此问题的还有一个注意事项,在解决时务必卸载掉原APP后再重新安装调试。在实际操作中出现过已经解决掉了重复ID的问题,依然会不断地报以上错误,该问题在clean project
的情况下也不会消失。猜测是原已安装的APP可能存在一定的数据缓存或未更新导致了问题重复出现。
尽管从理论上来说并没有开启Instant Run/Hotsopt
时,应用重新运行时应该重新安装的,不会出现以上情况,但是确实发生过。特此以作记录。