Khi bạn bật tính năng tối ưu hoá ứng dụng, chế độ cài đặt isShrinkResources = true
sẽ hướng dẫn trình tối ưu hoá xoá các tài nguyên không sử dụng, giúp giảm kích thước ứng dụng. Tính năng rút gọn tài nguyên chỉ hoạt động cùng với tính năng rút gọn mã, vì vậy, nếu bạn đang tối ưu hoá tài nguyên, hãy đặt cả isMinifyEnabled = true
, ví dụ:
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
Nếu bạn muốn giữ lại hoặc loại bỏ tài nguyên cụ thể, hãy tạo tệp giữ lại XML trong tài nguyên dự án, ví dụ: res/raw/my.package.keep.xml
. Tệp keep có các thành phần sau:
- Thẻ
<resources>
– Chứa tất cả phần tử tài nguyên con và thuộc tính giữ lại/loại bỏ. - Thuộc tính
tools:keep
– Chấp nhận danh sách tên tài nguyên được phân tách bằng dấu phẩy để xác định tài nguyên cần giữ lại - Thuộc tính
tools:discard
– Chấp nhận danh sách tên tài nguyên được phân tách bằng dấu phẩy để xác định tài nguyên cần loại bỏ
Sử dụng ký tự dấu hoa thị làm ký tự đại diện để tham chiếu nhiều tài nguyên trong cùng một thư mục, ví dụ:
<?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" />
Bạn có thể cho rằng thật ngớ ngẩn khi chỉ định tài nguyên nào sẽ được huỷ trong khi bạn có thể xoá những tài nguyên này. Tuy nhiên, việc huỷ tài nguyên có thể hữu ích khi sử dụng các biến thể bản dựng.
Nhắm đến các biến thể bản dựng cụ thể
Để xoá tài nguyên chỉ trong một số biến thể bản dựng, hãy đặt tất cả tài nguyên vào thư mục dự án chung, sau đó tạo một tệp my.package.build.variant.keep.xml
khác cho mỗi biến thể bản dựng trong thư mục tài nguyên của biến thể. Trong tệp giữ lại, hãy chỉ định tài nguyên cần xoá theo cách thủ công khi một tài nguyên nhất định có vẻ được sử dụng trong mã (và do đó không bị trình rút gọn xoá), nhưng bạn biết rằng tài nguyên đó thực sự sẽ không được sử dụng cho biến thể bản dựng nhất định.
Xoá tài nguyên thay thế không sử dụng
Trình tối ưu hoá chỉ xoá các tài nguyên không được mã ứng dụng tham chiếu đến, nghĩa là trình tối ưu hoá sẽ không xoá tài nguyên thay thế cho các cấu hình thiết bị khác nhau.
Sử dụng thuộc tính resConfigs
của Android cho Gradle trong tệp build.gradle
của mô-đun ứng dụng để xoá các tệp tài nguyên thay thế mà ứng dụng không cần.
Ví dụ: nếu bạn đang sử dụng một thư viện có chứa tài nguyên ngôn ngữ (chẳng hạn như Dịch vụ Google Play), thì ứng dụng sẽ bao gồm tất cả chuỗi ngôn ngữ đã dịch cho các thông báo trong những thư viện đó bất kể phần còn lại của ứng dụng có được dịch sang cùng một ngôn ngữ hay không. Để chỉ giữ lại những ngôn ngữ mà ứng dụng chính thức hỗ trợ, hãy chỉ định những ngôn ngữ đó bằng thuộc tính resConfigs
.
Mọi tài nguyên của những ngôn ngữ chưa được chỉ định sẽ bị xoá.
Các đoạn mã sau đây cho phép giới hạn tài nguyên ngôn ngữ chỉ còn tiếng Anh và tiếng Pháp:
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
hoặc
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
Khi bạn phát hành ứng dụng bằng định dạng Android App Bundle (AAB), theo mặc định, chỉ những ngôn ngữ được định cấu hình trên thiết bị của người dùng mới được tải xuống khi người dùng cài đặt ứng dụng. Tương tự, chỉ những tài nguyên khớp với mật độ điểm ảnh của thiết bị và thư viện gốc khớp với ABI của thiết bị mới được đưa vào nội dung tải xuống. Để biết thêm thông tin, hãy xem phần Bật lại hoặc tắt các loại APK cấu hình.
Đối với các ứng dụng cũ được phát hành bằng APK (được tạo trước tháng 8 năm 2021), bạn có thể tuỳ chỉnh mật độ màn hình hoặc tài nguyên ABI để đưa vào APK bằng cách tạo nhiều APK nhắm đến các cấu hình thiết bị khác nhau.
Tránh xung đột khi hợp nhất tài nguyên
Theo mặc định, trình bổ trợ Android cho Gradle (AGP) sẽ hợp nhất các tài nguyên có tên giống hệt nhau, chẳng hạn như các đối tượng có thể vẽ có cùng tên nằm trong các thư mục tài nguyên khác nhau.
Thuộc tính shrinkResources
không kiểm soát cũng như không thể kích hoạt hành vi này nhằm tránh lỗi xảy ra khi nhiều tài nguyên có tên khớp với tên đang được tham chiếu trong mã của bạn.
Việc hợp nhất tài nguyên chỉ xảy ra khi hai hoặc nhiều tệp có cùng tên, loại cũng như bộ hạn định (qualifier). AGP sẽ chọn tệp mà nó xác định là lựa chọn tốt nhất trong số các tệp trùng lặp (dựa trên thứ tự ưu tiên được mô tả bên dưới) và chỉ truyền duy nhất tài nguyên đó cho AAPT để phân phối trong cấu phần phần mềm bản dựng cuối cùng.
AGP tìm các tài nguyên trùng lặp ở các vị trí sau:
- Các tài nguyên chính, liên kết với nhóm tài nguyên chính, thường nằm trong
src/main/res/
- Lớp phủ biến thể, từ loại bản dựng và phiên bản của bản dựng
- Phần phụ thuộc dự án thư viện
AGP hợp nhất các tài nguyên trùng lặp theo thứ tự phân tầng ưu tiên như sau:
Ví dụ: nếu một tài nguyên nào đó xuất hiện lặp lại trong cả tài nguyên chính và phiên bản của bản dựng thì Gradle sẽ chọn tài nguyên trong phiên bản của bản dựng.
Nếu các tài nguyên giống hệt nhau xuất hiện trong cùng một nhóm tài nguyên, Gradle không thể hợp nhất các tài nguyên đó và phát sinh lỗi hợp nhất tài nguyên. Điều này có thể xảy ra nếu bạn xác định nhiều nhóm tài nguyên trong thuộc tính sourceSet
của tệp build.gradle
mô-đun, ví dụ: nếu cả src/main/res/
và src/main/res2/
đều chứa các tài nguyên giống nhau.
Khắc phục sự cố liên quan đến việc rút gọn tài nguyên
Khi bạn rút gọn các tài nguyên, cửa sổ Build (Tạo) sẽ trình bày bản tóm tắt về các tài nguyên đã bị xoá khỏi ứng dụng. (Nhấp vào Toggle view (Chuyển đổi chế độ xem) ở phía bên trái của cửa sổ để hiển thị văn bản đầu ra chi tiết từ Gradle.) Ví dụ:
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle cũng tạo một tệp chẩn đoán có tên resources.txt
trong <module-name>/build/outputs/mapping/release/
(chung thư mục với các tệp đầu ra của ProGuard). Tệp này bao gồm chi tiết như tài nguyên nào tham chiếu các tài nguyên khác và tài nguyên nào được sử dụng hoặc bị xoá.
Ví dụ: để tìm hiểu lý do @drawable/ic_plus_anim_016
vẫn còn trong ứng dụng, hãy mở tệp resources.txt
và tìm tên tệp đó. Bạn có thể thấy rằng tệp này được tham chiếu từ một tài nguyên khác:
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
Bây giờ, bạn cần biết lý do có thể tiếp cận được @drawable/add_schedule_fab_icon_anim
; và nếu tìm kiếm ở phía trên, bạn sẽ thấy tài nguyên đó được liệt kê trong tiêu đề Tài nguyên có thể tiếp cận ở mức cao nhất (root) là: trong resources.txt
.
Điều này có nghĩa là có một tham chiếu mã đến add_schedule_fab_icon_anim
, tức là mã nhận dạng R.drawable
của mã này được tìm thấy trong mã có thể tiếp cận.
Trừ phi bạn đang sử dụng tuỳ chọn kiểm tra nghiêm ngặt, các mã nhận dạng tài nguyên sẽ được đánh dấu là có thể tiếp cận được nếu chứa các hằng số chuỗi có thể dùng để tạo tên tài nguyên cho các tài nguyên được tải động. Trong trường hợp đó, nếu tìm kiếm kết quả bản dựng cho tên tài nguyên, bạn có thể thấy thông báo như sau:
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.
Nếu bạn thấy một trong những chuỗi này và chắc chắn rằng chuỗi đó không được dùng để tải động tài nguyên đã cho, hãy sử dụng thuộc tính tools:discard
trong tệp giữ lại để thông báo cho hệ thống xây dựng xoá tài nguyên đó.