SkillAgentSearch skills...

Jetmagic

A framework for building responsive Android apps using Jetpack Compose

Install / Use

/learn @DrifterAtSea/Jetmagic
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img src="../../blob/main/images/jetmagic-840x500.jpg" width="840" height="500" /> </p>

Jetmagic - A framework for building responsive Android apps using Jetpack Compose

Jetmagic is an Android framework that can be used to develop responsive Android apps that are built using Jetpack Compose. It provides features beyond those offered by Android's own Jetpack Compose framework. Jetmagic's primary purpose is to provide infrastructure needed to manage composables while letting you focus on building your app's core business objective. The framework consists of the following components:<br /><br />

  • Navigation Manager: A replacement for Android's standard Jetpack Compose navigation API. It supports animated navigation and the ability to pass objects between screens/composables. It also supports caching screens.

  • Composable Resource Manager (CRM): Provides support for responsive layouts allowing apps to easily switch "layouts" in a way similar to how alternate xml layouts are selected based on the device configuration using qualifiers such as language/region, device orientation, screen size, screen density, etc. Instead of xml resource layouts, the CRM manages composable resources. Useful for apps that need to run on multiple devices including phones/tablets/TVs. Built-in support for managing viewmodels for each composable.

  • Image Manager: Manages composable images. Currently this component provides better support for images that use animations/transitions than the standard Image composable.

  • Deep Linking: Provides support for deep links. Jetmagic allows external URIs to launch one or more screens while integrating wth the CRM to provide the correct layout based on the current system configuration. Jetmagic's deep linking supports multiple paths for any screen, regular expressions in paths, the ability to intercept, alter or terminate the navigation as Jetmagic navigates towards the target screen. It is also possible to hide all the launched screens (in a multi-screen deep link) except the target screen allowing developers to preprocess any data before navigating to the next successive screen.

<br />

The Github project contains a fully functional app that demonstrates each API. For a detailed overview of the framework and a step-by-step guide on creating a minimal responsive app, see:

https://johannblake.medium.com/creating-responsive-layouts-using-jetpack-compose-7746ba42666c

Add the following dependencies to your app's build.gradle file:

implementation 'io.github.johannrosenberg:jetmagic:1.5.1'
<br />

Jetmagic Architecture

<p align="center"> <img src="../../blob/main/images/jetmagic-architecture.png" width="700" height="638" /> </p> <br />

Jetmagic treats your composables like resources in a similar way that Android treats xml-based layout resources under the older view-based system. Under the older system, Android detects the device configuration and any changes to the device such as an orientation change and then selects the xml resource layout that would apply to the configuration settings.

Using Jetmagic, you tell the Composable Resource Manager (CRM) which composables you want to use as "layouts". You do this by creating an instance of a ComposableResource and set properties in the constructor that indicate the configuration settings you want associated with your composable such as orientation, screen size, screen density, etc. You also provide a callback that will get called if the resource is selected. In the callback, you simply make a call to the composable function that you want to use to render the UI.

When your app starts up, it will normally call on the Navigation Manager to navigate to the start sceen (a.k.a, the home screen). This call is made by indicating the resource you want to display. The Navigation Manager will then call the CRM which will then go through the list of composable resources that have been set up and find the one that the Navigation Manager has requested to navigate to. There could be more than one resource available and each of them is specific to some device configuration setting (or may act as a default with no configuration settings). Using the same algorithm that Android uses when selecting xml resources - through a process of elimination - it will end up with one resource that best matches the device configurations. It then creates an instance of a ComposableInstance class which will be used to contain state data about the composable that can be used during the time it is displayed on the screen. It returns this composable instance to the Navigation Manager, which then pushes it on top of its navigation stack, making it the current screen on the stack.

The Navigation Manager, through the use of LiveData, then triggers the Screen Factory to perform an update. The Screen Factory acts like a container for all the screens. It is not actually a container such as a Surface, Box, Column, etc. It is however a composable and you would normally include the Screen Factory as one of your top most composables within your screen hierarchy. This means that you can place a Screen Factory inside something like Surface, Box, or the content section of a Scaffold. Any composables that the Screen Factory renders will be placed inside your own container.

When the Screen Factory is either composed/recomposed including when the Navigation Manager triggers an update, the Screen Factory will then access all the composable instances on the navigation stack. Each composable instance effectively represents a screen. It then iterates through the list of these composable instances and invokes the RenderComposable property that each composable instance has. As part of the process of rendering the composable, the onRender property - which is a property of a composable resource - will be called, causing the composable associated with the resource to render itself. Any animations that are assigned to the resource will also be executed when the composable is rendered.

Navigating to another screen is done by either calling on the Navigation Manager or the CRM. If you know that a screen does not have any alternate resources but will always be displayed the same regardless of what the device configuration settings are, you can use the Navigation Manager. You also use the Navigation Manager if you want to go back to the previous screen or directly to the home screen. To use the CRM for navigation, consider the case where you have list of cats (as in the demo app) that are shown when the device is in portrait mode and clicking on an item takes you to another screen to show the cat details. But if you are on the list screen and rotate the device to be in landscape mode, you might decide to show both the list and the details side-by-side, as there is enough space for this. In landscape mode, when you click on the list item, the details pane will update - no navigation to another screen is performed. In this example, you don't want to be concerned with whether you are peforming a navigation or an update. You would just call the CRM's updateOrNavigateTo function and let it figure it out and make the correct choice. If the CRM determines that the details screen is not on the same screen that is displaying the list, it will call on the Navigation Manager to navigate to a new screen to show the details.

If configuration change occurs while the app is running, the activity's onDestroy is called and a call is made to the CRM informing it that a configuration change has occurred. The CRM will obtain all the composable instances from the Navigation Manager and set their recourceId to null. The resourceId is used to identify which composable resource was used to render the composable. Although the activity has been destroyed, the Navigation Manager and the CRM both retain the state of all the composable resources and composable instances. When the activity is restarted after onDestroy, the Screen Factory will be rendered again and will proceed to render the composable instances as it normally does. However, when it calls RenderComposable for each composable instance, the CRM will notice that the resourceId is set to null, indicating that it may need to select a new resource to render the composable. Because the composable instance is separate from the composable resource, the CRM and the Navigation Manager are able to retain the state of the composable instance even when a new resource is selected. This state includes any optional viewmodel that you want associated with the composable.

<br /><br />

Using the Demo App

Before setting up and working with Jetmagic's API, it is helpful to try out the demo app to see what Jetmagic is capable of. The following tests demonstrate the more important features although Jetmagic has more capabilities than are currently available in the demo app:

| Features | Test

Related Skills

View on GitHub
GitHub Stars188
CategoryDevelopment
Updated1mo ago
Forks12

Languages

Kotlin

Security Score

85/100

Audited on Feb 14, 2026

No findings