โดยปกติแล้ว แอปพลิเคชัน 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 ในโปรเจ็กต์