ปรับแต่งทรัพยากรที่จะเก็บไว้

เมื่อคุณเปิดใช้การเพิ่มประสิทธิภาพแอป การตั้งค่า 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 จะผสานทรัพยากรที่ซ้ำกันตามลําดับความสําคัญแบบซ้อนทับต่อไปนี้

Dependency → Main → Build flavor → Build type

ตัวอย่างเช่น หากทรัพยากรที่ซ้ำกันปรากฏทั้งในทรัพยากรหลักและรูปแบบการสร้าง 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 เพื่อแจ้งให้ระบบบิลด์นําทรัพยากรออก