Justson/AgentWeb · error · JsCallbackException

the WebView related to the JsCallback has been recycled

Error message

the WebView related to the JsCallback has been recycled

What it means

JsCallback.apply throws JsCallbackException when the WeakReference to the WebView it holds has been cleared, i.e. the WebView was destroyed/recycled (typically after AgentWeb.destroy() or page teardown). The library cannot execute the JS callback without a live WebView, so further calls are impossible.

Solutions

  1. Check the WebView is alive before calling apply, and discard stale JsCallbacks
  2. Cancel pending async work in onDestroyView/onDestroy so callbacks do not outlive the page
  3. Re-issue the callback through a fresh JsCallback obtained during the current page load
  4. Catch JsCallbackException and treat it as 'page gone' — log and skip

Example fix

// before
handler.postDelayed(() -> callback.apply(result), 5000); // webview may be gone
// after
handler.postDelayed(() -> {
    try { callback.apply(result); }
    catch (JsCallbackException e) { Log.w(TAG, "page already recycled", e); }
}, 5000);
Defensive patterns

Strategy: try-catch

Validate before calling

if (callback == null || webViewRefCleared(callback)) { return; }

Type guard

boolean callbackAlive(JsCallback cb) { try { cb.apply(); return false; } catch (JsCallbackException e) { return false; } }

Try / catch

try { callback.apply(args); } catch (JsCallbackException e) { Log.w(TAG, "webview recycled, drop callback", e); }

Prevention

When it happens

Trigger: Holding a JsCallback beyond the page/AgentWeb lifetime and calling apply() after the WebView was destroyed, or invoking from a delayed handler/thread after navigation completed and resources were recycled.

Common situations: Async work (network, timer) finishing after onDestroy and then attempting to call back into the page, caching JsCallback instances across page loads, or AgentWeb.destroy() being called on back-press while callbacks were pending.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Justson/AgentWeb@8f7f6adbf0 (2026-09-11). Data as JSON: /api/errors/9a11f82ee37927ae. Report an issue: GitHub.

Appendix: source

Thrown at agentweb-core/src/main/java/com/just/agentweb/JsCallback.java:51

    private WeakReference<WebView> mWebViewRef;
    private int mIsPermanent;
    private String mInjectedName;

    public JsCallback(WebView view, String injectedName, int index) {
        mCouldGoOn = true;
        mWebViewRef = new WeakReference<WebView>(view);
        mInjectedName = injectedName;
        mIndex = index;
    }

    /**
     * 向网页执行js回调;
     * @param args
     * @throws JsCallbackException
     */
    public void apply (Object... args) throws JsCallbackException {
        if (mWebViewRef.get() == null) {
            throw new JsCallbackException("the WebView related to the JsCallback has been recycled");
        }
        if (!mCouldGoOn) {
            throw new JsCallbackException("the JsCallback isn't permanent,cannot be called more than once");
        }
        StringBuilder sb = new StringBuilder();
        for (Object arg : args){
            sb.append(",");
            boolean isStrArg = arg instanceof String;
            // 有的接口将Json对象转换成了String返回,这里不能加双引号,否则网页会认为是String而不是JavaScript对象;
            boolean isObjArg = isJavaScriptObject(arg);
            if (isStrArg && !isObjArg) {
                sb.append("\"");
            }
            sb.append(String.valueOf(arg));
            if (isStrArg && !isObjArg) {
                sb.append("\"");
            }
        }

View on GitHub (pinned to 8f7f6adbf0)