Blog Infos
Author
Published
Topics
, , , ,
Author
Published

Creating features in Android development often involves repetitive tasks like setting up screen files, UI state management, and ViewModel classes. To streamline this process, we can use a Gradle Task to automatically generate these files based on reusable templates. This article will guide you step-by-step on how to implement and use this Gradle-based solution.

What Will Be Generated?

For every new screen, the Gradle task will generate:

  1. <ScreenName>Screen.kt: A composable function that defines the screen’s UI.
  2. <ScreenName>UiState.kt: A data class representing the screen’s UI state and events.
  3. <ScreenName>ViewModel.kt: A ViewModel that manages the UI state and handles user interactions.

How It Works

The custom Gradle task simplifies the process of generating new feature files in Android by using pre-defined templates. These templates are placed in the featureTemplate directory and are used to create new screen features with consistent structure and code.

1Directory Structure and Template Files

The Gradle task looks for templates in a directory called featureTemplate. Inside this directory, you can organize different feature templates into subfolders. Each subfolder corresponds to a template type. For example, the screenTemplate subfolder will contain the basic files needed to generate a new screen, such as Screen.ktUiState.kt, and ViewModel.kt.

Example of the directory structure:

featureTemplate/
    ├── screenTemplate/
    │   ├── Screen.kt
    │   ├── UiState.kt
    │   └── ViewModel.kt

2. Generated Directory Structure

When you run the Gradle task to generate a new feature, the task creates a new directory for the feature in your project’s src/main/java/com/example/app/ folder. This generated directory will contain files like:

src/main/java/com/example/app/<FeatureName>/
    ├── <FeatureName>Screen.kt
    ├── <FeatureName>UiState.kt
    └── <FeatureName>ViewModel.kt

For instance, if you create a feature called Home, the task will generate:

src/main/java/com/example/app/home/
    ├── HomeScreen.kt
    ├── HomeUiState.kt
    └── HomeViewModel.kt

3. Template Customization

The templates in the featureTemplate directory use placeholders like {{FeatureName}}{{packageName}}, and {{className}}. When the Gradle task runs, these placeholders are automatically replaced with actual values based on the featureName you provide and the configuration of your project.

For example, if your feature name is Home, the template file Screen.kt might look like this:

Template (Screen.kt):

package {{packageName}}

import androidx.compose.runtime.Composable

@Composable
fun {{className}}Screen() {
    // TODO: Implement the UI for {{className}}Screen
}

When you run the task with -PfeatureName=Home, the task will replace {{packageName}} with your base package name (e.g., com.example.app) and {{className}} with Home. This results in the following generated file:

Generated (HomeScreen.kt):

package com.example.app

import androidx.compose.runtime.Composable

@Composable
fun HomeScreen() {
    // TODO: Implement the UI for HomeScreen
}

This customization process ensures that each feature file is tailored to your project without manual editing.

Implementation of Feature Template Automation in Android Project

To implement the automation of feature generation in your Android project, follow the steps outlined below. These steps will guide you in setting up the necessary Gradle task, preparing template files, and using those templates to generate new features automatically.

Step 1: Setting Up the Gradle Task

The first step is to define a custom Gradle task in your build.gradle.kts file. This task will automatically generate the necessary feature files based on the template you specify.

How It Works:
  1. Defining Properties: The task will accept two properties:
  • featureName: The name of the feature you want to generate (e.g., Home).
  • templateName: The type of template you want to use (e.g., screenTemplate).
  • rootFolderName: Identifies the directory containing your template files (default is featureTemplate).

2. Code Replacement: The task will read the template files and replace placeholders ({{featureName}}{{className}}, and {{packageName}}) with actual values based on your project configuration.

3. Directory Structure: The task creates a new directory structure for the feature under src/main/java/<packageName>/<FeatureName>/ and generates the required files.

Code Implementation:

 

// build.gradle.kts (Module :app)
tasks.register("moveTemplateToFeature") {
    val rootFolderName = "featureTemplate"

    val featureName = project.findProperty("featureName") as String?
        ?: error("Feature name is required. Use -PfeatureName=<name> to specify it.")

    val templateName = project.findProperty("templateName") as String?
        ?: error("Template name is required. Use -PtemplateName=<name> to specify it.")

    // Retrieve the base package name from the project configuration
    val basePackageName = project.android.defaultConfig.applicationId
        ?: error("Base package could not be detected. Ensure applicationId is set in defaultConfig.")

    // Construct the base output path for the generated files
    val generatedFilePath = File(projectDir, "src/main/java/${basePackageName.replace(".", "/")}")

    // Map of placeholders to be replaced in template files
    val placeholders = mapOf(
        "{{packageName}}" to basePackageName,
        "{{featureName}}" to featureName.lowercase(),
        "{{className}}" to featureName.replaceFirstChar { it.titlecase(Locale.getDefault()) }
    )

    doLast {
        val featureDir = File(generatedFilePath, featureName.lowercase())
        if (featureDir.exists()) error("Feature '$featureName' already exists at ${featureDir.path}.")
        featureDir.mkdirs()

        val templateDir = File(rootDir, "$rootFolderName/$templateName")
        check(templateDir.exists() && templateDir.isDirectory) {
            "Template directory '$templateDir' not found or is not a directory."
        }

        // Copy and customize template files
        templateDir.walkTopDown()
            .filter { it.isFile }
            .forEach { file ->
                val relativePath = file.relativeTo(templateDir).parent ?: ""
                val featureFileName = "${featureName}${file.name}"
                val targetFile = File(featureDir, "$relativePath/$featureFileName")
                targetFile.parentFile.mkdirs()

                // Read file content and replace placeholders
                var content = file.readText()
                placeholders.forEach { (key, value) ->
                    content = content.replace(key, value)
                }
                targetFile.writeText(content)
                println("Generated file: ${targetFile.path}")
            }

        println("Feature '$featureName' successfully generated at ${featureDir.path}.")
    }
}

 

Step 2: Preparing the Template Files

The next step is to create the templates for the feature files. These templates will contain placeholders that will be replaced by the Gradle task during generation.

Template Folder Structure

Create a featureTemplate/ directory and then a subfolder for each template type (e.g., screenTemplate). Inside the screenTemplate/ folder, create the following files:

featureTemplate/
    ├── screenTemplate/
    │   ├── Screen.kt
    │   ├── UiState.kt
    │   └── ViewModel.kt

Screen Template (Screen.kt)

package {{packageName}}

import androidx.compose.runtime.Composable

@Composable
fun {{className}}Screen() {
    // TODO: Implement the UI for {{className}}Screen
}

UI State Template (UiState.kt)

package {{packageName}}

data class {{className}}UiState(
    val message: String = ""
)

sealed class {{className}}UiEvent {
    object OnButtonClick : {{className}}UiEvent()
}

 

ViewModel Template (ViewModel.kt)

 

package {{packageName}}

import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

class {{className}}ViewModel : ViewModel() {
    private val _uiState = MutableStateFlow({{className}}UiState())
    val uiState: StateFlow<{{className}}UiState> = _uiState

    fun handleEvent(event: {{className}}UiEvent) {
        when (event) {
            is {{className}}UiEvent.OnButtonClick -> {
                _uiState.value = {{className}}UiState("Button Clicked!")
            }
        }
    }
}

 

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Kobweb:Creating websites in Kotlin leveraging Compose HTML

Kobweb is a Kotlin web framework that aims to make web development enjoyable by building on top of Compose HTML and drawing inspiration from Jetpack Compose.
Watch Video

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kobweb

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author o ...

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kob ...

Jobs

No results found.

Step 3: Generating a Feature

Once the Gradle task and templates are set up, you can now generate new features by running a Gradle command.

How to Run:

Run the following command from the terminal:

./gradlew moveTemplateToFeature -PfeatureName=Home -PtemplateName=screenTemplate
  • featureName should be replaced with the name of the feature you want to create (e.g., Home).
  • templateName refers to the folder where your templates are stored (e.g., screenTemplate).

Generated Files

After running the command, the following files will be generated in the appropriate location:

src/main/java/com/example/app/home/
    ├── HomeScreen.kt
    ├── HomeUiState.kt
    └── HomeViewModel.kt

Each of these files will have the placeholders replaced with the correct feature and package names. The generated files will be ready to use, and you can implement your feature logic in them.

Customizations

1. Modify Templates

You can modify the files in the featureTemplate folder to suit your app’s structure and naming conventions.

2. Add More Templates

You can create additional template folders inside featureTemplate (e.g., repositoryTemplateserviceTemplate) and add new file generation logic in the Gradle task.

3. Placeholder Customization

The placeholders like {{packageName}}{{featureName}}, and {{className}} can be customized in your templates to support more dynamic replacements.

Benefits of Using Gradle for Feature Generation

  1. Efficiency: Automate repetitive tasks and focus on building features.
  2. Consistency: Maintain a standardized file structure and naming conventions across your project.
  3. Scalability: Easily add more templates or customize the Gradle task for additional features.
  4. Flexibility: Dynamically generate files using placeholders and templates tailored to your needs.
Conclusion

Automating feature creation with Gradle tasks can significantly streamline your development workflow, especially in projects with repetitive patterns. By defining templates and customizing them dynamically, you can maintain consistency, reduce errors, and save valuable development time.

This approach is particularly useful for scaling projects and ensuring that all modules adhere to your project’s structure and standards. Whether you’re generating screens, ViewModels, or other components, this method empowers you to focus more on logic and functionality rather than boilerplate code.

Note: If you need an example, check out my repository Screen Module Generator, where I’ve implemented a complete example to showcase an e-commerce product list feature using this Gradle task. It demonstrates how the entire structure is automatically set up and customized for practical use cases.

Happy coding!

Example GitHub Repo:

If you’re interested in learning more about Kotlin Multiplatform and Compose Multiplatform, check out my playlist on YouTube Channel:
Mastering Kotlin Multiplatform with Jetpack Compose: Complete Guide in Hindi

Thank you for reading! 🙌🙏✌ I hope you found this guide useful.

Don’t forget to clap 👏 to support me and follow for more insightful articles about Android Development, Kotlin, and KMP. If you need any help related to Android, Kotlin, and KMP, I’m always happy to assist.

Explore More Projects

If you’re interested in seeing full applications built with Kotlin Multiplatform and Jetpack Compose, check out these open-source projects:

  • News Kotlin Multiplatform App (Supports Android, iOS, Windows, macOS, Linux):
    News KMP App is a Kotlin Compose Multiplatform (KMP) project that aims to provide a consistent news reading experience across multiple platforms, including Android, iOS, Windows, macOS, and Linux. This project leverages Kotlin’s multiplatform capabilities to share code and logic while using Compose for UI, ensuring a seamless and native experience on each platform.
    GitHub Repository: News-KMP-App
  • Gemini AI Kotlin Multiplatform App (Supports Android, iOS, Windows, macOS, Linux, and Web):
    Gemini AI KMP App is a Kotlin Compose Multiplatform project designed by Gemini AI where you can retrieve information from text and images in a conversational format. Additionally, it allows storing chats group-wise using SQLDelight and KStore, and facilitates changing the Gemini API key.
    GitHub Repository: Gemini-AI-KMP-App
Follow me on

Medium , YouTube GitHub , Instagram , LinkedIn , Buy Me a Coffee , Twitter , DM Me For Freelancing Project

This article is previously published on proandroiddev.com.

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE
Menu