{"record":{"id":"77c9626969f0fa1d","repo":"microg/GmsCore","slug":"cannot-add-twice-the-same-onswitchchangelistener","errorCode":null,"errorMessage":"Cannot add twice the same OnSwitchChangeListener","messagePattern":"Cannot add twice the same OnSwitchChangeListener","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBar.java","lineNumber":185,"sourceCode":"        final boolean isChecked = !mSwitch.isChecked();\n        setChecked(isChecked);\n    }\n\n    public void propagateChecked(boolean isChecked) {\n        final int count = mSwitchChangeListeners.size();\n        for (int n = 0; n < count; n++) {\n            mSwitchChangeListeners.get(n).onSwitchChanged(mSwitch, isChecked);\n        }\n    }\n\n    @Override\n    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {\n        propagateChecked(isChecked);\n    }\n\n    public void addOnSwitchChangeListener(OnSwitchChangeListener listener) {\n        if (mSwitchChangeListeners.contains(listener)) {\n            throw new IllegalStateException(\"Cannot add twice the same OnSwitchChangeListener\");\n        }\n        mSwitchChangeListeners.add(listener);\n    }\n\n    public void removeOnSwitchChangeListener(OnSwitchChangeListener listener) {\n        if (!mSwitchChangeListeners.contains(listener)) {\n            throw new IllegalStateException(\"Cannot remove OnSwitchChangeListener\");\n        }\n        mSwitchChangeListeners.remove(listener);\n    }\n\n    static class SavedState extends BaseSavedState {\n        boolean checked;\n        boolean visible;\n\n        SavedState(Parcelable superState) {\n            super(superState);\n        }","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBar.java#L167-L203","documentation":"SwitchBar keeps a list of OnSwitchChangeListener objects and refuses to register the same listener instance twice. Adding a duplicate would cause the listener to receive every checked-state change twice, so addOnSwitchChangeListener throws an IllegalStateException when contains(listener) is already true.","triggerScenarios":"Calling addOnSwitchChangeListener(listener) with a listener instance that was already added and not removed; typical when an Activity/Fragment re-runs setup code (e.g. onResume or configuration change) without calling removeOnSwitchChangeListener first.","commonSituations":"Lifecycle mistakes in Android Activities/Fragments: adding the listener in onCreate and again in onResume; re-attaching after rotation; adding an anonymous listener recreated each call (a new instance is fine, but the same instance re-added is not).","solutions":["Ensure addOnSwitchChangeListener is called only once per listener instance, e.g. guard with a boolean flag or add in onCreate only.","Always pair with removeOnSwitchChangeListener in the symmetric lifecycle callback (onDestroy/onPause) before re-adding.","Check mSwitchChangeListeners.contains(listener) before adding if you cannot control call sites.","If duplicate registration is intentional, maintain your own list and skip SwitchBar's duplicate check."],"exampleFix":"// before\nswitchBar.addOnSwitchChangeListener(this);\n// after\nif (!switchBarContainsListener) {\n    switchBar.addOnSwitchChangeListener(this);\n    switchBarContainsListener = true;\n}","handlingStrategy":"validation","validationCode":"if (listener != null && !switchBarContainsListener) { switchBar.addOnSwitchChangeListener(listener); switchBarContainsListener = true; }","typeGuard":null,"tryCatchPattern":"try { switchBar.addOnSwitchChangeListener(listener); } catch (IllegalStateException e) { // already registered; ignore }","preventionTips":["Add listeners in onCreate only, remove in onDestroy","Keep add/remove strictly paired","Track registration with a boolean flag"],"tags":["android","ui","listener-registration","illegal-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}