{"record":{"id":"6b2881f76e64abea","repo":"Blankj/AndroidUtilCode","slug":"the-key-is-null","errorCode":null,"errorMessage":"The key is null.","messagePattern":"The key is null\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/utilcode/src/main/java/com/blankj/utilcode/util/DebouncingUtils.java","lineNumber":61,"sourceCode":"     *\n     * @param view     The view.\n     * @param duration The duration.\n     * @return {@code true}: yes<br>{@code false}: no\n     */\n    public static boolean isValid(@NonNull final View view, final long duration) {\n        return isValid(String.valueOf(view.hashCode()), duration);\n    }\n\n    /**\n     * Return whether the key is not in a jitter state.\n     *\n     * @param key      The key.\n     * @param duration The duration.\n     * @return {@code true}: yes<br>{@code false}: no\n     */\n    public static boolean isValid(@NonNull String key, final long duration) {\n        if (TextUtils.isEmpty(key)) {\n            throw new IllegalArgumentException(\"The key is null.\");\n        }\n        if (duration < 0) {\n            throw new IllegalArgumentException(\"The duration is less than 0.\");\n        }\n        long curTime = SystemClock.elapsedRealtime();\n        clearIfNecessary(curTime);\n        Long validTime = KEY_MILLIS_MAP.get(key);\n        if (validTime == null || curTime >= validTime) {\n            KEY_MILLIS_MAP.put(key, curTime + duration);\n            return true;\n        }\n        return false;\n    }\n\n    private static void clearIfNecessary(long curTime) {\n        if (KEY_MILLIS_MAP.size() < CACHE_SIZE) return;\n        for (Iterator<Map.Entry<String, Long>> it = KEY_MILLIS_MAP.entrySet().iterator(); it.hasNext(); ) {\n            Map.Entry<String, Long> entry = it.next();","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Blankj/AndroidUtilCode/blob/7b4caf9e5440046b3fefb63b6b6e2ead7ebaf809/lib/utilcode/src/main/java/com/blankj/utilcode/util/DebouncingUtils.java#L43-L79","documentation":"DebouncingUtils.isValid(String, long) keys recent activity by a string and returns whether enough time has elapsed. It rejects an empty/null key with IllegalArgumentException because the internal KEY_MILLIS_MAP is a ConcurrentHashMap and TextUtils.isEmpty(key) covers both null and \"\"; an empty key would collide all debounced callers into one slot and silently suppress legitimate events.","triggerScenarios":"Calling isValid(key, duration) where key is null, \"\", or whitespace-only produced by String.valueOf of a null/empty source; building a key from an object whose hash source is unset; forwarding a user-entered identifier that was never validated.","commonSituations":"Using String.valueOf(view.hashCode()) on a view whose hashCode is 0 and then trimming; debouncing by an analytics/event name that came back empty from a config; a per-item key derived from a missing database column; copy-paste of the view-based overload with the wrong argument.","solutions":["Always derive a meaningful, non-empty key (e.g. a stable view ID, a tag, or a namespaced event name) before calling isValid.","Guard with if (!TextUtils.isEmpty(key)) before invoking, and skip/no-op when the key is empty.","Prefer the view overload isValid(View, long) when debouncing UI clicks — it derives the key internally.","If the key comes from external input, validate and fall back to a deterministic default at the boundary."],"exampleFix":"// before\nboolean ok = DebouncingUtils.isValid(eventName, 1000); // eventName may be \"\"\n\n// after\nString key = TextUtils.isEmpty(eventName) ? \"fallback:\" + viewId : eventName;\nboolean ok = DebouncingUtils.isValid(key, 1000);","handlingStrategy":"validation","validationCode":"// Validate the key before debouncing\nString key = eventName;\nif (TextUtils.isEmpty(key)) {\n    key = \"fallback:\" + viewId; // or skip the call\n}\nboolean ok = DebouncingUtils.isValid(key, duration);","typeGuard":"// Ensure a usable key\npublic static String nonEmptyDebounceKey(String raw, String fallback) {\n    return (raw == null || raw.trim().isEmpty()) ? fallback : raw;\n}","tryCatchPattern":"try {\n    boolean ok = DebouncingUtils.isValid(key, duration);\n} catch (IllegalArgumentException e) {\n    // key was empty; substitute a stable key and retry\n    ok = DebouncingUtils.isValid(\"fallback:\" + viewId, duration);\n}","preventionTips":["Always derive a stable, non-empty key (view id, tag, or namespaced event name).","Guard with TextUtils.isEmpty(key) before calling and fall back or skip.","Prefer the View overload isValid(view, duration) for click debouncing."],"tags":["validation","debounce","argument-check","null-check"],"backgroundTag":null,"analyzedSha":"7b4caf9e5440046b3fefb63b6b6e2ead7ebaf809","analyzedAt":"2026-08-14T02:26:54.956Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}