ภาพรวมของบิลด์ Gradle

โดยปกติแล้ว แอปพลิเคชัน Android จะสร้างขึ้นโดยใช้ระบบบิลด์ Gradle ก่อนที่จะเจาะลึกรายละเอียดเกี่ยวกับวิธีกำหนดค่าบิลด์ เราจะอธิบายแนวคิดเบื้องหลังของบิลด์เพื่อให้คุณเห็นภาพรวมของระบบ

บิลด์คืออะไร

ระบบบิลด์จะเปลี่ยนซอร์สโค้ดของคุณเป็นแอปพลิเคชันที่เรียกใช้ได้ การสร้างมักเกี่ยวข้องกับเครื่องมือหลายอย่างเพื่อวิเคราะห์ คอมไพล์ ลิงก์ และแพ็กเกจแอปพลิเคชันหรือไลบรารี Gradle ใช้แนวทางแบบงานเพื่อจัดระเบียบและเรียกใช้คำสั่งเหล่านี้

งานจะรวมคำสั่งที่แปลอินพุตเป็นเอาต์พุต ปลั๊กอินจะกำหนดงานและการกําหนดค่า การใช้ปลั๊กอินกับบิลด์จะลงทะเบียนงานของปลั๊กอิน และเชื่อมต่อปลั๊กอินเข้าด้วยกันโดยใช้อินพุตและเอาต์พุต ตัวอย่างเช่น การใช้ ปลั๊กอิน Android Gradle (AGP) กับไฟล์บิลด์จะลงทะเบียนงานทั้งหมดที่จำเป็นต่อการสร้าง APK หรือไลบรารี Android ปลั๊กอิน java-library ช่วยให้คุณสร้างไฟล์ jar จากซอร์สโค้ด Java ได้ มีปลั๊กอินที่คล้ายกันสำหรับ Kotlin และภาษาอื่นๆ แต่ปลั๊กอินอื่นๆ มีไว้เพื่อขยายการทำงาน เช่น ปลั๊กอิน protobuf มีไว้เพื่อเพิ่มการรองรับ protobuf ลงในปลั๊กอินที่มีอยู่ เช่น AGP หรือ java-library

Gradle ให้ความสำคัญกับรูปแบบมากกว่าการกำหนดค่าเพื่อให้ปลั๊กอินมีค่าเริ่มต้นที่ดีอยู่แล้ว แต่คุณกำหนดค่าการสร้างเพิ่มเติมได้ผ่านภาษาเฉพาะโดเมน (DSL) แบบประกาศ DSL ได้รับการออกแบบมาเพื่อให้คุณระบุสิ่งที่จะสร้างได้ แทนที่จะระบุวิธีสร้าง ตรรกะในปลั๊กอินจะจัดการ "วิธี" การกำหนดค่าดังกล่าวระบุไว้ในไฟล์บิลด์หลายไฟล์ในโปรเจ็กต์ (และโปรเจ็กต์ย่อย)

อินพุตของงานอาจเป็นไฟล์และไดเรกทอรี รวมถึงข้อมูลอื่นๆ ที่เข้ารหัสเป็นประเภท Java (จำนวนเต็ม สตริง หรือคลาสที่กำหนดเอง) เอาต์พุตต้องเป็นไดเรกทอรีหรือไฟล์เท่านั้น เนื่องจากต้องเขียนลงในดิสก์ การต่อสายเอาต์พุตของงานเข้ากับอินพุตของงานอื่นจะลิงก์งานเข้าด้วยกันเพื่อให้งานหนึ่งต้องทำงานก่อนอีกงานหนึ่ง

แม้ว่า Gradle จะรองรับการเขียนโค้ดและประกาศงานแบบกำหนดเองในไฟล์บิลด์ แต่การดำเนินการนี้อาจทำให้เครื่องมือเข้าใจบิลด์และคุณดูแลรักษาได้ยากขึ้น ตัวอย่างเช่น คุณสามารถเขียนการทดสอบสําหรับโค้ดภายในปลั๊กอินได้ แต่จะเขียนในไฟล์บิลด์ไม่ได้ แต่คุณควรจำกัดประกาศตรรกะการสร้างและงานไว้สำหรับปลั๊กอิน (ที่คุณหรือผู้อื่นกำหนด) และประกาศว่าต้องการใช้ตรรกะนั้นอย่างไรในไฟล์บิลด์

จะเกิดอะไรขึ้นเมื่อการบิลด์ Gradle ทำงาน

บิลด์ Gradle ทำงานใน 3 ระยะ แต่ละระยะจะดำเนินการกับโค้ดส่วนต่างๆ ที่คุณกำหนดไว้ในไฟล์บิลด์

  • การเริ่มต้นจะกำหนดว่าโปรเจ็กต์และโปรเจ็กต์ย่อยใดที่จะรวมอยู่ในบิลด์ และตั้งค่าเส้นทางที่มีไฟล์บิลด์และปลั๊กอินที่ใช้ ระยะนี้มุ่งเน้นที่ไฟล์การตั้งค่าที่คุณประกาศโปรเจ็กต์ที่จะสร้างและตำแหน่งที่จะดึงข้อมูลปลั๊กอินและไลบรารี
  • การกําหนดค่าจะลงทะเบียนงานสําหรับแต่ละโปรเจ็กต์ และเรียกใช้ไฟล์บิลด์เพื่อใช้ข้อกําหนดเฉพาะของบิลด์ของผู้ใช้ โปรดทราบว่าโค้ดการกําหนดค่าจะไม่มีสิทธิ์เข้าถึงข้อมูลหรือไฟล์ที่สร้างขึ้นในระหว่างการดําเนินการ
  • การดำเนินการจะ "สร้าง" แอปพลิเคชันจริง เอาต์พุตของการกำหนดค่าคือ Directed Acyclic Graph (DAG) ของงาน ซึ่งแสดงขั้นตอนการสร้างที่จำเป็นทั้งหมดที่ผู้ใช้ร้องขอ (งานระบุไว้ในบรรทัดคำสั่งหรือเป็นค่าเริ่มต้นในไฟล์บิลด์) กราฟนี้แสดงความสัมพันธ์ระหว่างงาน ซึ่งอาจแสดงอย่างชัดแจ้งในการประกาศของงาน หรืออิงตามอินพุตและเอาต์พุตของงาน หากงานมีอินพุตที่เป็นเอาต์พุตของงานอื่น งานนั้นจะต้องทำงานหลังจากงานอื่น ระยะนี้จะทำงานที่ล้าสมัยตามลำดับที่กําหนดไว้ในกราฟ หากอินพุตของงานไม่มีการเปลี่ยนแปลงนับตั้งแต่การเรียกใช้ครั้งล่าสุด Gradle จะข้ามงานนั้น

ดูข้อมูลเพิ่มเติมได้ที่วงจรการบิลด์ของ Gradle

DSL สำหรับการกําหนดค่า

Gradle ใช้ Domain-Specific Language (DSL) เพื่อกำหนดค่าการสร้าง แนวทางแบบประกาศนี้มุ่งเน้นที่การระบุข้อมูลแทนการเขียนวิธีการทีละขั้นตอน (บังคับ) คุณสามารถเขียนไฟล์บิลด์โดยใช้ Kotlin หรือ Groovy แต่เราขอแนะนําอย่างยิ่งให้ใช้ Kotlin

DSL พยายามทําให้ทุกคน ทั้งผู้เชี่ยวชาญด้านโดเมนและโปรแกรมเมอร์ มีส่วนร่วมในโปรเจ็กต์ได้ง่ายขึ้น โดยกําหนดภาษาขนาดเล็กที่แสดงข้อมูลในลักษณะที่เป็นธรรมชาติมากขึ้น ปลั๊กอิน Gradle สามารถขยาย DSL เพื่อกำหนดค่าข้อมูลที่ต้องใช้สำหรับงานได้

ตัวอย่างเช่น การกําหนดค่าส่วน Android ของบิลด์อาจมีลักษณะดังนี้

Kotlin

android {
    namespace = "com.example.app"
    compileSdk = 34
    // ...

    defaultConfig {
        applicationId = "com.example.app"
        minSdk = 34
        // ...
    }
}

Groovy

android {
    namespace 'com.example.myapplication'
    compileSdk 34
    // ...

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 24
        // ...
    }
}

เบื้องหลัง โค้ด DSL จะคล้ายกับโค้ดต่อไปนี้

fun Project.android(configure: ApplicationExtension.() -> Unit) {
    ...
}

interface ApplicationExtension {
    var compileSdk: Int
    var namespace: String?

    val defaultConfig: DefaultConfig

    fun defaultConfig(configure: DefaultConfig.() -> Unit) {
        ...
    }
}

แต่ละบล็อกใน DSL จะแสดงโดยฟังก์ชันที่ใช้ LAMBDA เพื่อกําหนดค่า และพร็อพเพอร์ตี้ที่มีชื่อเดียวกันเพื่อเข้าถึง วิธีนี้ทำให้โค้ดในไฟล์บิลด์ดูคล้ายข้อมูลจำเพาะมากขึ้น

ทรัพยากร Dependency ภายนอก

ระบบบิลด์ Maven ได้เปิดตัวข้อกำหนด dependency, ระบบพื้นที่เก็บข้อมูล และระบบการจัดการ ไลบรารีจะจัดเก็บไว้ในที่เก็บข้อมูล (เซิร์ฟเวอร์หรือไดเรกทอรี) โดยมีข้อมูลเมตา ซึ่งรวมถึงเวอร์ชันและการพึ่งพาไลบรารีอื่นๆ คุณจะระบุที่เก็บถาวรที่จะค้นหา เวอร์ชันของข้อกำหนดเบื้องต้นที่ต้องการใช้ และระบบการสร้างจะดาวน์โหลดข้อมูลเหล่านั้นระหว่างการสร้าง

อาร์ติแฟกต์ Maven จะระบุด้วยชื่อกลุ่ม (บริษัท นักพัฒนาแอป ฯลฯ) ชื่ออาร์ติแฟกต์ (ชื่อไลบรารี) และเวอร์ชันของอาร์ติแฟกต์นั้น ซึ่งโดยทั่วไปจะแสดงเป็น group:artifact:version

แนวทางนี้ช่วยปรับปรุงการจัดการบิลด์ได้อย่างมาก คุณมักจะได้ยินที่เก็บข้อมูลดังกล่าวเรียกว่า "ที่เก็บ Maven" แต่ที่เก็บข้อมูลเหล่านี้เกี่ยวข้องกับวิธีแพ็กเกจและเผยแพร่อาร์ติแฟกต์ ระบบบิลด์หลายระบบใช้ที่เก็บและข้อมูลเมตาเหล่านี้ซ้ำ ซึ่งรวมถึง Gradle (และ Gradle สามารถเผยแพร่ไปยังที่เก็บเหล่านี้ได้) ที่เก็บข้อมูลสาธารณะอนุญาตให้แชร์กับทุกคน ส่วนที่เก็บข้อมูลของบริษัทจะเก็บข้อมูลที่เกี่ยวข้องภายในไว้

นอกจากนี้ คุณยังแยกโปรเจ็กต์ออกเป็นโมดูลเป็นโปรเจ็กต์ย่อย (หรือที่เรียกว่า "โมดูล" ใน Android Studio) ซึ่งสามารถใช้เป็นข้อกำหนดได้อีกด้วย โปรเจ็กต์ย่อยแต่ละโปรเจ็กต์จะสร้างเอาต์พุต (เช่น Jar) ที่โปรเจ็กต์ย่อยหรือโปรเจ็กต์ระดับบนสุดของคุณนำไปใช้ได้ วิธีนี้จะช่วยปรับปรุงเวลาสร้างโดยแยกส่วนที่จำเป็นต้องสร้างใหม่ออก รวมถึงแยกความรับผิดชอบในแอปพลิเคชันได้ดียิ่งขึ้น

เราจะอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับวิธีระบุการพึ่งพาในหัวข้อเพิ่มการพึ่งพาบิลด์

ตัวแปรของบิลด์

เมื่อสร้างแอปพลิเคชัน Android โดยทั่วไปแล้วคุณจะต้องสร้างตัวแปรหลายรายการ ตัวแปรมีโค้ดที่แตกต่างกันหรือสร้างขึ้นด้วยตัวเลือกที่แตกต่างกัน และประกอบด้วยประเภทบิลด์และตัวแปรผลิตภัณฑ์

ประเภทบิลด์จะแตกต่างกันไปตามตัวเลือกบิลด์ที่ประกาศ โดยค่าเริ่มต้น AGP จะตั้งค่าประเภทบิลด์เป็น "รุ่น" และ "แก้ไขข้อบกพร่อง" แต่คุณสามารถปรับแต่งและเพิ่มประเภทอื่นๆ ได้ (เช่น สําหรับการทดสอบเวอร์ชันหรือทดสอบภายใน)

บิลด์สำหรับการแก้ไขข้อบกพร่องจะไม่ย่อขนาดหรือสร้างความสับสนให้กับแอปพลิเคชัน ซึ่งจะช่วยเร่งความเร็วในการสร้างและเก็บสัญลักษณ์ทั้งหมดไว้เหมือนเดิม นอกจากนี้ยังทำเครื่องหมายแอปพลิเคชันเป็น "แก้ไขข้อบกพร่องได้" ลงนามด้วยคีย์แก้ไขข้อบกพร่องทั่วไป และเปิดใช้การเข้าถึงไฟล์แอปพลิเคชันที่ติดตั้งในอุปกรณ์ ซึ่งทำให้คุณสำรวจข้อมูลที่บันทึกไว้ในไฟล์และฐานข้อมูลขณะเรียกใช้แอปพลิเคชันได้

บิลด์รุ่นจะเพิ่มประสิทธิภาพแอปพลิเคชัน รับรองด้วยคีย์รุ่น และปกป้องไฟล์แอปพลิเคชันที่ติดตั้ง

เมื่อใช้ตัวแปรผลิตภัณฑ์ คุณจะเปลี่ยนแหล่งที่มาและตัวแปรของข้อกำหนดที่รวมไว้สำหรับแอปพลิเคชันได้ เช่น คุณอาจต้องการสร้างตัวแปร "เดโม" และ "เวอร์ชันเต็ม" สําหรับแอปพลิเคชัน หรือตัวแปร "ฟรี" และ "แบบชําระเงิน" คุณจะเขียนแหล่งที่มาทั่วไปในไดเรกทอรีชุดแหล่งที่มา "หลัก" และลบล้างหรือเพิ่มแหล่งที่มาในชุดแหล่งที่มาที่ตั้งชื่อตามรุ่น

AGP จะสร้างตัวแปรสำหรับชุดค่าผสมแต่ละชุดของประเภทบิลด์และตัวแปรผลิตภัณฑ์ หากไม่ได้กำหนด Flavor ระบบจะตั้งชื่อตัวแปรตามประเภทบิลด์ หากคุณกำหนดทั้ง 2 รายการ ระบบจะตั้งชื่อตัวแปรว่า <flavor><Buildtype> ตัวอย่างเช่น เมื่อใช้ประเภทบิลด์ release และ debug รวมถึงตัวแปร demo และ full AGP จะสร้างตัวแปรต่อไปนี้

  • demoRelease
  • demoDebug
  • fullRelease
  • fullDebug

ขั้นตอนถัดไป

เมื่อคุณเห็นแนวคิดการสร้างแล้ว ให้ดูโครงสร้างการสร้าง Android ในโปรเจ็กต์