{"record":{"id":"53951183681fa144","repo":"Tencent/matrix","slug":"call-init-first","errorCode":null,"errorMessage":"Call #init() first!","messagePattern":"Call #init\\(\\) first!","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/BatteryEventDelegate.java","lineNumber":80,"sourceCode":"            }\n        }\n    }\n\n    public static void init(Application application) {\n        if (sInstance == null) {\n            synchronized (TAG) {\n                if (sInstance == null) {\n                    sInstance = new BatteryEventDelegate(application);\n                }\n            }\n        }\n    }\n\n    public static BatteryEventDelegate getInstance() {\n        if (sInstance == null) {\n            synchronized (TAG) {\n                if (sInstance == null) {\n                    throw new IllegalStateException(\"Call #init() first!\");\n                }\n            }\n        }\n        return sInstance;\n    }\n\n    final Context mContext;\n    final List<Listener> mListenerList = new LinkedList<>();\n    final Handler mUiHandler = new Handler(Looper.getMainLooper());\n    final BackgroundTask mAppLowEnergyTask = new BackgroundTask();\n    boolean sIsForeground = true;\n    long mLastBatteryPowerPct;\n    long mLastBatteryTemp;\n\n    @Nullable\n    BatteryMonitorCore mCore;\n\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/BatteryEventDelegate.java#L62-L98","documentation":"BatteryEventDelegate.getInstance() uses double-checked locking and throws IllegalStateException if sInstance is null, meaning BatteryEventDelegate.init() was never called. The delegate is a singleton that requires explicit initialization before any accessor can be used.","triggerScenarios":"Calling BatteryEventDelegate.getInstance() before any call to BatteryEventDelegate.init(context, ...) — e.g. during early Application startup ordering, or after init failed silently.","commonSituations":"Accessing the delegate from a component (Activity/Service/ContentProvider) that runs before Application.onCreate init; calling getInstance() in unit tests without initializing the singleton; init() throwing earlier so sInstance was never assigned.","solutions":["Call BatteryEventDelegate.init(applicationContext) (ideally in Application.onCreate) before any getInstance() call.","Guard access: only call getInstance() after verifying init completed, e.g. keep a boolean flag set post-init.","In tests, invoke init() in @Before setup or mock the delegate instead of the singleton."],"exampleFix":"// before\nBatteryEventDelegate delegate = BatteryEventDelegate.getInstance(); // IllegalStateException\n\n// after\n// in MyApplication.onCreate()\nBatteryEventDelegate.init(getApplication());\nBatteryEventDelegate delegate = BatteryEventDelegate.getInstance();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    BatteryEventDelegate d = BatteryEventDelegate.getInstance();\n    // use d\n} catch (IllegalStateException e) {\n    BatteryEventDelegate.init(application); // lazy init then retry\n    BatteryEventDelegate d = BatteryEventDelegate.getInstance();\n}","preventionTips":["Call BatteryEventDelegate.init(application) in Application.onCreate before any component can touch the delegate.","Keep initialization order documented: Matrix.init -> BatteryEventDelegate.init -> feature code.","Avoid direct singleton access in tests; inject the delegate instead."],"tags":["android","initialization","singleton","battery"],"backgroundTag":"module-init-failed","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}