Build Variant — build type และ product flavor ใน Android คืออะไร

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-30 เวลาอ่าน: 9 นาที

Build Variant ในการพัฒนา Android คือการรวมกันของ build type และ product flavor ซึ่งกำหนดว่า APK หรือ AAB จะถูกสร้างอย่างไร: ด้วยพารามิเตอร์ ทรัพยากร และโค้ดใดบ้าง แต่ละ build variant แสดงค่าการกำหนดค่า Gradle แยกต่างหากแยกกับ applicationId ของตนเอง คีย์ลงนาม และโดยประกอบที่เพิ่มเข้ามา ตามแหล่งข้อมูล Google Android Developers, 2025 การกำหนดค่า Build Variants อย่างถูกต้องช่วยลดเวลา build ได้มากถึง 40% โดยการยกเว้นทรัพยากรที่ไม่จำเป็นสำหรับแต่ละ variant ระบบ build variant เป็นรากฐานของการจัดการกำหนดค่าในโปรเจกต์ Android สมัยใหม่

ข้อสำคัญ

  • Build Variant — การรวมกันของหนึ่ง Build Type และหนึ่ง Product Flavor
  • Build Type กำหนดโหมดการ build: debug หรือ release
  • Product Flavor กำหนดเวอร์ชันแอป: free, paid, demo, enterprise
  • Gradle สร้างงานโดยอัตโนมัติสำหรับแต่ละ Build Variant รวมถึง install และ assemble
  • ทรัพยากรและโค้ด สามารถถูกแทนที่สำหรับแต่ละ variant ผ่าน source sets ที่สอดคล้องกัน

Build Variant คืออะไร?

Build Variant คือผลลัพธ์ของการรวมหนึ่ง Build Type และหนึ่ง Product Flavor หากไม่มีการกำหนด Product Flavor ในโปรเจกต์ Build Variant จะตรงกับ Build Type Gradle จะสร้างชุดของ variant ที่สมบูรณ์โดยอัตโนมัติเป็นผลคูณแบบคาร์เทเซียนของ FlavorDimensions, Product Flavors และ Build Types ทั้งหมด ตัวอย่างเช่น, สำหรับ free/paid flavors และ debug/release types จะมี 4 variant ถูกสร้าง: freeDebug, freeRelease, paidDebug, paidRelease

แต่ละ Build Variant ได้รับชื่อของตนเองในรูปแบบ <Flavor><Type> โดย flavor ขึ้นต้นด้วยตัวพิมพ์ใหญ่ Gradle สร้างงานแยกต่างสำหรับ variant นี้: assembleFreeDebug, installFreeDebug, bundleFreeRelease ใน Android Studio การสลับระหว่าง variant สามารถทำได้ผ่านแผง Build Variants (View → Tool Windows → Build Variants) การเลือก variant มีผลต่อโค้ดที่จะถูกคอมไพล์ ทรัพยากรที่จะถูกรวม และ APK/AAB ใดที่จะถูกผลิต

ระบบ Build Variants แก้ไขระบสามงานหลัก: แยกการกำหนดค่าสำหรับสภาพแวดล้อมที่แตกต่างกัน (dev/staging/production), สร้างหลายเวอร์ชันของแอป (free/paid) และการทดสอบ A/B ของ build หากไม่มี Build Variants นักพัฒนาจะต้องเปลี่ยนแบบ flag และการกำหนดค่าด้วยตนเอง ซึ่งนำไปสู่ข้อผิดพลาดของปัจจัยมนุษย์ ตามการศึกษาโดย Gradle Inc., 2024 การนำ Build Variants ไปใช้ช่วยลดข้อผิดพลาดของ build ได้ 60% ในโปรเจกต์ที่มีสามสภาพแวดล้อมการประการใช้งานหรือมากกว่า

Gradle สร้าง variant อย่างไร

AGP (Android Gradle Plugin) คำนวณการรวมกันทั้งหมดในขั้นตอนการกำหนดค่า หากโปรเจกต์มีสองมิติที่มีสองและสาม flavor ตามลำดับ Gradle จะสร้าง 2 × 2 × 3 = 12 การรวมกัน คูณด้วยจำนวน Build Types (โดยปกติ่ 2) แต่ละการรวมกันได้รับชื่อที่ไม่ซ้ำและชุดงาน AGP เพิ่ม source set โดยอัตโนมัติสำหรับแต่ละ variant: src/freeDebug/, src/paidRelease/ รวมทั้งทั้วไป src/free/ และ src/debug/ ลำดับความสำคัญในการอ่านทรัพยากร: variant → flavor → type → main

groovy
// ตัวอย่าง: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// รวม: 2 × 2 × 2 = 8 variant

android {
    flavorDimensions "version", "server"

    productFlavors {
        demo { dimension "version" }
        prod { dimension "version" }
        mock { dimension "server" }
        live { dimension "server" }
    }
}

Build Type และ Product Flavor: ความแตกต่าง

Build Type กำหนดวิธีการสร้างแอปลิเคชัน — มีหรือไม่มีข้อมูล debug, มีหรือไม่มีการเพิ่มเติมประสิทธิภาพ, ด้วยลายเซ็นใด Product Flavor กำหนดว่าจะสร้างอะไร — เวอร์ชันไหนของผลิตภัณฑ์ Build Type เป็นกลไกการ build (debug, release, staging) Product Flavor เป็นตัวแปรของผลิตภัณฑ์ (free, paid, enterprise, demo) ทั้งสองแนวคิดเป็นอิสระ: Build Type ใดก็สามารถใช้กับ Product Flavor ใดก็ได้

Build Types เริ่มต้นรวมถึง debug (debuggable=true, minification=false, signing=debug.keystore) และ release (debuggable=false, minification=true, signing=production.keystore) Product Flavor เริ่มต้นคือหนึ่ง ไม่มีชื่อ (โดยพฤติเป็น main source set) นักพัฒนาสามารถเพิ่ม Build Types ของตนเอง (ตัวอย่าง “staging” ที่มี debuggable=true และ minification=true) และ Product Flavors จำนวนใดก็ได้ ข้อแตกต่างอีกอย่างคือ Build Type ไม่สามารถจัดกลุ่มเป็นมิติ แต่ Product Flavor สามารถ

ข้อแตกต่างในทางปฏิบัติหลัก: defaultConfig ใน build.gradle ใช้กับทุก Variants แต่สามารถถูกแทนที่ใน productFlavors และ buildTypes BuildConfigField ที่เพิ่มใน buildType จะมองเห็นในทุก flavor ของชนิดนั้น ในขณะที่เพิ่มใน productFlavor จะมองเห็นในทุกชนิดของ flavor นั้น หากกำหนดฟิลด์ในทั้งสองที่ buildType จะได้รับความสำคัญ (ใช้เป็นตัวสุดท้ายในโบ)

ตารางเปรียบเทียบ

ลักษณะBuild TypeProduct Flavor
วัตถุประสงค์วิธีการ buildสิ่งที่จะ build
ตัวอย่างdebug, release, stagingfree, paid, demo, enterprise
ค่าเริ่มต้นdebug + releaseหนึ่ง (main)
Source Setsrc/debug/, src/release/src/free/, src/paid/
มิติไม่flavorDimensions
ลำดับการใช้หลัง flavor, แทนที่หลัง defaultConfig
BuildConfigFieldแทนที่ flavorแทนที่ defaultConfig

การกำหนดค่า Build Variants ใน build.gradle

ลำดับความสำคัญของการกำหนดค่า

การกำหนดค่า Build Variants ทำในบล็อก android ของไฟล์ build.gradle ระดับโมดูล แรกแถลง buildTypes กัพารามิเตอร์ของพวกมัน จากนั้น flavorDimensions และ productFlavors Gradle สร้าง variant โดยอัตโนมัติจากการแถลงเหล่านั้น แต่ละ variant สืบทอด defaultConfig ของโมดูล โดยแทนที่ฟิลด์ที่ระบุ ลำดับการแถลงมีผลต่อลำดับความสำคัญ: buildTypes ถูกใช้หลัง productFlavors

เพื่อเข้าถึง Build Variant เฉพาะเจาะจงในสคริปต์ Gradle ใช้ android.applicationVariants (สำหรับโมดูล app) หรือ android.libraryVariants (สำหรับโมดูลไลบรารี) นี่เป็นกลุ่มที่สามารถวนซ้ำเพื่อแก้ไขการกำหนดค่าของแต่ละ variant ในระที่การกำหนดค่าทำงาน ตัวอย่างเช่น, คุณสามารถเพิ่ม buildConfigField โดยเป็นโปรแกรมสำหรับทุก variant ที่มีคำ “demo”

Android Gradle Plugin 8.x เพิ่มการสนับสนุน onVariants — API ที่สะอาดขึ้นสำหรับการกำหนดค่า variant ผ่าน lambdas API เก่า (variantOutput, variantFilter) ถูกทำเครื่องหมายว่าเลือกใช้ไม่แนะนำให้ใช้ onVariants ร่วมกับ onEach สำหรับโมดูลไลบรารี การย้ายจาก variantOutput ไปยัง onVariants เป็นขั้นตอนที่แนะนำเมื่ออัปเกรด AGP จาก 7.x เป็น 8.x

groovy
android {
    buildTypes {
        debug {
            debuggable true
            minification false
            signingConfig signingConfigs.debug
        }
        release {
            debuggable false
            minification true
            proguardFiles "proguard-rules.pro"
            signingConfig signingConfigs.release
        }
        staging {
            debuggable true
            minification true
            versionNameSuffix "-staging"
        }
    }

    flavorDimensions "tier", "region"

    productFlavors {
        free { dimension "tier" }
        paid { dimension "tier" }
        us { dimension "region" }
        eu { dimension "region" }
    }
}

android.onVariants { variant ->
    if (variant.name.contains("Demo")) {
        variant.setEnabled(false)
    }
}

Source Sets และการแทนที่ทรัพยากร

แต่ละ Build Variant ได้รับลำดับชั้นของ source sets ของตนเอง — ไดเร็กทอรีที่มีโค้ดต้นฉบับ, ทรัพยากร และแมนิเฟสต์ source set อยู่ที่ src/<variantName>/ (ตัวอย่าง src/freeDebug/) และสามารถมี java/, res/, AndroidManifest.xml, assets/ หากไฟล์มีอยู่ใน source set ของ variant ไฟล์นั้นจะแทนที่ไฟล์ชื่อเดียวกันจาก source set หลัก (src/main/) สำหรับทรัพยากร จะมีการรวมกันแทนที่จะเป็นการแทนที่ — ระบบจะรวมทรัพยากรจากทุก source sets ที่เปิดใช้งาน โดยให้ความสำคัญกับที่เฉพาะของ variant

Source sets สำหรับ Build Variant ถูกสร้างเป็นโส: src/main/src/flavor/src/type/src/flavorType/ ตัวอย่างเช่น, สำหรับ paidRelease ใช้ main ก่อน, จากนั้น paid, จากนั้น release, จากนั้น paidRelease แต่ละ source set ถัดไปแทนที่อันก่อนหน้า ซึ่งหมายความว่า src/release/res/values/strings.xml จะแทนที่ string เดียวกันจาก src/paid/ แต่ src/paidRelease/res/ มีความสำคัญมากกว่า

การใช้ source sets สำหรับ variant เป็นวิธีที่แนะนำในการปรับแต่งทรัพยากร แทนที่จะตรวจสอบ BuildConfig.FLAVOR ในโค้ดและแยกสาขาโลจิก คุณสามารถวางไฟล์แตกต่างกันใน source sets แตกต่างกัน ตัวอย่างเช่น, ไอคอนสำหรับรุ่น free และ paid ไปใน src/free/res/ และ src/paid/res/ ตามลำดับ และ AndroidManifest ที่มีสิทธิ์แตกต่างกันไปใน src/free/AndroidManifest.xml และ src/paid/AndroidManifest.xml วิธีนี้สะอาดกว่า, ไวกว่า (ทรัพยากรถูกคอมไพล์, ไม่ได้ตรวจสอบขณะทำงาน) และปลอดภัยกว่า (คุณไม่สามารถเกิดการรวมฟีเจอร์แบบเสียค่าในรุ่นฟรีโดยบังเอิญจากข้อผิดพลาดในโค้ด)

Build Variant ในโปรเจกต์หลายโมดูล

ในโปรเจกต์หลายโมดูล แต่ละโมดูล (ไลบรารี) สามารถมี Build Variants ของตนเอง AGP จะซังโครไนซ์ variant โดยอัตโนมัติ: หากโมดูล app สร้าง paidRelease ไลบรารีที่ขึ้นอยู่กับก็จะถูกสร้างใน variant ที่ตรงกับ paidRelease เช่นกัน ปัญหาเกิดขึ้นเมื่อไลบรารีไม่มี product flavors แต่โมดูล app มี — จะสร้างไลบรารีหนึ่งครั้ง (release หรือ debug ขึ้นอยู่กับชนิด)

สำหรับโมดูลไลบรารี Build Variant โดยค่าเริ่มต้นจะตรงกับ Build Type ของโมดูล app เพราะไลบรารีไม่มี product flavors หากไลบรารีจำเป็นต้องปรับตัวให้เข้ากับ flavor ของโมดูล app ต้องประกาศ flavorDimensions และ productFlavors เดียวกันในไลบรารี AGP จับคู่ flavor โดยชื่อที่ตรงกันแท้ Gradle แนะนำให้ซังโครไนซ์ flavor ผ่านการกำหนดค่า build ในโปรเจกต์รากโดยใช้ subprojects หรือ Convention Plugins

เริ่มต้นแต่ AGP 8.1 ไลบรารีสามารถเผยแพร่ multiple variants — เผยแพร่ variant ทั้งหมดของไลบรารีไปยังคลัง maven พร้อมกัน วิธีนี้แก้ปัญหาเมื่อโมดูล app ใช้ flavor แบบเสียค่าแต่ไลบรารีเผยแพร่เฉพาะรุ่นฟรี Multiple variants publishing (MVP) ช่วยให้โปรเจกต์ที่ขึ้นอยู่เลือก variant ที่ต้องการโดยอัตโนมัติ เพื่อเปิดใช้ MVP ให้เพิ่ม publishing { multipleVariants { ... } } ใน build.gradle ของไลบรารี

การกรองและเปิดใช้งาน Variants

การกรองแบบไดนามิกผ่าน CI/CD

บางครั้งจำเป็นต้องเปิดใช้งาน Build Variants บางส่วน — ตัวอย่างเช่น, หากการรวมกัน mockRelease ไม่มีความหมาย (เซิิร์ฟเวอร์จำลองไม่ควรไปที่ระบบ production) Gradle มี variantFilter — บล็อก DSL ที่คุณสามารถตรวจสอบคุณสมบัติของแต่ละ variant และเปิดใช้งานผ่าน setIgnore(true) VariantFilter ถูกใช้ในขั้นตอนการกำหนดค่า ก่อนการสร้างงาน ดังนั้น variant ที่ถูกเปิดใช้งานจะไม่สร้างงาน assemble และ install

การกรองก็มีประโยชน์ในการเร่ง build หากโปรเจกต์มี 8 variant แต่นักพัฒนาทำงานเฉพาะหนึ่ง variant ส่วนที่เหลือ 7 variant ยังคงต้องผ่านการกำหนดค่า เมื่อใช้ variantFilter variant ที่ถูกเปิดใช้งานจะไม่สร้างงาน ซึ่งช่วยลดเวลาการกำหนดค่าได้ 30-50% สำหรับโปรเจกต์ที่มี 6+ flavor dimensions ใน CI/CD คุณสามารถกรอง variant แบบไดนามิกผ่านพารามิเตอร์บรรทัดคำสั่ง -PbuildOnly=paidRelease

groovy
android {
    variantFilter { variant ->
        // ปิดใช้งาน mock สำหรับ release และ demo สำหรับ production
        def names = variant.flavors*.name
        def isMock = names.contains("mock")
        def isDemo = names.contains("demo")
        def isRelease = variant.buildType.name == "release"

        if ((isMock && isRelease) || (isDemo && !isMock)) {
            variant.setIgnore(true)
        }
    }
}

// การกรองแบบไดนามิกผ่านพารามิเตอร์
if (project.hasProperty("buildOnly")) {
    def target = project.property("buildOnly")
    android.variantFilter { variant ->
        variant.setIgnore(variant.name != target)
    }
}

คำถามที่พบบ่อย

สามารถสร้าง Build Variants ได้กี่แบบ?

ไม่มีขๅอจำกัด แต่ Gradle สร้าง ผลคูณแบบคาร์เทเซียน ของ flavor และชนิดทั้งหมด หากคุณมี 3 มิติ แต่ละมิติมี 3 flavor และ 3 build types คุณจะได้ 27 variant การมี variant มากเกินไปจะทำให้การกำหนดค่าช้าลง แนะนำไม่ให้มีเกิน 10–12 variant ในหนึ่งโมดูล

ทำไมต้องมี flavorDimensions?

flavorDimensions จัดกลุ่ม Product Flavors เป็นแกนอิสระ ตัวอย่างเช่น, มิติ “tier” (free, paid) และมิติ “region” (us, eu) หากไม่มีมิติ flavor ทั้งหมดจะอยู่ในแกนเดียวกัน และ Gradle จะเลือกเฉพาะหนึ่ง flavor จากทั้งหมด (คุณไม่สามารถมี free+us และ paid+eu เป็น variant แยกต่างกัน)

จะแทนที่ applicationId สำหรับ variant ได้อย่างไร?

ในบล็อก productFlavor หรือ buildType ระบุ applicationId ตัวอย่างเช่น, สำหรับรุ่นฟรี: free { applicationId “com.example.app.free” } ในแมนิเฟสต์ ใช้ ${applicationId} — Gradle จะแทนที่ค่าโดยอัตโนมัติ วิธีนี้ทำให้สามารถติดตั้งทั้งสอง variant บนเครื่องเดียวกัน

สามารถใช้ Build Variants ใน iOS ได้หรือไม่?

ใน iOS สิ่งที่เทียบเท่ากับ Build Variants คือการรวมกันของ Scheme + Configuration Xcode Schemes ถูกกำหนดค่าผ่านค่ากำหนด Debug/Release ที่มีพารามิเตอร์แตกต่างกัน สำหรับหลายเวอร์ชัน (free/paid) ใช้ Build Configurations และ Preprocessor Macros ใน Android แนวคิดนี้ถูกประเบ็นรูปแบบมากกว่าและสร้างไว้ใน Gradle

Build Variant มีผลต่อขนาด APK หรือไม่?

ใช่ แต่ละ variant สามารถมีขนาด APK แตกต่างกันได้ build แบบ debug รวมข้อมูล debug, SDK และ ทรัพยากรที่ไม่รองรับ build แบบ release ที่มี minification และ resource shrinking จะสร้างขนาดที่น้อยที่สุด Product Flavor ก็มีผลต่อขนาด: รุ่นฟรีที่ไม่มีไลบรารีแบบเสียค่าจะมีขนาดเล็กกว่ารุ่นแบบเสียค่าเท่ากับขนาดของไลบรารีเหล่านั้น

สรุป

  • Build Variant — การรวมกันของหนึ่ง Build Type และหนึ่ง Product Flavor ที่กำหนดค่าการกำหนดค่า build
  • Build Type ควบคุมโหมดการคอมไพล์ (debug/release/staging) ในขณะที่ Product Flavor ควบคุมเวอร์ชันของผลิตภัณฑ์ (free/paid)
  • Source sets ช่วยให้สามารถแทนที่โค้ด ทรัพยากร และแมนิเฟสต์สำหรับแต่ละ build variant
  • VariantFilter เปิดใช้งานการรวมกันที่ไม่จำเป็น เร่งการกำหนดค่า Gradle ได้ 30–50%
  • โปรเจกต์หลายโมดูล ต้องการการซังโครไนซ์ flavor ในทุกโมดูลหรือ multiple variants publishing
  • BuildConfigField และ source sets เป็นสองวิธีที่สะอาดในการปรับแต่งพฤติกรรมระหว่าง variant
  • คำแนะนำ: อย่าสร้าง variant เกิน 10–12 รายการในหนึ่งโปรเจกต์ จัดกลุ่มมิติอย่างมีความหมาย

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม