Skip to content

Storing Data Permanently Part 1/2 – Day 13 Android 14 Masterclass

Storing Data Permanently Part 1/2 - Day 13 Android 14 Masterclass
Become a developer with our complete learning paths
Become a developer with our complete learning paths

Storing Data Permanently Part 1/2 – Day 13 Android 14 Masterclass

Welcome to Day 13 of the Android 14 & Kotlin Masterclass, focusing on “Storing Data Permanently.” In this essential session, we explore the integration of critical dependencies like SQLite, Room, Shared Preferences, and DataStore. Key topics include the Kotlin-KAPT Plugin, Scaffold in Jetpack Compose, managing hexadecimal colors, and implementing FloatingActionButton. This day is packed with practical insights for robust Android app development, emphasizing data storage and UI design.

 

1. Adding Dependencies: Storing Data

Dependencies are external libraries or modules that your application relies on to function properly. Dependencies are added in your build.gradle file.

In the context of storing data permanently in Android applications, there are several types of storage options available, each potentially requiring different dependencies. These include:

  • SQLite: For storing structured data in a private database.
  • Room: An abstraction layer over SQLite to allow fluent database access.
  • Shared Preferences: For storing key-value pairs of simple data types.
  • DataStore: A more robust and asynchronous solution for storing key-value pairs, replacing Shared Preferences.

Implementation Tips

  • Choose the Right Storage Option: The choice between Room, Shared Preferences, and DataStore depends on your specific use case. For complex, structured data, Room is preferable. For lightweight, simple key-value storage, Shared Preferences or DataStore can be used.
  • Asynchronous Operations: When using these libraries, especially Room and DataStore, ensure that data operations are performed asynchronously to prevent blocking the UI thread.
  • Version Management: Always check for the latest versions of these dependencies to ensure compatibility and access to the latest features and security improvements.

Here are dependencies we added for our project: Storing Data Permanently

 

2. Kotlin-KAPT Plugin

KAPT, or Kotlin Annotation Processing Tool, is a part of the Kotlin compiler that allows for annotation processing in Kotlin code.

Annotations are a form of metadata that can be added to Kotlin code (like classes, methods, or fields) to provide additional information about the elements they are attached to, and they can influence the way programs are stored, compiled, and executed.

KAPT is particularly useful because it allows Kotlin projects to leverage annotation processors from Java libraries, which are essential for generating boilerplate code, performing compile-time validation, and for various other tasks that can improve the development experience and performance of the application.

KAPT is used for:

  • Processing annotations to generate code at compile-time.
  • Validating code before it gets compiled.
  • Working with libraries that use annotations to perform their functions, such as Dagger for dependency injection, Room for database access, and many others.

Setup

To enable KAPT in your Kotlin project, you need to apply the KAPT plugin in your build.gradle.kts file:

Advantages of Using KAPT

  • Interoperability: Allows Kotlin code to utilize Java annotation processors, bridging the ecosystem between Kotlin and Java.
  • Efficiency: Processes annotations without the need for Java stubs, which makes the build process more efficient.
  • Integration: Works well with popular Java libraries that rely on annotation processing.

 

3. Scaffold in Jetpack Compose

In Jetpack Compose, Scaffold is a composable function that implements the basic material design visual layout structure.

It provides slots for the most common top-level components such as the app bar, floating action button, drawer, bottom navigation, and the main content area.

Scaffold is designed to provide a consistent layout structure that adheres to material design guidelines.

Usage

Scaffold is typically used as a high-level component that sets up the structure of your UI. It allows developers to quickly scaffold a screen with the components that are most commonly used in a material design app.

Components of Scaffold

  • TopBar: A top app bar that displays information and actions relating to the current screen. It’s equivalent to Toolbar or ActionBar in the older View system.
  • BottomBar: A bar that is displayed at the bottom of the screen.
  • FloatingActionButton: A circular button that floats above the content and usually represents the primary action on the screen.
  • Drawer: A panel that slides in horizontally from the edge of the screen to show navigation options.
  • Content: The main UI content, which is displayed beneath the TopBar and above the BottomBar.

Customization

  • You can customize each part of the Scaffold to suit your design needs. For example, the TopAppBar can include navigation icons, title, actions, and be stylized with colors and elevation.
  • The Scaffold‘s body content (the main UI) can be any composable that you want to display as the main content of your screen.

Best Practices

  • Use Scaffold when you want to build a layout that follows Material Design guidelines.
  • Remember that the Scaffold structure is only a starting point. You can always create custom layouts if the provided structure doesn’t fit your needs.

By using Scaffold, you can ensure that your app has a consistent structure and design across different screens, saving time on UI development and making your codebase more maintainable.

Syntax & Example

Here’s a simple example of how to use Scaffold in a Jetpack Compose application:

Or:

Demonstrates the use of a topBar in a simple home view layout.

Or:

Let’s break down the components of this TopAppBar:

  • title: This is a composable lambda that takes other composables to define the title of the app bar. In this case, we’re simply displaying a text title.
  • navigationIcon: This is another composable lambda where you can provide an icon that acts as a navigation button. In this example, we’re using an IconButton with a back arrow icon inside it.
    • IconButton: A pre-styled Composable that provides a clickable area containing an icon. It is generally used for actions that do not require text labels.
    • onClick: The lambda provided to IconButton which defines what should happen when the icon is clicked. In this example, we are calling navController.navigateUp(), which is typically used to navigate to the previous screen in the navigation stack.
    • Icon: This Composable is used to display an icon. Icons.Filled.ArrowBack is a material icon provided by the material design icons set that signifies a return action.
    • contentDescription: A text description of the icon, which is used by screen readers for accessibility. In this example, it’s set to null assuming the navigation action is adequately described by the UI context, but in production code, you should provide a proper description.

Best Practices – TopAppBar

  • Use descriptive icons and titles in TopAppBar for better user navigation.
  • Provide contentDescription for all icons to ensure your app is accessible to users who rely on screen readers.
  • Make sure the actions within the TopAppBar are relevant to the current content. Overloading the app bar with too many actions can confuse users.
  • If you use a navigation icon, ensure it corresponds with the navigation pattern of your app—whether it opens a drawer or goes back in the navigation stack.

 

4. Modifier.heightIn and Elevation

Modifiers in Jetpack Compose allow you to modify the appearance and behavior of a component.

This line of code is an example of chaining multiple modifier functions together to apply several effects to a composable:

Let’s break down each part:

  • Modifier: This is the base class for all modifiers in Jetpack Compose. It’s an immutable representation that encapsulates the modifications or decorations to be applied to a composable function. The Modifier is the starting point to which you can attach various other modifier functions.
  • heightIn: This modifier function is used to specify the allowable height range for the composable it’s applied to.
    • min: The minimum height that the composable can have. It is defined as 100.dp, which means 100 density-independent pixels. Density-independent pixels are a unit of measurement that allow for UI consistency across different screen densities.
    • max: The maximum height that the composable can have. It is set to 200.dp, meaning the composable’s height will not exceed 200 density-independent pixels.

    This means that whatever composable this modifier is applied to, its height will be at least 100.dp and at most 200.dp, depending on the constraints passed by its parent in the layout.

  • elevation: This modifier function is used to give a composable a shadow effect, making it appear elevated above other elements on the screen.
    • The parameter 3.dp specifies the elevation height. In material design, elevation is used to express a hierarchy of surfaces by casting shadows. A higher value results in a larger, more noticeable shadow, which indicates that the element is “higher” above the other surfaces.
  • Chaining Modifiers: In Kotlin, you can chain modifier functions together using the . syntax. Each modifier function returns an updated Modifier instance with the new modification applied.

When you apply this combined modifier to a composable, you’re effectively saying: “This component should have a minimum height of 100.dp and a maximum height of 200.dp, and it should also have an elevation of 3.dp.” This would be useful, for example, in designing a card or button that needs to adhere to certain size constraints and stand out visually within the UI.

 

5. Understanding Hexadecimal and Colors

In digital applications, colors are often represented using hexadecimal (hex) color codes. These codes are a way of specifying colors in a format that combines red, green, and blue (RGB) color values in a single hexadecimal number.

Hex color codes are widely used in various programming environments, including Android development.

Hex Color Codes

  • Format: A hex color code typically starts with a # followed by six or eight hexadecimal digits. Each pair of digits represents the intensity of the red, green, or blue light channels, respectively.
  • RGB: In a six-digit hex code, the first two digits represent the red channel, the middle two represent the green channel, and the last two represent the blue channel. The range for each color is 00 to FF in hexadecimal (0 to 255 in decimal), where 00 is the absence of color and FF is the full intensity of the color.
  • Transparency (Alpha): An eight-digit hex code includes an additional pair of digits at the beginning that represents the alpha channel — the transparency of the color. The range is the same (00 to FF), where 00 is completely transparent and FF is completely opaque.

Examples

  • Solid Color: #FF0000 – This is the hex code for the color red. FF represents full intensity red, and the other two pairs are 00, indicating no contribution from green or blue.
  • Translucent Color: #80FF0000 – This is the hex code for a half-transparent red color. 80 represents 50% opacity, FF is full intensity red, and the green and blue channels are 00.

Android and Hex Colors

In Android development, colors are used in XML layouts and in Kotlin/Java code.

  • XML: You can define a color resource in res/values/colors.xml like so:
  • Kotlin/Java: You can use the Color class to define colors programmatically:

Color Resources

Android encourages the use of color resources to maintain consistency across the application and to facilitate theming and styling.

In Android development, colorResource is a function used within Kotlin code to access color resources. These color resources are defined in XML format and are usually stored in the res/values/colors.xml file of your Android project. This method of organizing colors promotes reusability and consistency across your app’s UI.

Accessing Color Resources

  • colorResource Function: This function retrieves a color from the resources based on its resource ID.
  • Usage in Compose: In Jetpack Compose, you can use colorResource directly within your composables to apply colors, like so:

Defining Color Resources

  • colors.xml: This is an XML resource file located in the res/values directory.
  • Defining a Color: You can define a new color by adding a <color> element with a name and a hex value.

  • Referencing in XML Layouts: In XML layouts, you reference a color using @color/color_name.

Adding Extra Colors

  • Extending colors.xml: To add extra colors, simply add new <color> elements in the colors.xml file.
  • Maintainability: It’s a good practice to categorize and name your colors meaningfully, such as colorPrimary, colorAccent, textColorPrimary, etc.

Example of Adding Extra Colors

Here’s how you would add extra colors to your colors.xml:

By using colorResource and defining colors in colors.xml, you can easily manage and apply a cohesive color scheme throughout your Android app.

Using a Color Selector

To aid in selecting hex colors, you can use tools like Google’s color selector hex tool. These tools provide a user-friendly interface to choose colors and often include the ability to adjust transparency.

Best Practices

  • Consistency: Define common colors in the colors.xml resource file to maintain consistency throughout your app.
  • Naming: Use descriptive names for your color resources to make it clear what they represent.
  • Accessibility: Choose color combinations that provide sufficient contrast to be accessible to all users, including those with visual impairments.

By understanding hex color codes and how to use them in Android, developers can precisely control the UI’s color scheme, enhancing the visual appeal and usability of their applications.

 

6. Adding a Navigation Icon in Jetpack Compose

In Jetpack Compose, navigation icons are typically used in top app bars as interactive elements that trigger navigation events, such as opening a drawer or returning to the previous screen.

These icons are not only functional but also an integral part of the material design language, providing visual cues to users about possible actions.

NavigationIcon Composable

  • Purpose: A NavigationIcon is commonly placed in the TopAppBar composable and is usually represented by an icon that indicates its function (like a hamburger menu for opening a drawer or an arrow for going back).

Implementing a NavigationIcon

To add a navigation icon to a TopAppBar, you use the navigationIcon parameter, which takes a composable lambda. Inside this lambda, you typically use an IconButton for its clickable effects and place an Icon inside it.

Syntax & Example

Here’s an example of how you can add a navigation icon to your TopAppBar:

Understanding the Code

  • IconButton: This is a composable that provides a clickable area that contains an icon. It is designed to be used inside TopAppBar as a navigationIcon or in other parts of the UI where an icon button is needed.
  • Icon: A composable that draws an icon. The icon can be sourced from different image vectors provided by the material design icons set, or you can define your own.
  • imageVector: This is a parameter of the Icon composable where you pass the vector graphic you want to display. In the example provided, Icons.Filled.ArrowBack is used, which is a pre-defined material icon representing a backward navigation.
  • Icons.AutoMirrored: This is a feature where the icon will automatically mirror itself in right-to-left (RTL) layout directions. However, it is not used in the provided code snippet. If you wanted to use it, it would look something like this:

  • It’s important to note that not all icons need to be auto-mirrored. It depends on the context of the icon and whether its directionality affects its meaning.
  • contentDescription: This is an accessibility feature, providing a text description of the icon’s function, which is read aloud to users with screen readers.

Best Practices

  • Always provide a contentDescription for icons to ensure your app is accessible.
  • Ensure the navigation icon’s action is clear to the user and consistent with common UI patterns (like a back arrow for navigating back).
  • Use material design icons where possible to maintain consistency with design standards and user expectations.

Adding a navigation icon with proper actions and descriptions can greatly enhance the navigability and user experience of your Android app.

7. FloatingActionButton in Jetpack Compose

The FloatingActionButton (FAB) is a distinctive circular button that hovers over the user interface in material design.

It’s intended for a promoted action and is typically anchored to the bottom right corner of the screen or a key focal point within the app, suggesting a primary action.

Usage

The FAB should represent the most common action on a screen. It’s meant to stand out and indicate to the user that this button performs an important and frequent action, such as composing a new email, adding a new contact, or starting a new chat.

Design & Behavior

  • Elevation: The FAB has a shadow that makes it appear elevated above other UI elements, indicating its importance.
  • Icon: The FAB usually contains an icon that reflects the action it will trigger.
  • Color: The button often uses the accent color of the app’s theme to stand out.

Syntax & Example

Here’s a detailed explanation of how to implement a FloatingActionButton in Jetpack Compose:

  • onClick: This is a lambda that defines what action to perform when the FAB is clicked. It’s critical for the FAB to have a click listener, as it’s an action button.
  • backgroundColor: Sets the background color of the FAB. It typically uses the secondary color from the MaterialTheme to align with the app’s color scheme, but it can be customized.
  • contentColor: This is the color of the content inside the FAB, usually the icon. It is often set to a color that contrasts with the backgroundColor for visibility. The function contentColorFor is used to determine an appropriate content color based on the background.
  • elevation: Determines the size of the shadow cast by the FAB, giving it a raised appearance. You can adjust this value to control the depth effect.
  • Icon: The child of the FloatingActionButton that typically represents the button’s action. In the example above, the icon used is Icons.Default.Add, which is an icon provided by the material design icons set, representing an addition or creation action.
  • contentDescription: Provides a brief description of the icon’s action, which is used by screen readers for users who have visual impairments.

Best Practices

  • Use a FAB for a positive primary action like create, favorite, share, or navigate to a common destination.
  • Don’t overcrowd your UI with multiple FABs; stick to one per screen.
  • Ensure that the icon inside the FAB is self-explanatory or accompanied by text on first use.

By following these practices, you can use the FloatingActionButton effectively in your apps to enhance user experience and promote key actions.

 

8. Card Layout in Jetpack Compose

In material design, a Card is a surface that displays content and actions on a single topic. It acts as an entry point for more detailed information.

Cards have a slight elevation and rounded corners, implying that they are touchable elements separate from the background and other content.

Usage

Cards are used to present a summary of information that is detailed enough to understand the context but concise enough to not overwhelm the user.

They are commonly used to showcase elements like products in an e-commerce app, articles in a news app, or profiles in a social media app.

Design & Behavior

  • Elevation: Cards have a shadow that makes them appear elevated above the app’s background.
  • Shape: They typically have rounded corners, adhering to material design principles.
  • Content: Cards can contain images, text, buttons, or other interactive elements.
  • Interaction: They can be made clickable to trigger actions like navigation or to display detailed information.

Syntax & Example

Here’s a detailed example of how a Card can be implemented in Jetpack Compose:

  • Modifier: The modifier parameter allows you to specify the layout and behavior of the card, such as its size, padding, and click actions.
  • fillMaxWidth: This modifier function makes the Card fill the entire width available to it by its parent composable.
  • padding: It is applied to create space around the Card, separating it from other UI elements.
  • clickable: This modifier makes the Card respond to click events. You can define the action that will be triggered when the user taps the Card.
  • elevation: This parameter gives the Card its depth over other elements by casting a shadow around it.
  • shape: Defines the shape of the Card, in this case, with rounded corners.
  • Column: This is a composable that places its children in a vertical sequence. Inside the Card, we use a Column to layout its contents.
  • Text: These composables are used to add text inside the Card. You can style the text using the typography styles provided by MaterialTheme.

Best Practices

  • Keep the content of a Card simple to maintain readability and usability.
  • Cards should be used as an entry point to more complex details, so make sure tapping on a Card leads to more in-depth content related to that Card.
  • Maintain consistent sizing and spacing for Cards, especially when they are part of a list or grid, to create a cohesive look.

By utilizing the Card layout effectively, you can present information in a clean, organized manner that is easy for users to interact with and navigate through.

 

9. Keyboard Options in Jetpack Compose

In Jetpack Compose, KeyboardOptions is a class used to configure the software keyboard behavior for text input components like TextField and OutlinedTextField.

These options enable you to control aspects of the keyboard such as the type of keyboard that should be shown, the appearance of the ‘Enter’ key, and more.

Usage

KeyboardOptions is particularly useful when you want to optimize the keyboard layout for specific types of input. For instance, showing a number pad when the user is expected to enter numeric values, or capitalizing the first letter of each sentence in a text input.

Commonly Used Keyboard Options

  • keyboardType: This option allows you to specify the type of keyboard to be displayed. For example, KeyboardType.Text, KeyboardType.Number, KeyboardType.Email, etc.
  • imeAction: This option specifies the action on the ‘Enter’ key. It can be set to actions like ImeAction.Search, ImeAction.Done, ImeAction.Next, etc.

Syntax & Example

Here’s an example showing how to use KeyboardOptions in a TextField composable:

  • KeyboardOptions: This is the class where you define the configuration of the keyboard.
    • keyboardType: Here, KeyboardType.Text indicates that a standard text keyboard should be displayed. You can change this based on the expected input (like KeyboardType.Email for email input fields).
    • imeAction: In this example, ImeAction.Done configures the ‘Enter’ key to display ‘Done’, which can be used to close the keyboard or submit the input.
  • KeyboardActions: This is a class where you define the actions to be performed based on the keyboard events. In the example above, an action is defined for the onDone event.

Best Practices

  • Choose the keyboardType that best fits the data type the user is expected to input to improve usability. For example, use KeyboardType.Number for numeric inputs.
  • Use appropriate imeAction to match the action the user is likely to take. For instance, if the text field is for searching, use ImeAction.Search.
  • Handle keyboardActions appropriately to make the user experience smooth and intuitive. For example, when the user presses ‘Done’, you might want to process the input or move the focus to the next text field.

By configuring KeyboardOptions and KeyboardActions properly, you can significantly enhance the text input experience in your app, making it more user-friendly and efficient.

10. Using Dummy Data in Android Development

Dummy data refers to placeholder data used during the development and testing of software.

Dummy data is often used to simulate real data in UI components and layouts, allowing developers to design and test the appearance and behavior of the app before the actual data is available or integrated.

Purpose

  • Design and Layout Testing: It helps in visualizing and refining the UI when the actual data is not yet available or is dynamic in nature.
  • Functionality Testing: Developers can use dummy data to test the functionality of the app, such as data sorting, filtering, and user interactions.
  • Performance Testing: Dummy data can be used to assess how the app performs with different quantities and types of data.

Creating Dummy Data

Dummy data can be anything that mimics the structure of your expected real data but doesn’t necessarily carry meaningful content. It can be hard-coded within the app or generated using dummy data libraries.

Example

Here’s a basic example of how you might create and use dummy data in an Android app:

Suppose your app displays a list of users. Each user has a name and an email.

  1. Define a Data Model:

  1. Create a List of Dummy Users:

  1. Use Dummy Data in UI Components:

If you’re using Jetpack Compose, you can display this list in a LazyColumn:

For traditional XML-based layouts, you would set up an Adapter to bind this data to, for example, a RecyclerView.

Best Practices

  • Separation: Keep dummy data separate from your production code. This helps in easily replacing or removing it when the actual data integration is ready.
  • Realistic Data: Use dummy data that is representative of real data in terms of structure and type to get a more accurate representation of how your app will function.
  • Scalability: Test with varying amounts of data to understand how your layout and performance will scale.

Tools and Libraries

There are tools and libraries available that can generate dummy data for different scenarios, like random user data, text, images, etc. These can be useful for more complex or varied data needs.

By effectively using dummy data, developers can streamline the development process, ensuring that the app’s design and functionality are well-tested and ready for integration with real data sources.

 

Conclusion: Storing Data Permanently Part 1/2 – Day 13 Android 14 Masterclass

Wrapping up Day 13, we’ve journeyed through vital aspects of permanent data storage in Android applications. From understanding various storage options to utilizing advanced UI components in Jetpack Compose, the day was rich with actionable knowledge. These skills are fundamental to elevating your proficiency as an Android developer, ensuring your apps are not only functional but also user-friendly and visually appealing.

 

If you want to skyrocket your Android career, check out our The Complete Android 14 & Kotlin Development Masterclass. Learn Android 14 App Development From Beginner to Advanced Developer.

Master Jetpack Compose to harness the cutting-edge of Android development, gain proficiency in XML — an essential skill for numerous development roles, and acquire practical expertise by constructing real-world applications.

 

Check out Day 11 of this course here.

Check out Day 12 of this course here.

Check out Day 14 of this course here.

Lost in coding? Discover our Learning Paths!
Lost in coding? Discover our Learning Paths!
Enter your email and we will send you the PDF guide:
Enter your email and we will send you the PDF guide