Optimizing Roku UI: Tips and Tricks

Amitdogra
5 min readJan 25, 2024

--

🚀 Master Roku App Development: Your Ultimate Guide to Success with below Tips and Tricks! Elevate Your Skills, Ignite Your Creativity🌟

1. Rule of Thirds

Understanding UI Resolutions:

Roku devices support various resolutions, but for simplicity, we’ll concentrate on FHD and HD. While explicit layouts can be provided for both, a common and efficient approach is to provide only the FHD layout and let Roku automatically handle downscaling for HD.

To achieve this, add the following line to your manifest file:

ui_resolutions=FHD

Now, you can use a 1920x1080 grid for specifying UI dimensions, and Roku will handle the conversion to HD automatically.

Dealing with Rounding Issues:

When using the autoscaling approach, it’s crucial to be mindful of rounding issues. Since all dimensions are essentially multiplied by 2/3 for downscaling, the original dimensions must be divisible by 3 to avoid problems.

Example:

Consider a 3x3 grid where each square is 199x199. While the overall grid is 597x597 (divisible by 3), individual squares cause white lines due to 199 not being divisible by 3.

+----------------------+----------------------+----------------------+
| [199x199] | [199x199] | [199x199] |
| | | |
| | | |
| | | |
+----------------------+----------------------+----------------------+
| [199x199] | [199x199] | [199x199] |
| | | |
| | | |
| | | |
+----------------------+----------------------+----------------------+
| [199x199] | [199x199] | [199x199] |
| | | |
| | | |
| | | |
+----------------------+----------------------+----------------------+

Adjusted Layout (Ensuring Divisibility by 3):

+----------------------+----------------------+----------------------+
| [201x201] | [201x201] | [201x201] |
| | | |
| | | |
| | | |
+----------------------+----------------------+----------------------+
| [201x201] | [201x201] | [201x201] |
| | | |
| | | |
| | | |
+----------------------+----------------------+----------------------+
| [201x201] | [201x201] | [201x201] |
| | | |
| | | |
| | | |
+----------------------+----------------------+----------------------+

In the adjusted layout, each square is now 201x201, ensuring divisibility by 3. This resolves the issue of white lines and ensures a proper fit within the 597x597 overall grid when autoscaled for HD resolutions.

2. Poster component order

Loading images from the web introduces a common challenge — the lack of control over source image sizes. Oversized images can become a memory burden, impacting the overall performance of your Roku app. To address this, we turn our attention to the Poster component and its ability to dynamically resize incoming images.

The Roku docs highlight three crucial properties that play a pivotal role in controlling how images are loaded into memory:

  • loadWith
  • loadHeight
  • loadDisplayMode

By judiciously utilizing these properties, developers can load images that might be too large while consuming memory only as required for the desired final size. A practical example showcases the use of these properties:

<Poster uri="http://big.image" loadDisplayMode="scaleToZoom" loadWidth="720" loadHeight="405" />

The Importance of Property Source Order

An interesting quirk comes to light — the order in which properties are set matters.

The Roku docs emphasize that the load scaling options must be set before the uri field for them to take effect.

Adjusting the markup to ensure that the uri is set after the other properties is crucial for effective image resizing:

<Poster loadDisplayMode="scaleToZoom" loadWidth="720" loadHeight="405" uri="http://big.image" />

3. Component initialization order

Instances of components defined in an XML file follow a well-defined initialization order when they are created.

The <children> element nodes defined in XML markup are created, and their fields are set to their initial values, either to a default value, or to the value specified in the XML markup.

The <interface> element fields of the XML component are created, and their initial values are set, either to a default value, or to the value specified by the value attribute.

The <script> element init() function is called, and all initializations contained in the function are performed.

Note the following implications of this initialization order.

Observer Functions

Observer functions of fields that are set up in the init() function do not get called when those fields are initialized. This is because the initialization of interface fields, or of fields of the component <children> element nodes, is done before the init() function that sets up the observers is called. Thus, in some cases, it may be necessary to explicitly call the field observer functions in init() if they need to be executed for the initial field setting.

Also note that field observer callback functions set up in init() cannot be guaranteed to have returned when the component is created using createObject() or createChild(). This means that a component object may not have been completely constructed immediately after those calls.

Parenting and the Focus Chain

For nodes that are defined in the <children> XML markup of the component file, the parent node is set after the node is created, and init() is called.

This has implications for the focus chain (see Remote Control Events), which must end at a node derived from Scene. Until the newly-created node is parented to a node that is either derived from Scene, or parented to a node in a focus chain that ends on a node derived from Scene, you will not be able to set remote control focus on the node.

Program Action Fields

Certain fields should not be set in XML markup of the SceneGraph nodes, specifically any control fields that initiate a program action, such as starting a video to play, or an animation.

These fields should be set in BrightScript as part of scripting the program flow of the component.

4. Reducing Rendezvous occurrence

A Rendezvous issue occurs when a Task thread attempts to access (read/write) a property of a Render thread object. When a Rendezvous issue occurs, it is placed in a system queue and will be resolved in the next device rendering cycle. If there are numerous Rendezvous issues in the same cycle, it can cause delays in rendering, resulting in the app being less responsive to user input.

Another issue with Roku is that there is no direct way for two Task threads to communicate with each other. Communication must go through a Render thread before reaching the target Task thread. Therefore, communication between two Task threads usually results in double the number of Rendezvous compared to communication between a Task thread and the Render thread.

Read more about roku threads here.

5. High performance Task component

The Task component has been frequently misused by many developers due to the lack of information from Roku documentation. It should not be used as an asynchronous thread for a multi-threading approach but rather as a web worker for the app.

Based on Roku’s recommendation, the Task component in this framework will have the following characteristics:

Minimal Input and Output Fields:

Typically involves 1 input for the request, 1 input for initParams, and 1 output for response.

Lightweight init() Function:

Focuses on setting the observer to the m.port.

Avoids heavy tasks in the init() function.

Caution with m Context in init():

Refrains from setting up very large AssocArray to the 'm' context in init() due to deep-copying issues during Task execution.

Limited Access to Render-owned Components:

Does not or limits access to m.top, m.global, or any Render-owned components from the Task thread.

Awareness of Rendezvous Spreading:

Exercises caution, especially in cases where a series of Task-owned objects have been transferred to the Render thread one after another due to Rendezvous issues.

Learn more about Rendezevous in Roku here.

Check Roku Development Tips!

Check Roku cache using Registry

Check Roku Threading

💻 Happy coding!

--

--

Amitdogra

Passionate Roku developer with a love for web technologies and backend wizardry. 🚀 ✨ #Android #Streaming #Roku #Web #Nodejs