Blog Infos
Author
Published
Topics
, , , ,
Author
Published

In the previous article, we explored how to automate feature creation using a Gradle task. Now, let’s take it a step further and implement a Gradle task that does the reverse — transforming an existing feature into a reusable template. This approach is invaluable for modular apps where features need to be replicated with slight variations.

What Will Be Generated?

The moveFeatureToTemplate Gradle task will generate a template version of the specified feature by extracting its structure and replacing feature-specific details with placeholders.

1. A New Template Directory

A new folder inside featureTemplate/ with the specified templateName (e.g., featureTemplate/screenTemplate).

2. Transformed Files

All files from the original feature (featureName) will be copied to the new template folder.

The feature-specific names, such as class names and package names, will be replaced with placeholders:

  • {{packageName}} instead of the original package.
  • {{featureName}} instead of the lowercase feature name.
  • {{className}} instead of the PascalCase feature name.

3. Updated File Names

The new files in the template will have generic names instead of being tied to a specific feature. Example structure:

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

How It Works

The custom Gradle task simplifies the process of creating reusable templates from existing features in your Android project. This task scans a specific feature directory, extracts its structure and files, and transforms them into a generalized template format using placeholders. The resulting templates can then be reused for generating new features.

1. Input Directory and Feature Files

The Gradle task expects an existing feature directory under your project’s src/main/java/ folder. The feature directory contains files like <FeatureName>Screen.kt<FeatureName>UiState.kt, and <FeatureName>ViewModel.kt.

Example of the feature directory structure:

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

For instance, if the feature name is Home, the directory might look like this:

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

2. Generated Template Directory Structure

The task transforms the feature directory into a reusable template structure by creating placeholders ({{packageName}}{{featureName}}{{className}}) in the file contents and filenames. The generated template is stored in the featureTemplate directory under the specified template name.

Example of the generated template structure:

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

If you convert the Home feature into a template called screenTemplate, the task will generate:

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

3. Placeholder Replacement

The task scans each file in the feature directory and replaces specific parts of the file names and contents with placeholders. This ensures that the feature can be reused for different features without manual adjustments. The following components are replaced with placeholders:

  • File namesHomeScreen.kt becomes Screen.kt.
  • Class names: The class name HomeScreen becomes {{className}}Screen.
  • Package names: The actual package name (e.g., com.example.app.home) becomes {{packageName}}.

Example:

Input (HomeScreen.kt):

package com.example.app.home

import androidx.compose.runtime.Composable

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

Output Template (Screen.kt):

package {{packageName}}

import androidx.compose.runtime.Composable

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

This process allows the feature files to be converted into a generalized template format. When you need to create a new feature, the task will replace these placeholders with the correct values based on the feature you specify.

Implementation of Feature Template Automation in Android Project

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

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 template files based on the feature files you specify.

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

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

Code Implementation:

// build.gradle.kts (Module :app)
tasks.register("moveFeatureToTemplate") {
    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.")

    val copyFilePath = projectDir.path + "/src/main/java/" + basePackageName.replace(".", "/")

    val placeholders = mapOf(
        basePackageName to "{{packageName}}",
        featureName.lowercase() to "{{featureName}}",
        featureName.replaceFirstChar { it.titlecase(Locale.getDefault()) } to "{{className}}",
    )

    doLast {

        val featureDir = File(copyFilePath, featureName.lowercase())
        val templateDir = File(rootDir, "$rootFolderName/$templateName")

        if (!featureDir.exists()) {
            throw IllegalArgumentException("Feature '$featureName' not exists.")
        }
        if (templateDir.exists()) {
            throw IllegalArgumentException("Template '$templateName' already exists.")
        }
        val fileName = featureName.replaceFirstChar {
            if (it.isLowerCase()) it.titlecase(
                Locale.getDefault()
            ) else it.toString()
        }
        featureDir.walkTopDown().filter { it.isFile }.forEach { file ->

            val findName = file.name.indexOf(fileName) + fileName.length
            val templateFileName = file.name.substring(findName, file.name.length)
            val targetFile = File(templateDir, templateFileName)
            targetFile.parentFile.mkdirs()

            var content = file.readText()
            placeholders.forEach { (key, value) ->
                content = content.replace(key, value)
            }
            targetFile.writeText(content)

            println("Generated file: $targetFile")
        }
        println("Template '$featureName' generated successfully in $templateDir")
    }
}

Step 2: Preparing the Feature Files

Ensure that the feature files exist in the project before running the task.

Step 3: Generating a Template

Run the following command from the terminal:

./gradlew moveFeatureToTemplate -P featureName=Home -P templateName=screenTemplate
Generated Template Successfully:

 

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

 

Customizations

1. Configurable Output Directory

Instead of always saving templates in featureTemplate/, allow the user to specify a custom output directory:

val outputDir = project.findProperty("outputDir") as String? ?: "featureTemplate"
val templateDir = File(rootDir, "$outputDir/$templateName")
2. Exclude Certain Files

You might not want to include test files, documentation, or specific files in the template. Modify the filtering logic to exclude them:

val excludedFiles = listOf("README.md", "test/", "androidTest/")
featureDir.walkTopDown()
    .filter { it.isFile && !excludedFiles.any { ex -> it.path.contains(ex) } }
    .forEach { file -> /* Process File */ }
3. Include Additional Placeholder Replacements

For further customization, extend the placeHoldersmap to replace additional project-specific values, such as:

val placeholders = mapOf(
    basePackageName to "{{packageName}}",
    featureName.lowercase() to "{{featureName}}",
    featureName.replaceFirstChar { it.titlecase(Locale.getDefault()) } to "{{className}}",
    "com.example.app" to "{{basePackage}}"
)

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.

Benefits of Using Gradle for Feature Generation

Gradle provides a powerful automation framework for managing Android projects efficiently. Here’s why it’s a great choice for feature template automation:

1. Eliminates Manual Work

Manually copying and modifying files for every new feature is error-prone and time-consuming. This task automates the entire process, reducing human errors.

2. Ensures Consistency

Using a standardized template guarantees that all features follow the same structure, improving code maintainability and readability across the project.

3. Accelerates Development

Developers can focus on implementing features rather than boilerplate setup, significantly reducing onboarding time for new team members.

4. Fully Integrated with Build System

Since it runs inside Gradle, the template generation fits seamlessly into the existing Android build pipeline without requiring external scripts or tools.

5. Easy to Customize and Extend

Gradle allows developers to modify the task as per project requirements, whether by adding more placeholders, supporting multiple template types, or integrating it with CI/CD pipelines.

6. Version Control Friendly

Since the template transformation is deterministic and automated, it ensures that every developer gets the same template structure, avoiding inconsistencies in codebase contributions.

Conclusion

This Gradle task provides a streamlined way to extract existing feature modules and convert them into reusable templates. By automating the transformation process, it enhances maintainability and accelerates the development of new features. Stay tuned for further improvements and integrations in upcoming articles!

Note: If you need an example, check out my repository

simple-create-feature-example: This branch demonstrates how to automate the creation of a simple home screen feature. It includes the setup of UI state, UI events, and ViewModel using Gradle tasks to streamline the development process.

simple-create-template-example: In this branch, you’ll see how to create reusable templates for Android screens. It showcases the automation of screen, UI state, UI event, and ViewModel creation, making it easy to replicate the feature structure across different projects.

master: This branch provides a real-world example with an e-commerce product list feature. It demonstrates how Gradle tasks are used to set up and customize a complete feature structure, offering a practical use case for automating feature creation in Android apps.

Happy coding!

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

Gradle
Kotlin
Android
Automation

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