In order to take the experience of using Jetpack Compose to a higher level, and to understand everyone's content needs for Compose development and learning, we sincerely invite you to participate in the Jetpack Compose usage survey. Click here to participate in the survey immediately.
By Andrew Flynn and Jon Boekenoogen, Technical Leads at Google Play
In 2020, the management of the Google Play Store development team made a major decision: revamp the entire Play Store technology stack. Because the existing code is more than 10 years old, there is a huge technical debt in the process of countless Android platform version releases and feature updates. We needed new frameworks that could support hundreds of engineers working simultaneously without compromising developer productivity, user experience, or the performance of the Play Store itself .
We have a long-term roadmap for this, updating everything in the store from the network layer all the way down to pixel rendering. Amongst this, we also wanted to adopt a modern declarative interface framework to achieve our product goals around interactivity and user satisfaction. After analyzing various options, we made a (at the time) bold decision to use Jetpack Compose , which was still in Alpha preview at the time.
Since then, the Google Play Store has worked closely with the Jetpack Compose team to publish and refine a version of Jetpack Compose that meets our specific needs. This article will walk you through our migration approach, the challenges and benefits identified along the way, and share some insights into choosing Compose for applications with many contributors.
priority
When we use Jetpack Compose for the new UI rendering layer, we need to prioritize the following two points:
- Developer Productivity: The Play Store team has hundreds of engineers improving the code, so it should be easy (and fun) to develop.
- Performance : The Play Store renders a lot of media-intensive content, where many business metrics are sensitive to latency and stuttering, so we needed to make sure it performed well on all devices, especially low-memory hardware and Android (Go version) devices.
Developer productivity
We've been writing user interface code with Jetpack Compose for over a year now , and thanks to Jetpack Compose, it makes UI development easier.
We tend to write interfaces with less code, sometimes 50% less . This improvement is achieved thanks to Compose, a declarative interface framework that takes advantage of the simplicity of Kotlin. Custom drawing and layout are now simple function calls instead of overriding various view subclasses.
Take the scoring table as an example:
Written using a view class, this table contains:
- A total of 3 view classes, 2 of which require custom drawing of rounded rectangles and stars
- ~350 lines of Java code, 55 lines of XML
Written in Compose, this table contains:
- All @Composable functions included in the same file and language!
- ~210 lines of Kotlin code
animation
Animation is a much-lauded feature of Compose for its simplicity and expressiveness. Our team is using Compose to build motion features that greatly improve Play Store user satisfaction. Writing sequential or parallel animations has never been easier with Compose's declarative and animation APIs. Our team no longer has to worry about all the corner cases regarding animation cancellations and callback chains. Lottie is a popular animation library that already provides an easy-to-use Compose API.
You can learn more about building animations with Compose by watching the " Animation Becomes Compose's Acclaimed Feature " video.
Now you might be thinking: this all sounds great, but what about library dependencies that provide views? It's true that not all library developers implement Compose-based APIs, especially when we first migrated. However, Compose provides simple view interoperability through its ComposeView and AndroidView APIs. We have successfully integrated with popular libraries like ExoPlayer and YouTube Player in this way.
performance
The Play Store and the Jetpack Compose team work closely together to ensure Compose runs as fast as the view framework without hiccups. This is a daunting task due to the need to package Compose in an application (rather than as part of the Android framework). Rendering a single UI component to the screen is fast, but the end-to-end time to load the entire Compose framework into application memory is long.
One of the biggest performance improvements with Compose for the Play Store came from the development of benchmark profiles . Whilecloud profiles have been out for a while to help improve app startup times, they only work with API 28+ and don't work well for apps with a frequent (weekly) update cadence. To address this, the Play Store and the Android team have collaborated to develop Baseline Profiles: developer-predefined, packaged, application-specifiable profiles, provided with your app, that are completely identical to cloud profiles Compatible and can be defined at the specific application level and at the library level (developers who adapt Compose can use this feature for free!). By rolling out a benchmark profile, the Play Store saw a 40% reduction in initial page render time for its search results pages. This is huge progress!
Reusing UI components is the core mechanism that makes Compose great at rendering, especially when scrolling. Compose will skip reorganization of composables that are known to be skippable when possible (e.g. they are immutable), but developers can also force composables to be skippable if all parameters meet @Stable annotation requirements pass. The Compose compiler also provides a handy guide on how to prevent certain functions from being skipped. When creating a large number of reused UI components in the Play Store that are frequently used in scrolling situations, we have found that unnecessary reorganization increases lost frame times, resulting in stuttering. We built a Modifier to easily spot these reorganizations in our debug setup. By applying these techniques to our interface components, we were able to reduce stuttering by 10-15% .
△ Recombination visualization modifiers in practice (Modifiers) blue (no recombination), green (1 recombination)
Another key to optimizing Compose for Play Store apps is to develop a detailed end-to-end migration strategy for the entire app . During our initial integration experiments, we encountered a dual-stack problem: running Compose and view class rendering concurrently in a single user session was very memory-intensive, especially on low-end devices. This happens when the code is running on the same page, and it also happens when two different pages (for example, the Play Store home page and the search results page) are each on different stacks. To improve this startup delay, it is important that we have a specific plan for the order and timing of page migrations to Compose . At the same time, we found that it is helpful to improve memory performance by "warming up" some common classes before the application migrates to fully use Compose for rendering.
Separating Compose from the Android framework reduces the overhead for our team to contribute directly to Jetpack Compose, resulting in improved turnaround times for the benefit of all developers. We worked with the Jetpack Compose team to roll out features like the LazyList item type cache and quickly make lightweight fixes like extra object allocations .
Looking to the future
Adopting Compose on the Play Store has increased the happiness of our team of developers and has greatly improved code quality and health . All of the new Play Store features are built on this framework, and Compose helps enable faster and smoother access for apps . Due to the nature of our Compose migration strategy, we can't accurately measure APK size changes or build speeds, etc., but all the signs we're seeing are very positive!
Compose is the future of Android interface development, and has helped further refine the Play Store. You are welcome to keep following us for the latest content.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。