گریدل پروژتو تمیز کن

چند وقتیه که کثیف بودن گریدلم خیلی رو اعصاب بوده و گریدل اکثر پروژه هام در بهترین حالت ممکن این شکلی بود:

Before
Before

و حالا با استفاده از Kotlin DSL میشه یکم مرتب ترش کرد:

نکته: دو اسکریپت بالا واسه دو پروژه مختلف هستن و ربطی به هم ندارن! اما پروسه تغییر به کاتلین DSL رو این پایین می‌نویسم.


برای اطلاعات بیشتر ارائه سنا عبادی رو در لاگ کت ببینید:

https://www.youtube.com/playlist?list=PLT2xIm2X7W7jRcn9QvxaUA1JoZ3jrHv7W


مرحله اول، ساخت پوشه buildSrc:

در root پروژه خودتون، پوشه buildSource رو به صورت زیر و با این ترتیب بنویسید:

بعد ساخت پوشه ابتدا پوشه سورس رو به ترتیب:

src -> main -> java

ایجاد کنید و فایل Dependencies.kt رو داخلش بسازید. بعد از این مرحله، گریدل اسکریپت خودتون رو داخل پوشه buildSrc ایجاد کنید:

build.gradle.kts:

import org.gradle.kotlin.dsl.`kotlin-dsl`
plugins {
    `kotlin-dsl`
}

repositories {
    jcenter()
}

حالا پروژه رو sync کنید و منتظر بمانید!

بعد از sync شدن پروژه، دو پوشه gradle و build به پوشه buildSrc اضافه میشه که اگه از ورژن کنترل(git) استفاده می‌کنید، بهتره که اونارو به gitignore اضافه کنید. به صورت دستی فایل گیت ایگنور رو اضافه کنید و به صورت زیر عمل کنید:

.gradle
/build

حالا نوبت اینه که پروژه اصلیمون رو به کاتلین DSL منتقل کنیم!

مرحله دوم، تغییر Settings به kts:

settings.gradle:

include ':app'
rootProject.name = &quotStationery&quot

settings.gradle.kts:

include(&quot:app&quot)
rootProject.name = &quotStationery&quot

پروژه رو Sync کنید.

مرحله سوم، تغییر فایل های build:

ابتدا فایل Dependencies رو به اینصورت بنویسید:

object Dependencies {

    object Versions {
    }

    object DefaultConfig {
    }

    object Plugins {
    }

    object Libraries {
        object Test {
        }
    }

    object ClassPaths {
    }
}

آبجکت Versions برای نگه داری نسخه ها، آبجکت DefaultConfig برای نگه داری کانفیگ گریدل app، آبجکت Plugins برای نگه داری پلاگین ها، آبجکت Libraries برای نگه داری کتابخونه ها و آبجکت Test برای نگه داری کتابخونه های تست، آبجکت ClassPaths برای نگه داری ClassPath های ما ?


اول ClassPath ها و ورژنای اونارو اضافه می کنیم:

object Versions {
    const val gradle = &quot4.1.0&quot
    const val kotlin = &quot1.4.10&quot
}


object ClassPaths {
    const val gradle = &quotcom.android.tools.build:gradle:${Versions.gradle}&quot
    const val kotlin = &quotgradle-plugin&quot
}


بیلد گردیل ماژول پروژه رو ویرایش می‌کنیم:

build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = &quot1.3.72&quot
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath &quotcom.android.tools.build:gradle:4.1.0&quot
        classpath &quotorg.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version&quot

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

build.gradle.kts:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url = uri(&quothttps://jitpack.io&quot) }
    }
    dependencies {
        classpath(Dependencies.ClassPaths.gradle)
        classpath(kotlin(Dependencies.ClassPaths.kotlin, version = Dependencies.Versions.kotlin))

        classpath(Dependencies.ClassPaths.hilt)
        classpath(Dependencies.ClassPaths.safeArgs)
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url = uri(&quothttps://jitpack.io&quot) }
    }
}

tasks.register(&quotclean&quot,Delete::class){
    delete(rootProject.buildDir)
}


حالا میرسیم به تغییر گریدل ماژول اپ، اول اطلاعاتی که لازم داریم رو داخل Dependencies که ساختیم اضافه میکنیم:

object Dependencies {

    object Versions {
        const val gradle = &quot4.1.0&quot
        const val kotlin = &quot1.4.10&quot
        const val coreKTX = &quot1.3.1&quot
        const val appCompat = &quot1.2.0&quot
        const val constraintLayout = &quot2.0.1&quot
        const val legacySupport = &quot1.0.0&quot
        const val espresso = &quot3.3.0&quot
        const val jUnit = &quot4.13&quot
        const val arch = &quot2.1.0&quot
        const val concurrent = &quot1.1.0&quot
        const val lifeCycle = &quot2.2.0&quot
        const val hilt = &quot2.28-alpha&quot
        const val hiltAndroid = &quot1.0.0-alpha02&quot
        const val leakCanary = &quot2.4&quot
    }

    const val compileSdkVersion = 30
    const val buildToolsVersion = &quot30.0.2&quot

    object DefaultConfig {
        const val applicationID = &quotir.moeindeveloper.stationery&quot
        const val minSdKVersion = 19
        const val targetSdkVersion = 30
        const val versionCode = 1
        const val versionName = &quot1.0&quot
        const val testInstrumentationRunner = &quotandroidx.test.runner.AndroidJUnitRunner&quot
    }

    object Plugins {
        const val application = &quotcom.android.application&quot
        const val android = &quotandroid&quot
        const val kotlinExtensions = &quotandroid.extensions&quot
        const val kapt = &quotkapt&quot
        const val hilt = &quotdagger.hilt.android.plugin&quot
        const val safeArgs = &quotandroidx.navigation.safeargs.kotlin&quot
    }

    object Libraries {
        const val kotlin = &quotorg.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}&quot
        const val coreKTX = &quotandroidx.core:core-ktx:${Versions.coreKTX}&quot
        const val appCompat = &quotandroidx.appcompat:appcompat:${Versions.appCompat}&quot
        const val constraintLayout = &quotandroidx.constraintlayout:constraintlayout:${Versions.constraintLayout}&quot
        const val legacySupport = &quotandroidx.legacy:legacy-support-v4:${Versions.legacySupport}&quot
        const val concurrent = &quotandroidx.concurrent:concurrent-futures-ktx:${Versions.concurrent}&quot
        const val viewModel = &quotandroidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifeCycle}&quot
        const val liveData = &quotandroidx.lifecycle:lifecycle-livedata-ktx:${Versions.lifeCycle}&quot
        const val lifeCycleCommon = &quotandroidx.lifecycle:lifecycle-common-java8:${Versions.lifeCycle}&quot
        const val activity = &quotandroidx.activity:activity-ktx:${Versions.activity}&quot
        const val hilt = &quotcom.google.dagger:hilt-android:${Versions.hilt}&quot
        const val hiltCompiler = &quotcom.google.dagger:hilt-android-compiler:${Versions.hilt}&quot
        const val hiltAndroid = &quotandroidx.hilt:hilt-lifecycle-viewmodel:${Versions.hiltAndroid}&quot
        const val leakCanary = &quotcom.squareup.leakcanary:leakcanary-android:${Versions.leakCanary}&quot

        object Test {
            const val espressoContrib = &quotandroidx.test.espresso:espresso-contrib:${Versions.espresso}&quot
            const val espressoIntents = &quotandroidx.test.espresso:espresso-intents:${Versions.espresso}&quot
            const val espressoAccessibility = &quotandroidx.test.espresso:espresso-accessibility:${Versions.espresso}&quot
            const val espressoWeb = &quotandroidx.test.espresso:espresso-web:${Versions.espresso}&quot
            const val espressoIdlingConcurrent = &quotandroidx.test.espresso.idling:idling-concurrent:${Versions.espresso}&quot
            const val jUnit = &quotjunit:junit:${Versions.jUnit}&quot
        }
    }

    object ClassPaths {
        const val gradle = &quotcom.android.tools.build:gradle:${Versions.gradle}&quot
        const val kotlin = &quotgradle-plugin&quot
        const val hilt = &quotcom.google.dagger:hilt-android-gradle-plugin:${Versions.hilt}&quot
        const val safeArgs = &quotandroidx.navigation:navigation-safe-args-gradle-plugin:${Versions.navigation}&quot
    }
}

خب حالا فایل گریدل ماژول اپ رو به کاتلین DSL تغییر میدیم:

build.gradle:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdkVersion 30
    buildToolsVersion &quot30.0.2&quot

    defaultConfig {
        applicationId &quotir.moeindeveloper.stationery&quot
        minSdkVersion 19
        targetSdkVersion 30
        versionCode 1
        versionName &quot1.0&quot

        testInstrumentationRunner &quotandroidx.test.runner.AndroidJUnitRunner&quot
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation &quotorg.jetbrains.kotlin:kotlin-stdlib:$kotlin_version&quot
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

قسمت پلاگین:

plugins {
    id(Dependencies.Plugins.application)
    kotlin(Dependencies.Plugins.android)
    kotlin(Dependencies.Plugins.kotlinExtensions)
    kotlin(Dependencies.Plugins.kapt)
    id(Dependencies.Plugins.hilt)
    id(Dependencies.Plugins.safeArgs)
}

برای پلاگین هایی که برا کاتلین هستن از kotlin استفاده می کنیم مثل kotlin-android و دیگه نیازی نیست که کاتلین رو اول عبارت بنویسیم و اینطوری کافیه:

const val android = &quotandroid&quot

قسمت اندروید:

android {
    compileSdkVersion(Dependencies.compileSdkVersion)
    buildToolsVersion(Dependencies.buildToolsVersion)

    defaultConfig {
        applicationId = Dependencies.DefaultConfig.applicationID
        minSdkVersion(Dependencies.DefaultConfig.minSdKVersion)
        targetSdkVersion(Dependencies.DefaultConfig.targetSdkVersion)
        versionCode = Dependencies.DefaultConfig.versionCode
        versionName = Dependencies.DefaultConfig.versionName
        multiDexEnabled = true
        testInstrumentationRunner = Dependencies.DefaultConfig.testInstrumentationRunner
    }

    buildTypes {
        getByName(&quotrelease&quot) {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile(&quotproguard-android-optimize.txt&quot), &quotproguard-rules.pro&quot)
        }
    }

    buildFeatures {
        viewBinding = true
    }


    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }


    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}

قسمت وابستگی ها:

dependencies {
    implementation(Dependencies.Libraries.kotlin)
    implementation(Dependencies.Libraries.coreKTX)
    implementation(Dependencies.Libraries.appCompat)
    implementation(Dependencies.Libraries.constraintLayout)
    implementation(Dependencies.Libraries.legacySupport)

    /*
    arch components
     */
    implementation(Dependencies.Libraries.concurrent)
    implementation(Dependencies.Libraries.viewModel)
    implementation(Dependencies.Libraries.liveData)
    implementation(Dependencies.Libraries.lifeCycleCommon)
    implementation(Dependencies.Libraries.activity)
    /*
    arch components
     */


    /*
    Hilt
     */
    implementation(Dependencies.Libraries.hilt)
    kapt(Dependencies.Libraries.hiltCompiler)
    implementation(Dependencies.Libraries.hiltAndroid)
    /*
    Hilt
     */
    debugImplementation(Dependencies.Libraries.leakCanary)


    /*
    Test libs
     */
    androidTestImplementation(Dependencies.Libraries.Test.espressoCore)
    androidTestImplementation(Dependencies.Libraries.Test.espressoContrib)
    androidTestImplementation(Dependencies.Libraries.Test.espressoIntents)
    androidTestImplementation(Dependencies.Libraries.Test.espressoAccessibility)
    androidTestImplementation(Dependencies.Libraries.Test.espressoWeb)
    androidTestImplementation(Dependencies.Libraries.Test.espressoIdlingConcurrent)
    testImplementation(Dependencies.Libraries.Test.jUnit)
    /*
    Test libs
     */

}

build.gradle.kts:

plugins {
    id(Dependencies.Plugins.application)
    kotlin(Dependencies.Plugins.android)
    kotlin(Dependencies.Plugins.kotlinExtensions)
    kotlin(Dependencies.Plugins.kapt)
    id(Dependencies.Plugins.hilt)
    id(Dependencies.Plugins.safeArgs)
}
android {
    compileSdkVersion(Dependencies.compileSdkVersion)
    buildToolsVersion(Dependencies.buildToolsVersion)

    defaultConfig {
        applicationId = Dependencies.DefaultConfig.applicationID
        minSdkVersion(Dependencies.DefaultConfig.minSdKVersion)
        targetSdkVersion(Dependencies.DefaultConfig.targetSdkVersion)
        versionCode = Dependencies.DefaultConfig.versionCode
        versionName = Dependencies.DefaultConfig.versionName
        multiDexEnabled = true
        testInstrumentationRunner = Dependencies.DefaultConfig.testInstrumentationRunner
    }

    buildTypes {
        getByName(&quotrelease&quot) {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile(&quotproguard-android-optimize.txt&quot), &quotproguard-rules.pro&quot)
        }
    }

    buildFeatures {
        viewBinding = true
    }


    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }


    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}
dependencies {
    implementation(Dependencies.Libraries.kotlin)
    implementation(Dependencies.Libraries.coreKTX)
    implementation(Dependencies.Libraries.appCompat)
    implementation(Dependencies.Libraries.constraintLayout)
    implementation(Dependencies.Libraries.legacySupport)

    /*
    arch components
     */
    implementation(Dependencies.Libraries.concurrent)
    implementation(Dependencies.Libraries.viewModel)
    implementation(Dependencies.Libraries.liveData)
    implementation(Dependencies.Libraries.lifeCycleCommon)
    implementation(Dependencies.Libraries.activity)
    /*
    arch components
     */


    /*
    Hilt
     */
    implementation(Dependencies.Libraries.hilt)
    kapt(Dependencies.Libraries.hiltCompiler)
    implementation(Dependencies.Libraries.hiltAndroid)
    /*
    Hilt
     */
    debugImplementation(Dependencies.Libraries.leakCanary)


    /*
    Test libs
     */
    androidTestImplementation(Dependencies.Libraries.Test.espressoCore)
    androidTestImplementation(Dependencies.Libraries.Test.espressoContrib)
    androidTestImplementation(Dependencies.Libraries.Test.espressoIntents)
    androidTestImplementation(Dependencies.Libraries.Test.espressoAccessibility)
    androidTestImplementation(Dependencies.Libraries.Test.espressoWeb)
    androidTestImplementation(Dependencies.Libraries.Test.espressoIdlingConcurrent)
    testImplementation(Dependencies.Libraries.Test.jUnit)
    /*
    Test libs
     */
}

گریدل رو سینک کنید! کار شما تموم شد و گردیل شما مرتبه و هندل کردن اطلاعات آسون تر شده و به راحتی میتونید نسخه هارو تغییر بدید!

نکته مهم: چینش کانفیگ شما به این صورت کاری زمان بر و وقت گیره! برای راحتی کار از این پلاگین استفاده کنید:

https://github.com/jmfayard/refreshVersions


اگه پیشنهادی، انتقادی یا سوالی داشتید در کامنت ها واسم بنویسید!