didi/DoKit · error · IllegalStateException

Already explicitly declared as no placeholder.

Error message

Already explicitly declared as no placeholder.

What it means

Thrown by RequestCreator.placeholder(int) when the creator was already switched to no-placeholder mode via noPlaceholder(). noPlaceholder() is an explicit opt-out of placeholder behavior, so subsequently setting a placeholder resource is rejected to catch the contradiction.

Source

Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/RequestCreator.java:110

    public RequestCreator noPlaceholder() {
        if (placeholderResId != 0) {
            throw new IllegalStateException("Placeholder resource already set.");
        }
        if (placeholderDrawable != null) {
            throw new IllegalStateException("Placeholder image already set.");
        }
        setPlaceholder = false;
        return this;
    }

    /**
     * A placeholder drawable to be used while the image is being loaded. If the requested image is
     * not immediately available in the memory cache then this resource will be set on the target
     * {@link ImageView}.
     */
    public RequestCreator placeholder(int placeholderResId) {
        if (!setPlaceholder) {
            throw new IllegalStateException("Already explicitly declared as no placeholder.");
        }
        if (placeholderResId == 0) {
            throw new IllegalArgumentException("Placeholder image resource invalid.");
        }
        if (placeholderDrawable != null) {
            throw new IllegalStateException("Placeholder image already set.");
        }
        this.placeholderResId = placeholderResId;
        return this;
    }

    /**
     * A placeholder drawable to be used while the image is being loaded. If the requested image is
     * not immediately available in the memory cache then this resource will be set on the target
     * {@link ImageView}.
     * <p>
     * If you are not using a placeholder image but want to clear an existing image (such as when
     * used in an {@link android.widget.Adapter adapter}), pass in {@code null}.

View on GitHub (pinned to 626827cddb)

Solutions

  1. Decide placeholder behavior once per request; remove either noPlaceholder() or placeholder(...).
  2. Parameterize your loader helper so the placeholder decision is made in a single if/else.
  3. Do not blanket-apply noPlaceholder() in base helpers — leave the choice to call sites.

Example fix

// before
RequestCreator c = defaultCreator(url).noPlaceholder();
c.placeholder(R.drawable.ph); // throws

// after
RequestCreator c = defaultCreator(url);
if (usePlaceholder) c.placeholder(R.drawable.ph); else c.noPlaceholder();
Defensive patterns

Strategy: validation

Validate before calling

RequestCreator c = picasso.load(url);
if (!useNoPlaceholder) c.placeholder(R.drawable.ph);

Prevention

When it happens

Trigger: Chaining .noPlaceholder().placeholder(R.drawable.ph) on the same RequestCreator.

Common situations: Shared code calling noPlaceholder() defensively, then call-site code adding a placeholder; merging two code paths during refactoring; adapting adapter-view code (where noPlaceholder is common) into a context that wants a placeholder.

Related errors


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