เมื่อคุณเปิดใช้การเพิ่มประสิทธิภาพแอป การตั้งค่า isShrinkResources = true
จะสั่งให้เครื่องมือเพิ่มประสิทธิภาพนําทรัพยากรที่ไม่ได้ใช้งานออก ซึ่งจะช่วยลดขนาดแอป การลดขนาดทรัพยากรจะทํางานร่วมกับการลดขนาดโค้ดเท่านั้น ดังนั้นหากต้องการเพิ่มประสิทธิภาพทรัพยากร ให้ตั้งค่า isMinifyEnabled = true
ด้วย ตัวอย่างเช่น
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
หากต้องการเก็บหรือทิ้งทรัพยากรที่เฉพาะเจาะจง ให้สร้างไฟล์ keep รูปแบบ XML ในทรัพยากรโปรเจ็กต์ เช่น res/raw/my.package.keep.xml
ไฟล์ keep ประกอบด้วยคอมโพเนนต์ต่อไปนี้
- แท็ก
<resources>
- มีองค์ประกอบทรัพยากรย่อยทั้งหมดและแอตทริบิวต์เก็บ/ทิ้ง - แอตทริบิวต์
tools:keep
- ยอมรับรายการชื่อทรัพยากรที่คั่นด้วยคอมมาซึ่งระบุทรัพยากรที่จะเก็บไว้ - แอตทริบิวต์
tools:discard
- ยอมรับรายการชื่อทรัพยากรที่คั่นด้วยคอมมาซึ่งระบุทรัพยากรที่จะทิ้ง
ใช้อักขระดอกจันเป็นไวลด์การ์ดเพื่ออ้างอิงทรัพยากรหลายรายการในโฟลเดอร์เดียวกัน เช่น
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
การระบุทรัพยากรที่จะทิ้งอาจดูไม่จำเป็นเมื่อคุณลบทรัพยากรเหล่านั้นได้ แต่การทิ้งทรัพยากรจะมีประโยชน์เมื่อใช้ตัวแปรของบิลด์
กําหนดเป้าหมายตัวแปรของบิวด์ที่เฉพาะเจาะจง
หากต้องการนำทรัพยากรในตัวแปรการสร้างบางรายการออก ให้ใส่ทรัพยากรทั้งหมดในไดเรกทอรีโปรเจ็กต์ทั่วไป จากนั้นสร้างไฟล์ my.package.build.variant.keep.xml
ไฟล์อื่นสำหรับตัวแปรการสร้างแต่ละรายการในไดเรกทอรีทรัพยากรของตัวแปร ในไฟล์ keep ให้ระบุทรัพยากรที่จะนําออกด้วยตนเองเมื่อดูเหมือนว่าทรัพยากรหนึ่งๆ จะใช้ในโค้ด (และด้วยเหตุนี้จึงไม่มีการนําออกโดยเครื่องมือลดขนาด) แต่คุณทราบว่าจริงๆ แล้วจะไม่มีการใช้ทรัพยากรนั้นกับตัวแปรบิลด์หนึ่งๆ
นำทรัพยากรทางเลือกที่ไม่ได้ใช้ออก
เครื่องมือเพิ่มประสิทธิภาพจะนำเฉพาะทรัพยากรที่ไม่ได้อ้างอิงโดยโค้ดแอปออก ซึ่งหมายความว่าจะไม่นำทรัพยากรทางเลือกสำหรับการกำหนดค่าอุปกรณ์ที่แตกต่างกันออก
ใช้พร็อพเพอร์ตี้ resConfigs
ของ Android Gradle ในไฟล์ build.gradle
โมดูลของแอปเพื่อนำไฟล์ทรัพยากรทางเลือกที่แอปไม่ต้องการออก
ตัวอย่างเช่น หากคุณใช้ไลบรารีที่มีทรัพยากรภาษา (เช่น Google Play Services) แอปของคุณจะมีสตริงภาษาที่แปลแล้วทั้งหมดสำหรับข้อความในไลบรารีเหล่านั้น ไม่ว่าส่วนที่เหลือของแอปจะแปลเป็นภาษาเดียวกันหรือไม่ก็ตาม หากต้องการเก็บเฉพาะภาษาที่แอปรองรับอย่างเป็นทางการ ให้ระบุภาษาเหล่านั้นโดยใช้พร็อพเพอร์ตี้ resConfigs
ระบบจะนำทรัพยากรสำหรับภาษาที่ไม่ได้ระบุออก
ตัวอย่างต่อไปนี้แสดงวิธีจำกัดทรัพยากรภาษาไว้ที่ภาษาอังกฤษและฝรั่งเศสเท่านั้น
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
หรือ
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
เมื่อคุณเผยแพร่แอปโดยใช้รูปแบบ Android App Bundle (AAB) ระบบจะดาวน์โหลดเฉพาะภาษาที่กําหนดค่าไว้ในอุปกรณ์ของผู้ใช้โดยค่าเริ่มต้นเมื่อผู้ใช้ติดตั้งแอป ในทํานองเดียวกัน ระบบจะรวมเฉพาะทรัพยากรที่ตรงกับความหนาแน่นของหน้าจอของอุปกรณ์และไลบรารีเนทีฟที่ตรงกับ ABI ของอุปกรณ์ไว้ในการดาวน์โหลด ดูข้อมูลเพิ่มเติมได้ที่เปิดหรือปิดใช้ APK การกำหนดค่าประเภทต่างๆ อีกครั้ง
สำหรับแอปเดิมที่เผยแพร่ด้วย APK (สร้างขึ้นก่อนเดือนสิงหาคม 2021) คุณสามารถปรับแต่งทรัพยากรความหนาแน่นของหน้าจอหรือ ABI เพื่อรวมไว้ใน APK ได้โดยสร้าง APK หลายรายการที่กำหนดเป้าหมายเป็นการกำหนดค่าอุปกรณ์ที่แตกต่างกัน
หลีกเลี่ยงความขัดแย้งเมื่อผสานทรัพยากร
โดยค่าเริ่มต้น ปลั๊กอิน Android Gradle (AGP) จะผสานทรัพยากรที่มีชื่อเหมือนกัน เช่น ทรัพยากรที่วาดได้ซึ่งมีชื่อเดียวกันซึ่งอยู่ในโฟลเดอร์ทรัพยากรที่แตกต่างกัน
พร็อพเพอร์ตี้ shrinkResources
ไม่ได้ควบคุมลักษณะการทํางานนี้และปิดใช้ไม่ได้ เนื่องจากลักษณะการทํางานนี้จําเป็นเพื่อหลีกเลี่ยงข้อผิดพลาดเมื่อทรัพยากรหลายรายการมีชื่อเดียวกับที่โค้ดของคุณอ้างอิง
การผสานทรัพยากรจะเกิดขึ้นก็ต่อเมื่อไฟล์ตั้งแต่ 2 ไฟล์ขึ้นไปใช้ชื่อ ประเภท และตัวระบุทรัพยากรที่เหมือนกัน AGP จะเลือกไฟล์ที่ระบุว่าเป็นตัวเลือกที่ดีที่สุดจากไฟล์ที่ซ้ำกัน (ตามลําดับความสําคัญที่อธิบายไว้ด้านล่าง) และส่งทรัพยากรเพียงรายการเดียวนั้นไปยัง AAPT เพื่อเผยแพร่ในอาร์ติแฟกต์บิลด์สุดท้าย
AGP จะค้นหาทรัพยากรที่ซ้ำกันในส่วนต่อไปนี้
- แหล่งข้อมูลหลักที่เชื่อมโยงกับชุดแหล่งข้อมูลหลัก ซึ่งโดยทั่วไปจะอยู่ใน
src/main/res/
- การซ้อนทับตัวแปรจากประเภทบิลด์และตัวแปรของบิลด์
- ทรัพยากร Dependency ของโครงการห้องสมุด
AGP จะผสานทรัพยากรที่ซ้ำกันตามลําดับความสําคัญแบบซ้อนทับต่อไปนี้
ตัวอย่างเช่น หากทรัพยากรที่ซ้ำกันปรากฏทั้งในทรัพยากรหลักและรูปแบบการสร้าง Gradle จะเลือกทรัพยากรในรูปแบบการสร้าง
หากทรัพยากรที่เหมือนกันปรากฏในชุดแหล่งที่มาเดียวกัน Gradle จะผสานไม่ได้และแสดงข้อผิดพลาดการผสานทรัพยากร กรณีนี้อาจเกิดขึ้นได้หากคุณกำหนดชุดแหล่งที่มาหลายชุดในพร็อพเพอร์ตี้ sourceSet
ของไฟล์โมดูล build.gradle
เช่น หากทั้ง src/main/res/
และ src/main/res2/
มีทรัพยากรที่เหมือนกัน
แก้ปัญหาการลดขนาดทรัพยากร
เมื่อคุณลดขนาดทรัพยากร หน้าต่างสร้างจะแสดงข้อมูลสรุปของทรัพยากรที่นําออกจากแอป (คลิกสลับมุมมองทางด้านซ้ายของหน้าต่างเพื่อแสดงเอาต์พุตข้อความแบบละเอียดจาก Gradle) เช่น
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle จะสร้างไฟล์การวินิจฉัยชื่อ resources.txt
ใน <module-name>/build/outputs/mapping/release/
ด้วย (โฟลเดอร์เดียวกับไฟล์เอาต์พุตของ ProGuard) ไฟล์จะมีรายละเอียด เช่น ทรัพยากรใดอ้างอิงทรัพยากรอื่นๆ และทรัพยากรใดที่ใช้หรือนําออก
เช่น หากต้องการดูสาเหตุที่ @drawable/ic_plus_anim_016
ยังอยู่ในแอป ให้เปิดไฟล์ resources.txt
แล้วค้นหาชื่อไฟล์นั้น คุณอาจพบว่ามีการอ้างอิงจากแหล่งข้อมูลอื่น
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
ตอนนี้คุณต้องทราบว่าเหตุใด @drawable/add_schedule_fab_icon_anim
จึงเข้าถึงได้ หากค้นหาขึ้นด้านบน คุณจะเห็นแหล่งข้อมูลที่แสดงอยู่ใต้ส่วนหัวแหล่งข้อมูลที่เข้าถึงได้ของรูทมีดังนี้ ใน resources.txt
ซึ่งหมายความว่ามีโค้ดอ้างอิงถึง add_schedule_fab_icon_anim
กล่าวคือ พบรหัส R.drawable
ของ add_schedule_fab_icon_anim
ในโค้ดที่เข้าถึงได้
คุณสามารถทําเครื่องหมายรหัสทรัพยากรว่าเข้าถึงได้หากมีสตริงคงที่ที่ดูเหมือนว่าอาจใช้ในการสร้างชื่อทรัพยากรสําหรับทรัพยากรที่โหลดแบบไดนามิก เว้นแต่คุณจะใช้การตรวจสอบแบบเข้มงวด ในกรณีนี้ หากคุณค้นหาชื่อทรัพยากรในเอาต์พุตการสร้าง คุณอาจเห็นข้อความดังต่อไปนี้
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because its format-string matches string pool constant ic_plus_anim_%1$d.
หากเห็นสตริงใดสตริงหนึ่งเหล่านี้และมั่นใจว่าไม่มีการใช้สตริงดังกล่าวเพื่อโหลดทรัพยากรที่ระบุแบบไดนามิก ให้ใช้แอตทริบิวต์ tools:discard
ในไฟล์ keep เพื่อแจ้งให้ระบบบิลด์นําทรัพยากรออก