RepoPilot

How do their APIs compare?

About jakewharton/butterknife · 2 messages · last activity 9/8/2026

Question

How do their APIs compare?

RepoPilot

Here's a comparison of the two libraries' APIs, drawn from what's in the repository data.

jakewharton/butterknife — Annotation-driven binding API

Butter Knife's public surface is almost entirely annotations processed at compile time, not a runtime API you call step-by-step. The pattern is:

  • Field binding: @BindView(R.id.foo) on a field, resolved via generated code rather than reflection at runtime (only one Class.forName lookup remains historically, per [CHANGELOG.md:L270-L274]).
  • Method binding for listeners: annotations like @OnClick, @OnPageChange map directly onto Android callback interfaces. For example, @OnPageChange exposes an inner Callback enum (PAGE_SELECTED, PAGE_SCROLLED, PAGE_SCROLL_STATE_CHANGED) where each constant is tied via @ListenerMethod to a specific interface method name/parameter signature [butterknife-annotations/src/main/java/butterknife/OnPageChange.java:L47-L74]. This is a declarative mapping — you pick a Callback value and Butter Knife's annotation processor generates the actual listener implementation.
  • Resource binding: @BindString, @BindBool, @BindColor, @BindDimen, @BindDrawable, @BindInt, @BindArray, @BindBitmap, @BindFont — these bind Android resources directly to fields, no getResources() calls needed by the user (see version history in [CHANGELOG.md:L281-L295], [CHANGELOG.md:L246-L256]).
  • Lifecycle API: a single entry point, ButterKnife.bind(this), returns an Unbinder (introduced in 8.0.0) so you can null out references later — this replaced the old inject/unbind pair from 7.0.0 [CHANGELOG.md:L246-L285].
  • Grouping: multiple views can be grouped into a List/array and manipulated via Action, Setter, or Android Property through ButterKnife.apply (later moved to ViewCollections) [CHANGELOG.md:L351-L360], [CHANGELOG.md:L71-L82].
  • Codegen internals: under the hood, BindingSet in the compiler builds the generated unbind/bind methods, handling null-checks, listener removal, and field naming — e.g. asHumanDescription builds human-readable error messages listing bound elements [butterknife-compiler/src/main/java/butterknife/compiler/BindingSet.java:L565-L584], and bestGuess maps primitive/type strings to TypeName for codegen [butterknife-compiler/src/main/java/butterknife/compiler/BindingSet.java:L585-L601].

So Butter Knife's "API" is best understood as annotations + one bind call + generated unbind call, with almost no imperative control flow exposed to the caller.

lingochamp/filedownloader — Imperative, service-oriented download API

FileDownloader's API is a much more traditional method-call-driven, stateful engine API centered on the FileDownloader singleton and task builders:

  • Engine control methods: things like stopForeground(boolean) [library/src/main/java/com/liulishuo/filedownloader/FileDownloader.java:L606-L608] and setMaxNetworkThreadCount(int) [FileDownloader.java:L671-L685], which directly mutate engine-wide state and can fail with warnings if tasks are active.
  • Deprecated completion-marking API: setTaskCompleted(String url, String path, long totalBytes) and its bulk overload setTaskCompleted(List<FileDownloadTaskAtom>) let callers tell the engine a file was already downloaded outside the library — both are now no-ops that just log a warning, since the DB-based completion tracking was removed in 0.3.3+ [FileDownloader.java:L606-L645], [FileDownloader.java:L646-L669].
  • Async binding lifecycle: methods like insureServiceBind(), insureServiceBindAsync(), and bindService(Runnable) manage the download service's startup before dependent calls execute [CHANGELOG-ZH.md:L474-L484].
  • **Pluggable components

Want to ask your own question?

Open chat for jakewharton/butterknife

Public Q&A. Generated by RepoPilot from the actual source of jakewharton/butterknife. AI answers can be incomplete or stale — verify before relying on them.