JessYanCoding/AndroidAutoSize · error · java.lang.IllegalStateException
Not in applications main thread
Error message
Not in applications main thread
What it means
AutoSize throws this IllegalStateException from Preconditions.checkMainThread() when an API that must run on Android's main (UI) thread is invoked from a background thread. Android view/window measurement and UI sizing operations are not thread-safe, so the library enforces main-thread execution defensively. It is a fail-fast guard, not a recoverable failure.
Solutions
- Move the AutoSize call to the main thread: wrap it in Activity.runOnUiThread(...) or post it to the main Handler.
- With coroutines, call it inside withContext(Dispatchers.Main) { ... }.
- With RxJava, use observeOn(AndroidSchedulers.mainThread()) before invoking the API.
- If the call originates in a library callback, verify which thread the callback delivers on and hop threads there.
Example fix
// before
executor.execute(() -> AutoSize.autoConvertDensityOfGlobalConfig(activity));
// after
new Handler(Looper.getMainLooper()).post(() ->
AutoSize.autoConvertDensityOfGlobalConfig(activity)); Defensive patterns
Strategy: try-catch
Validate before calling
public static boolean isMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
// call site:
if (isMainThread()) AutoSize.autoConvertDensityOfGlobalConfig(activity);
else new Handler(Looper.getMainLooper()).post(() -> AutoSize.autoConvertDensityOfGlobalConfig(activity)); Type guard
public static void runOnMain(Runnable r) {
if (Looper.myLooper() == Looper.getMainLooper()) r.run();
else new Handler(Looper.getMainLooper()).post(r);
} Try / catch
try {
Preconditions.checkMainThreadGuarded(); // or the AutoSize call directly
AutoSize.autoConvertDensityOfGlobalConfig(activity);
} catch (IllegalStateException e) {
Log.w("AutoSize", "wrong thread, reposting to main", e);
new Handler(Looper.getMainLooper()).post(() -> AutoSize.autoConvertDensityOfGlobalConfig(activity));
} Prevention
- Always invoke AutoSize APIs from Activity/Fragment lifecycle methods or view callbacks, which run on the main thread.
- Centralize sizing logic in one helper that hops to the main thread internally.
- In coroutines use withContext(Dispatchers.Main); in RxJava use observeOn(AndroidSchedulers.mainThread()).
- Add a debug-mode thread assertion around your sizing helper to catch regressions early.
When it happens
Trigger: Calling an AutoSize API (e.g. init/autoSizeDensity related entry points that route through checkMainThread) from a worker thread, HandlerThread, RxJava/Coroutine IO dispatcher, or AsyncTask.doInBackground instead of the main looper.
Common situations: Developers hooking AutoSize into async code paths: adapting density after a network-driven layout change inside a coroutine on Dispatchers.IO, calling sizing helpers in a background-initialized SDK, or an Activity not yet on the main thread during exotic initialization.
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
- you can't instantiate me!
- you can't instantiate me!
- you can't instantiate me!
- you should init first
- negative size:
AI-assisted analysis of JessYanCoding/AndroidAutoSize@e402ecdd99 (2026-09-07).
Data as JSON: /api/errors/f4b18f956a5cd861.
Report an issue: GitHub.
Appendix: source
Thrown at autosize/src/main/java/me/jessyan/autosize/utils/Preconditions.java:113
}
public static int checkElementIndex(int index, int size, String desc) {
if (index >= 0 && index < size) {
return index;
} else {
throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
}
}
/**
* Throws {@link IllegalStateException} if the calling thread is not the application's main
* thread.
*
* @throws IllegalStateException If the calling thread is not the application's main thread.
*/
public static void checkMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("Not in applications main thread");
}
}
private static String badElementIndex(int index, int size, String desc) {
if (index < 0) {
return format("%s (%s) must not be negative", new Object[]{desc, Integer.valueOf(index)});
} else if (size < 0) {
throw new IllegalArgumentException((new StringBuilder(26)).append("negative size: ").append(size).toString());
} else {
return format("%s (%s) must be less than size (%s)", new Object[]{desc, Integer.valueOf(index), Integer.valueOf(size)});
}
}
public static int checkPositionIndex(int index, int size) {
return checkPositionIndex(index, size, "index");
}
public static int checkPositionIndex(int index, int size, String desc) {View on GitHub (pinned to e402ecdd99)