# facebook/litho: declarative Android UI with asynchronous layout

> Litho defines UI as immutable component trees, measures them off the UI thread and flattens the view hierarchy. It is a framework for Android teams with a performance budget, not a drop-in replacement for XML layouts.

**facebook/litho** — A declarative framework for building efficient UIs on Android.

- Repository: https://github.com/facebook/litho
- Website: https://fblitho.com
- Stars: 7,800 · Forks: 769
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/facebook-litho

## The Android problem Litho was written to solve

Android's stock toolkit asks you to inflate XML into a tree of View and ViewGroup objects, then measure and lay that tree out on the main thread. For a settings screen this is fine. For a scrolling feed with hundreds of rows, measurement and layout compete with the frame deadline, and deep nesting multiplies the cost. Litho's answer is to stop treating the view tree as the source of truth. You describe a component from immutable inputs, and the framework decides what to measure, when to measure it, and how much of a real View hierarchy to keep. The README frames this as three properties: declarative components, asynchronous layout, and view flattening through Yoga. The audience is Android engineers working on surfaces where scroll smoothness is a product requirement, and who are willing to learn a component model rather than write more XML.

## Components, Yoga layout and why the view count drops

A Litho component is built from a ComponentContext plus a set of props, as the README's Text example shows: Text.create(c).text("Hello World").textSizeDip(50).build(). That object is a description, not a widget. The framework uses Yoga, a layout engine, to compute positions, and the README states that it automatically reduces the number of ViewGroups the UI contains. This is the mechanism behind the flattening claim: intermediate containers that exist only to arrange children do not need to become ViewGroups, because Yoga already knows where the children go. Measurement and layout can run ahead of the UI thread, so by the time a frame is drawn much of the arithmetic is done. The second consequence is recycling. The README says any component, text or image, can be recycled and reused anywhere in the UI, which is a finer unit than a RecyclerView row. A row is recycled as a whole; a Litho text or image component can be reused across different rows. That granularity is the interesting part of the design, and it is also what makes the component tree immutable: if props do not change, the mounted output can be reused.

## Installing Litho and rendering a first component

The README states that Litho can be integrated into Gradle or Buck projects and points to the Getting Started guide at fblitho.com for installation instructions, so the exact dependency coordinates belong to that guide rather than the README. What the README does give is the runtime prerequisite and a minimal screen. First, SoLoader must be initialized in your Application class, otherwise the native layout library will not load:

```java
public class SampleApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, false);
  }
}
```

With that in place, an Activity can build a component and hand it to a LithoView, which is what setContentView receives:

```java
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final ComponentContext c = new ComponentContext(this);

    final Component component = Text.create(c)
        .text("Hello World")
        .textSizeDip(50)
        .build();

    setContentView(LithoView.create(c, component));
}
```

What you should see is a single text label at 50dp, rendered without a TextView in your own layout XML. The repository also ships a sample app. The README gives two ways to build and run it on an attached device or emulator, one for Buck and one for Gradle:

```bash
$ buck fetch sample
$ buck install -r sample
```

```bash
$ ./gradlew :sample:installDebug
```

If either path fails, the failure is in your toolchain setup, not in the component code above, because the sample is the reference configuration the project maintains.

## Where Litho stops being the right tool

The cost of Litho is that your UI is no longer ordinary Android. Components are immutable descriptions, so state that changes has to flow through props and the framework's update path rather than through a mutable view field. Teams used to findViewById and direct mutation will find the debugging story different: what you inspect at runtime is mounted output derived from a component tree, not the tree you wrote. The README also makes the build story explicit. Integration is described for Gradle or Buck, and the repository carries both build.gradle and BUCK files, plus a litho-compiler-plugin and litho-processor directory. That means annotation processing and a build-tooling surface are part of adoption. For a small app with a dozen static screens, this is a large amount of machinery for a layout problem that ConstraintLayout and a RecyclerView already solve. Litho's advantages show up at scale, in long lists and repeated elements; below that scale you are paying the learning and build cost without collecting the benefit. The README does not document rollback or a migration path away from Litho, so treat the decision as one you would reverse by rewriting screens.

## Litho against Jetpack Compose

The obvious comparison is Jetpack Compose, and the difference is in where the work happens. Compose is also declarative and also avoids hand-written XML, but its runtime is built around recomposition of composable functions driven by snapshot state. Litho's model is a component built from immutable props, with Yoga computing layout and the framework flattening the resulting view hierarchy. The README's asynchronous layout claim is the sharpest distinction: Litho measures and lays out ahead of time without blocking the UI thread, which is a layout-scheduling property rather than a rendering-model property. Compose's advantage is that it is the direction Google's Android toolkit has moved, so documentation, tooling and hiring all point that way. Litho's advantage is maturity on exactly the problem it was built for, plus a sample app and a test surface that the repository layout shows in litho-espresso, litho-screenshot and litho-instrumentation-tests. Neither is a drop-in for the other; switching either way is a rewrite of the screens involved.

## Release cadence, maintenance and the Apache-2.0 terms

The release history is uneven. v0.49.1 is dated 2024-03-14, v0.49.0 is dated 2024-02-02, and the release before that, v0.47.0, is dated 2023-02-15. The last push to the repository was on 2026-09-21, so work continues even though the published version numbers have not moved since early 2024. That gap matters for planning: if you adopt Litho, you should expect to pin a version and read the CHANGELOG.md in the repository rather than assume frequent releases. The repository is not archived. On licensing, Litho is Apache-2.0, which permits commercial use and modification, and the repository ships a THIRD_PARTY_NOTICES.txt alongside the LICENSE file. Apache-2.0 also includes a patent grant and requires that notices be preserved; if you redistribute a modified build, read the LICENSE and the third-party notices rather than assuming the terms are identical to a permissive licence without those clauses. This is a description of the files present, not legal advice.

## Conclusion

Adopt Litho if you are building a feed-like Android surface where off-thread measurement and view flattening are worth rewriting screens as immutable components; skip it if your UI is a handful of static screens that ConstraintLayout already handles. Before committing, verify that your Gradle or Buck setup matches the getting-started guide, that SoLoader.init is called in your Application class, and that the version of litho-core you resolve is one you are prepared to pin.

## FAQ

### How do you install facebook/litho in an Android project?

The README says Litho can be integrated either in Gradle or Buck projects and directs you to the Getting Started guide at fblitho.com for the installation instructions. The repository itself carries both build.gradle and BUCK files, and the sample app shows a working configuration for each.

### What problem does facebook/litho solve on Android?

It lets you define UI declaratively from immutable inputs, measures and lays out ahead of time without blocking the UI thread, and uses Yoga to reduce the number of ViewGroups in the UI. It also recycles individual components such as text or images anywhere in the UI.

### Does facebook/litho require any initialization at startup?

Yes. The README's quick start initializes SoLoader in the Application class with SoLoader.init(this, false) inside onCreate, before any component is created.

### How do you run the facebook/litho sample app?

The README gives two options for an attached device or emulator: buck fetch sample followed by buck install -r sample, or ./gradlew :sample:installDebug. The sample sources live under sample/ in the repository.

### Is facebook/litho actively maintained?

The repository is not archived and its last push was on 2026-09-21, but the most recent published release, v0.49.1, is dated 2024-03-14. The version numbers have been stable since then, so check CHANGELOG.md for what has landed since.

## Sources

- [facebook/litho on GitHub](https://github.com/facebook/litho)
- [License: Apache-2.0](https://github.com/facebook/litho/blob/master/LICENSE)
- [Project website](https://fblitho.com)
- [README](https://github.com/facebook/litho/blob/master/README.md)
- [Releases](https://github.com/facebook/litho/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/facebook-litho
