Screen

public abstract class Screen implements LifecycleOwner


A Screen has a Lifecycle and provides the mechanism for the app to send Templates to display when the Screen is visible. Screen instances can also be pushed and popped to and from a Screen stack, which ensures they adhere to the template flow restrictions (see onGetTemplate for more details on template flow).

The Screen class can be used to manage individual units of business logic within a car app. A Screen is closely tied to the CarAppService it is a part of, and cannot be used without it. Though Screen defines its own lifecycle (see getLifecycle), that lifecycle is dependent on its CarAppService: if the car app service is stopped, no screens inside of it can be started; when the car app service is destroyed, all screens will be destroyed.

Screen objects are not thread safe and all calls should be made from the same thread.

Summary

Protected constructors

Screen(@NonNull CarContext carContext)

Public methods

final void

Removes this screen from the stack, which will move its lifecycle state down to DESTROYED.

final @NonNull CarContext

Returns the CarContext of the CarAppService.

final @NonNull Lifecycle

Returns this screen's lifecycle.

@Nullable String

Retrieves the marker that has been set for this screen, or null if one has not been set.

final @NonNull ScreenManager

Returns the ScreenManager to use for pushing/removing screens.

final void

Requests the current template to be invalidated, which eventually triggers a call to onGetTemplate to get the new template to display.

abstract @NonNull Template

Returns the Template to present in the car screen.

void

Updates the marker for this screen.

void

Sets the result that will be sent to the OnScreenResultListener that was given when pushing this screen onto the stack using pushForResult.

Protected constructors

Screen

Added in 1.0.0
protected Screen(@NonNull CarContext carContext)

Public methods

finish

Added in 1.0.0
public final void finish()

Removes this screen from the stack, which will move its lifecycle state down to DESTROYED.

Call when your screen is done and should be removed from the stack.

If this screen is the only one in the stack, it will not be finished.

getCarContext

Added in 1.0.0
public final @NonNull CarContext getCarContext()

Returns the CarContext of the CarAppService.

getLifecycle

Added in 1.0.0
public final @NonNull Lifecycle getLifecycle()

Returns this screen's lifecycle.

Here are some ways you can use a Screen's Lifecycle:

What each Event means for a screen:

ON_CREATE

The screen is in the process of being pushed to the screen stack, it is valid, but contents from it are not yet visible in the car screen. You should get a callback to onGetTemplate at a point after this call. This is where you can make decision on whether this Screen is still relevant, and if you choose to not return a Template from this Screen call finish.

ON_START

The template returned from this screen is visible in the car screen.

ON_RESUME

The user can now interact with the template returned from this screen.

ON_PAUSE

The user can no longer interact with this screen's template.

ON_STOP

The template returned from this screen is no longer visible.

ON_DESTROY

This screen is no longer valid and is removed from the screen stack.

Listeners that are added in ON_START, should be removed in ON_STOP.

Similarly, listeners that are added in ON_CREATE should be removed in ON_DESTROY.

getMarker

Added in 1.0.0
public @Nullable String getMarker()

Retrieves the marker that has been set for this screen, or null if one has not been set.

See also
setMarker

getScreenManager

Added in 1.0.0
public final @NonNull ScreenManager getScreenManager()

Returns the ScreenManager to use for pushing/removing screens.

invalidate

Added in 1.0.0
public final void invalidate()

Requests the current template to be invalidated, which eventually triggers a call to onGetTemplate to get the new template to display.

If the current State of this screen is not at least STARTED, then a call to this method will have no effect.

After the call to invalidate is made, subsequent calls have no effect until the new template is returned by onGetTemplate.

To avoid race conditions with calls to onGetTemplate you should call this method with the main thread.

Throws
androidx.car.app.HostException

if the remote call fails

onGetTemplate

Added in 1.0.0
public abstract @NonNull Template onGetTemplate()

Returns the Template to present in the car screen.

This method is invoked whenever a new template is needed, for example, the first time the screen is created, or when the UI is invalidated through a call to invalidate.

Throttling of UI updates To minimize user distraction while driving, the host will throttle template updates to the car screen. When the app invalidates multiple times in a short period, the host will call this method for each call, but it may not update the actual car screen right away. This will ensure there are not excessive UI changes in a short period of time.

For example, if the app sends the host two or more templates within a period of time shorter than the throttle period, only the last template will be displayed on the car screen.

Template Restrictions The host limits the number of templates to display for a given task to a maximum of 5, of which the last template of the 5 must be one of the following types:

If the 5 template quota is exhausted and the app attempts to send a new template, the host will display an error message to the user before closing the app. Note that this limit applies to the number of templates, and not the number of screen instances in the stack. For example, if while in screen A an app sends 2 templates, and then pushes screen B, it can now send 3 more templates. Alternatively, if each screen is structured to send a single template, then the app can push 5 Screen instances onto the ScreenManager stack.

There are special cases to these restrictions: template refreshes, back and reset operations.

Template Refreshes Certain content updates are not counted towards the template limit. In general, as long as an app returns a template that is of the same type and contains the same main content as the previous template, the new template will not be counted against the quota. For example, updating the toggle state of a row in a androidx.car.app.model.ListTemplate does not count against the quota. See the documentation of individual Template classes to learn more about what types of content updates can be considered a refresh. Back Operations To enable sub-flows within a task, the host detects when an app is popping a Screen from the ScreenManager's stack, and updates the remaining quota based on the number of templates that the app is going backwards by.

For example, if while in screen A, the app sends 2 templates and then pushes screen B and sends 2 more templates, then the app has 1 quota remaining. If the app now pops back to screen A, the host will reset the quota to 3, because the app has gone backwards by 2 templates.

Note that when popping back to a Screen, an app must send a Template that is of the same type as the one last sent by that screen. Sending any other template types would cause an error. However, as long as the type remains the same during a back operation, an app can freely modify the contents of the template without affecting the quota.

Reset Operations Certain Template classes have special semantics that signify the end of a task. For example, the androidx.car.app.navigation.model.NavigationTemplate is a template that is expected to stay on the screen and be refreshed with new turn-by-turn instructions for the user's consumption. Upon reaching one of these templates, the host will reset the template quota, treating that template as if it is the first step of a new task, thus allowing the app to begin a new task. See the documentation of individual Template classes to see which ones trigger a reset on the host.

If the host receives an android.content.Intent to start the car app from a notification action or from the launcher, the quota will also be reset. This mechanism allows an app to begin a new task flow from notifications, and it holds true even if an app is already bound and in the foreground.

See androidx.car.app.notification.CarAppExtender for details on notifications.

setMarker

Added in 1.0.0
public void setMarker(@Nullable String marker)

Updates the marker for this screen.

Set the marker to null to clear it.

This is used for setting a marker to where you can jump back to by calling popTo.

setResult

Added in 1.0.0
public void setResult(@Nullable Object result)

Sets the result that will be sent to the OnScreenResultListener that was given when pushing this screen onto the stack using pushForResult.

Only the final result set will be sent.

The result will be propagated when this screen is being destroyed. This can be due to being removed from the stack or explicitly calling finish.

Parameters
@Nullable Object result

the value to send to the OnScreenResultListener that was given when pushing this screen onto the stack using pushForResult