didi/DoKit · error · IllegalStateException

Listener already set.

Error message

Listener already set.

What it means

DokitPicasso.Builder.listener() throws IllegalStateException when a Listener has already been set. The listener slot is single-assignment like the other builder components, so configuring it twice fails immediately.

Source

Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/DokitPicasso.java:765

    /** Specify the memory cache used for the most recent images. */
    public Builder memoryCache(Cache memoryCache) {
      if (memoryCache == null) {
        throw new IllegalArgumentException("Memory cache must not be null.");
      }
      if (this.cache != null) {
        throw new IllegalStateException("Memory cache already set.");
      }
      this.cache = memoryCache;
      return this;
    }

    /** Specify a listener for interesting events. */
    public Builder listener(Listener listener) {
      if (listener == null) {
        throw new IllegalArgumentException("Listener must not be null.");
      }
      if (this.listener != null) {
        throw new IllegalStateException("Listener already set.");
      }
      this.listener = listener;
      return this;
    }

    /**
     * Specify a transformer for all incoming requests.
     * <p>
     * <b>NOTE:</b> This is a beta feature. The API is subject to change in a backwards incompatible
     * way at any time.
     */
    public Builder requestTransformer(RequestTransformer transformer) {
      if (transformer == null) {
        throw new IllegalArgumentException("Transformer must not be null.");
      }
      if (this.transformer != null) {
        throw new IllegalStateException("Transformer already set.");
      }

View on GitHub (pinned to 626827cddb)

Solutions

  1. Register only one Listener and route events from it to all consumers
  2. If multiple observers are needed, create a composite listener that fans out and register it once
  3. Remove the duplicate listener() call

Example fix

// before
builder.listener(baseListener);
builder.listener(appListener); // IllegalStateException

// after
class CompositeListener implements DokitPicasso.Listener {
  ...delegate to baseListener and appListener...
}
builder.listener(new CompositeListener());
Defensive patterns

Strategy: validation

Validate before calling

class Composite implements DokitPicasso.Listener { public void onImageLoadFailed(DokitPicasso p, Uri u, Exception e) { a.onImageLoadFailed(p,u,e); b.onImageLoadFailed(p,u,e); } }
builder.listener(new Composite()); // registered once

Try / catch

try { builder.listener(l); } catch (IllegalStateException e) { if (!e.getMessage().contains("Listener already set")) throw e; }

Prevention

When it happens

Trigger: Calling builder.listener(...) twice, e.g. a base SDK init installs a listener and app code installs another one for its own error reporting.

Common situations: Layered initialization (framework + app) that both want load-failure callbacks; merging two setup code paths without deduplicating the listener call.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/56c9d7b4a4c306f5. Report an issue: GitHub.