Skip to content

A sample app exploring what's possible with Compose on Android

Notifications You must be signed in to change notification settings

tunjid/listingApp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

651923d · Jan 20, 2025
Nov 24, 2024
Nov 18, 2024
Sep 23, 2024
Sep 28, 2024
Nov 24, 2024
Jan 20, 2025
Jan 20, 2025
Sep 23, 2024
Jan 1, 2024
Sep 28, 2024
May 19, 2024
Jan 1, 2024
Jan 1, 2024
Jan 1, 2024
Nov 18, 2024

Repository files navigation

Declarative APIS for declarative UIs

This project outlines how the declarative principles of Compose, especially how its state ownership, production and management semantics provide systemic benefits when extended to the entirety of the UI layer. I also refer to this concept as "x as state".

In particular the following are explored:

The above are used to implement a system design that supports

  • Shared element transitions using a single root LookaheadScope in the NavHost ( see AdaptiveContentHost and SharedElements.kt)
  • Predictive back animations and seeking using an immutable hoisted navigation state that is adapted on a screen configuration basis.
  • Seeding pagination pipelines from navigation arguments.
  • Persistence of navigation state to disk to restore navigation past process death, including after system reboots.

The above provide a system where "first frame readiness" is guaranteed when navigating between navigation destinations, obviating the need for legacy APIs from View such as Activity.postponeEnterTransition() and Activity.startPostponedEnterTransition().

App recordings

Portrait orientation Landscape orientation
photo portrait landscape
video portrait landscape

Screens

There are 4 screens in the app:

  • ListingFeedScreen: Vertical grid. Feed and list in a list-detail canonical layout implementation. Each feed item has a horizontal list of non paginated images.
  • ListingDetailScreen: Detail screen in a canonical list-detail implementation. Has a paginated horizontal list for media displayed.
  • GridGalleryScreen: Grid gallery layout for media, it is paginated.
  • PagerGalleryScreen: Full screen paged gallery layout for media, it is paginated. Also implements drag to dismiss with Modifier.Node.

All screens have the same state declaration:

@Composable
fun FeatureScreen(
    modifier: Modifier = Modifier,
    state: State,
    actions: (Action) -> Unit,
)

Where State is an immutable data class, however a class backed by compose state is as effective. actions is an event sink commonly used by MVI frameworks and is a stable Compose parameter.

Routing to the screen is defined higher up using remember retained semantics scoped to navigation:

    @Composable
     fun FeatureRoute() {
        val stateHolder = rememberRetainedStateHolder<ListingDetailStateHolder>(
            route = this@FeatureRoute
        )
        FeatureScreen(
            modifier = Modifier.backPreviewBackgroundModifier(),
            state = stateHolder.state.collectAsStateWithLifecycle().value,
            actions = stateHolder.accept
        )
    }

Here, based on navigation and UI state including predictive back progress, the FeatureScreen can be Composed.

About

A sample app exploring what's possible with Compose on Android

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages