12/08/2018, 13:29

[Smaller APK part 3]Removing unused resources

Trong phần tiếp theo của loạt bài tối ưu kích thước file apk, tôi trình bày về các phương pháp để loại bỏ các tài nguyên không dùng đến trong ứng dụng. Tài nguyên (Resources) ở đây gồm nhiều loại: ảnh chuỗi (string), layout file, dimension... Có 2 cách để loại bỏ tài nguyên không dùng đến ...

Trong phần tiếp theo của loạt bài tối ưu kích thước file apk, tôi trình bày về các phương pháp để loại bỏ các tài nguyên không dùng đến trong ứng dụng.

Tài nguyên (Resources) ở đây gồm nhiều loại:

  • ảnh
  • chuỗi (string), layout file, dimension...

Có 2 cách để loại bỏ tài nguyên không dùng đến trong ứng dụng (đây là những resource không dùng đến nhưng có phụ thuộc vào thành phần khác mà không loại bỏ được bằng tay). Cách 1: sử dụng cờ minify/shinking tương tự như ở part2

android {
    ...
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

Tương tự với loại bỏ mã code, loại bỏ resource cũng xảy ra một vấn đề là loại bỏ nhầm tài nguyên được sử dụng. Để tránh tình trạng này bạn có thể dùng keep để tạo ngoại lệ cho các tài nguyên không muốn tự động shrink

Trong file res/raw/keep.xml

<?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*"
/>

hoặc sử dụng discard, ở cùng file keep.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="safe"
    tools:discard="@layout/unused2"
/>

Bạn có thể đọc thêm về debugging shrink bằng log file và chuyển chế độ safe và strict ở trang sau

https://tools.android.com/tech-docs/new-build-system/resource-shrinking

Tất nhiên tốt nhất bạn nên kiểm soát thật tốt tài nguyên và loại bỏ bằng tay các tài nguyên mà ban chắc chắn không sử dụng đến thay vì sử dụng tools tự động.

Loại bỏ những config dư thừa với ResConfigs

Có rất nhiều thư viện hỗ trợ multi language. Support Library và Google Play Services là một ví dụ. Nếu bạn không có nhu cầu sử dụng multi language, bạn có thể loại bỏ nó bằng cách sau:

android {
    defaultConfig {
        ...
        resConfigs "en", "fr"
    }
}

Sparse configurations in resources.arsc

Vấn đề mà tôi đề cập đến ở phần này sẽ dành cho những ứng dụng có dung lượng lớn với hàng trăm hay hàng nghìn chuỗi, styles... ở trong file resources.arsc

Nếu bạn nhận thấy tập tin này chiếm một số lượng lớn bất thường trong APK file, điều này có thể chỉ báo rằng bạn có quá nhiều cấu hình dạng spare (tạm dịch là rải rác). Xem ví dụ sau để hiểu rõ hơn:

Nếu bạn khai báo 5 chuỗi trong file strings, các string sẽ được cấp phát như thế này

String pool: "My App", "Hello", "Exit", "Settings", "Feature"
                  Default config:
string/myapp      0x00000001
string/hello      0x00000002
string/exit       0x00000003
string/settings   0x00000004
string/feature    0x00000005

Bây giờ bạn muốn override 1 strings cho v21 chẳng hạn, lúc đó, bạn khai báo thêm một strings.xml trong v21. Lúc đó, bạn nghĩ đơn giản mình vừa khai báo thêm một xâu nữa thôi, nhưng sự thật thì các đối tượng được cấp phát như thế này:

String pool: "My App", "Hello", "Exit", "Settings", "Feature", "New feature"
                  Default config:         -v21 config:
string/myapp      0x00000001              NO_ENTRY
string/hello      0x00000002              NO_ENTRY
string/exit       0x00000003              NO_ENTRY
string/settings   0x00000004              NO_ENTRY
string/feature    0x00000005              0x00000006

                  ==========              ==========
Config size:      20 bytes                20 bytes!

Nhìn xem, ở v21 sinh ra các value null nhưng value này vẫn dành 4 bytes cấp phát. Bạn có thể tưởng tượng ra ảnh hưởng của việc này chưa?

Ví dụ ứng dụng có 50 ngôn ngữ, với khoảng 3500 strings, lúc đó dung tích thêm là:

4 bytes * 3500 null entries * 50 languages = 700 kilobytes

thế là 700 kB có thể được tiết kiệm bởi cách xoá một strings. Với 3 strings thì bạn sẽ tiết kiệm được 2.5M!

Như vậy trong trường hợp ứng dụng có nhiều resource, việc tạo thêm 1 resource bằng cách hợp lý bằng cách xem xét có thật sự cần thiết để tạo folder resource mới hay không.

May mắn là Google có một công cụ có thể giúp bạn tìm ra những tài nguyên dạng sparse, nó gọi là ArscBlamer và có thể tìm thấy ở đây

https://github.com/google/android-arscblamer

$ bazel run //java/com/google/devrel/gmscore/tools/apk/arsc:ArscDumper --apk=/FULL_PATH_TO_APK/bar.apk - keys > output.csv

1-hXU9WJgejvby0CxFDaJj1A.png

More fun and interesting!

Tool này khá thú vị đấy nhỉ, hi vọng bài viết hữu ích cho các bạn. Happy coding!

0