Blog Post

Introducing Jetpack Compose Support

We here at PSPDFKit have been eagerly following the development of Jetpack Compose and its fast ecosystem adoption and production-level quality. Google has been hard at work, and it shows! Progress since the first beta has been constant, and we already have yet another robust framework to integrate PSPDFKit for Android with.

Unveiling Jetpack Compose support as part of the 8.0 release of our Android PDF SDK was quite the exciting moment. Like Compose itself, our support for the framework is rather initial, but we’re more than happy to be providing built-in APIs for what we believe will be the new default when building new Android applications.

We also felt this was the right time to work on and launch a new and updated Android Catalog, with its UI fully rewritten to use all of the shiny new tech we could get our hands on.

This blog post goes over some of the interesting bits we found while implementing both the new Catalog and internal APIs, in what (I personally hope!) will be the first of many Jetpack Compose-centered posts to come.

In with the New!

Declaratively building interfaces is all the rage these days. From web with React, to iOS with SwiftUI, and now Android with Jetpack Compose, an ever-increasing number of developers is coming into contact with the paradigm shift from older UI and view systems.

These declarative frameworks are (or attempt to be) faster to write, require less code and boilerplate, and read clearer. On Android, Jetpack Compose succeeds in making it so the UI can be written a lot faster than before, and with its expressive APIs coupled with all the best Kotlin has to offer, the end result tends to be much more elegant and readable.

In short, you can now declare your application’s interface through composable functions. Nesting multiple composable functions — each emitting a part of your layout — creates, or rather, composes, your UI. These functions are defined in terms of what they should look like on a given application state, and they’re automatically updated (or recomposed) whenever that state changes.

It sounds and truly is quite simple, but starting off can be a bit confusing, as the way you think about and approach your UI is different than with the usual Android views. With some practice, however, Jetpack Compose starts to feel natural, and your code more straightforward.

Previous Kotlin experience and a deeper understanding of coroutines and the MVVM architecture will leave you feeling right at home, as the framework beautifully integrates Kotlin’s already-intuitive APIs.

Moreover, theming has never been easier. Compose implements Material in an extremely elegant and easy-to-customize way. And the newer APIs for animations are a breeze to use and mold into whatever your imagination or design team cooks up.

And don’t even get me started on how simple lists are to write now! And… and… and…

There’s simply too much to unpack in detail in a single blog post! So, our team’s main takeaway is that Jetpack Compose truly succeeds at what it sets out to achieve: offering a framework for building UIs that are quick and easy to write and maintain.

Fresh APIs

Using PSPDFKit for Android with Jetpack Compose was already possible by starting an activity from inside a composable function. This solution worked fine, but it was far from a Compose-first experience.

Now, with version 8.0 of PSPDFKit for Android, you can use our viewer itself as a composable through DocumentView:

DocumentView(
    documentState = documentState,
    modifier = Modifier.fillMaxSize()
)

Meanwhile, our DocumentState class serves as a central repository for the state, and it can easily be hoisted for use and customization through the rememberDocumentState composable function:

val pdfActivityConfiguration = remember {
    PdfActivityConfiguration
        .Builder(context)
        .setUserInterfaceViewMode(UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_HIDDEN)
        .build()
}

val documentState = rememberDocumentState(
    state.selectedDocumentUri,
    pdfActivityConfiguration
)

Note that all of the new Jetpack Compose internals and APIs are annotated with ExperimentalPSPDFKitApi to, well, denote them as experimental. While these APIs might change in the future, we believe this serves as a great launching point for any additional Compose functionality within the SDK.

This is the first step we’re taking toward Jetpack Compose support, with the long-term intention of creating Compose-first APIs that integrate into and feel as elegant and seamless as the rest of the framework.

For a more detailed and practical view of our Jetpack Compose support, refer to our Opening a PDF in a Jetpack Compose Application blog post.

Catalog Recomposition

Part of our Compose work consisted of a rewrite of our Android Catalog. A recomposition, if you will.

This served both as a way of spreading the Jetpack Compose experience around the team and of us deciding that the Catalog could do with a nice UI revamp:

But don’t worry! All of our examples are still in there as you’d expect. In fact, the majority of the examples are still using the same structure as the old Catalog. For the Compose users out there, there’s also a new example on the use of our new APIs.

Structurally, we went with a simple unidirectional Redux-like approach, where our single CatalogViewModel holds and exposes an immutable version of the central State. This serves as a single source of truth for the state of the whole application, similar to the way our DocumentView works with its DocumentState.

We chose to use coroutine flows for collecting the state in the UI. Any user preferences set are also persisted through the new DataStore API.

The interface itself is quite straightforward, with a custom-made expandable list hosting both the examples and settings on different pages of a master-detail design. Compared to the Android view system, setting up a list with Compose is a breeze! We ended up using a LazyColumn with headers, and it expands or collapses depending on part of our state.

Both pages also feature a search box as a nice extra. And, as this is a rather simple application, no real navigation was needed, and we ended up taking the Jetpack Compose navigation component off the project. Compose is nicely modular like that!

You can check out the code for the Catalog application in our GitHub repository.

Conclusion

The adoption of Jetpack Compose was straightforward, with most of the work to support it being internal, and related to our own build processes and scripts (which might be the topic of a future blog post). For the rewrite itself, though, implementation of the Catalog was fast and simple. This was surprising to me, as someone relatively new to the Android ecosystem!

Of course, it’s not all sunshine and roses. Some APIs are still rough around the edges, and performance in some places leaves a bit to be desired (though it’s been improved a lot since the earlier versions). I also found the preview to not always work as it should, though that experience was not shared by others in the company, so who knows.

Furthermore, writing declarative UI requires something of an approach adjustment if you haven’t worked with it yet. However, as a good developer who can still learn new tricks, once you get past that initial barrier, it’s easy to see some of the niceties Android development has been lacking for a while now. We found using the new and shiny toolkit to be quite the enjoyable experience, and it seems even easier to buy into it as the future of UI in the platform, even for the biggest skeptics among us.

The point is, Jetpack Compose is early in its lifecycle, and some of the issues are definitely expected and will certainly get ironed out, just like many already have since the first alpha versions. So, while the question “Is Jetpack Compose ready for production?” might still have a variety of answers depending on your specific use case, we here at PSPDFKit find it’s already in a rather nice spot, and we’ll be making sure our customers get great support for it if or when they decide to use it too!

Share post
Free trial Ready to get started?
Free trial