Phát triển lặp lại nhanh chóng cho Android
Trang này mô tả cách bazel mobile-install giúp quá trình phát triển lặp lại cho Android nhanh hơn nhiều. Trang này mô tả những lợi ích của phương pháp này so với những nhược điểm của các bước xây dựng và cài đặt riêng biệt.
Tóm tắt
Để cài đặt các thay đổi nhỏ cho ứng dụng Android một cách nhanh chóng, hãy làm như sau:
- Tìm quy tắc
android_binarycủa ứng dụng mà bạn muốn cài đặt. - Kết nối thiết bị của bạn với
adb. - Chạy
bazel mobile-install :your_target. Quá trình khởi động ứng dụng sẽ chậm hơn một chút so với bình thường. - Chỉnh sửa mã hoặc tài nguyên Android.
- Chạy
bazel mobile-install :your_target. - Tận hưởng quá trình cài đặt gia tăng nhanh chóng và tối thiểu!
Một số tuỳ chọn dòng lệnh cho Bazel có thể hữu ích:
--adbcho Bazel biết tệp nhị phân adb nào cần sử dụng--adb_argcó thể dùng để thêm các đối số bổ sung vào dòng lệnh củaadb. Một ứng dụng hữu ích của việc này là chọn thiết bị mà bạn muốn cài đặt nếu bạn có nhiều thiết bị kết nối với máy trạm:bazel mobile-install :your_target -- --adb_arg=-s --adb_arg=<SERIAL>
Khi bạn không chắc chắn, hãy xem ví dụ, liên hệ với chúng tôi trên Nhóm Google, hoặc báo cáo vấn đề trên GitHub
Giới thiệu
Một trong những thuộc tính quan trọng nhất của chuỗi công cụ dành cho nhà phát triển là tốc độ: có sự khác biệt rất lớn giữa việc thay đổi mã và xem mã chạy trong vòng một giây và phải đợi vài phút, đôi khi vài giờ, trước khi bạn nhận được ý kiến phản hồi về việc các thay đổi của bạn có thực hiện những gì bạn mong đợi hay không.
Rất tiếc, chuỗi công cụ Android truyền thống để tạo tệp .apk đòi hỏi nhiều bước tuần tự, nguyên khối và tất cả các bước này phải được thực hiện để tạo ứng dụng Android. Tại Google, việc phải đợi 5 phút để tạo một thay đổi một dòng không phải là điều hiếm gặp đối với các dự án lớn hơn như Google Maps.
bazel mobile-install giúp quá trình phát triển lặp lại cho Android nhanh hơn nhiều bằng cách kết hợp việc cắt tỉa thay đổi, phân chia công việc và thao tác thông minh với các thành phần bên trong của Android, tất cả đều không thay đổi bất kỳ mã nào của ứng dụng.
Các vấn đề với quá trình cài đặt ứng dụng truyền thống
Việc tạo ứng dụng Android có một số vấn đề, bao gồm:
Tạo tệp dex. Theo mặc định, công cụ Dexer (trước đây là
dx, hiện làd8hoặcr8) được gọi chính xác một lần trong bản dựng và không biết cách sử dụng lại công việc từ các bản dựng trước: công cụ này sẽ tạo tệp dex cho mọi phương thức, mặc dù chỉ có một phương thức được thay đổi.Tải dữ liệu lên thiết bị. adb không sử dụng toàn bộ băng thông của kết nối USB 2.0 và các ứng dụng lớn hơn có thể mất nhiều thời gian để tải lên. Toàn bộ ứng dụng được tải lên, ngay cả khi chỉ có các phần nhỏ thay đổi, chẳng hạn như một tài nguyên hoặc một phương thức, vì vậy, đây có thể là một nút thắt lớn.
Biên dịch sang mã gốc. Android L đã giới thiệu ART, một thời gian chạy Android mới, biên dịch các ứng dụng trước thời gian thay vì biên dịch chúng ngay trong thời gian như Dalvik. Điều này giúp các ứng dụng nhanh hơn nhiều với chi phí là thời gian cài đặt lâu hơn. Đây là một sự đánh đổi tốt cho người dùng vì họ thường cài đặt ứng dụng một lần và sử dụng nhiều lần, nhưng dẫn đến quá trình phát triển chậm hơn khi một ứng dụng được cài đặt nhiều lần và mỗi phiên bản chạy nhiều nhất là một vài lần.
Phương pháp của bazel mobile-install
bazel mobile-install thực hiện các cải tiến sau:
Phân chia việc khử đường và tạo tệp dex. Sau khi tạo mã Java của ứng dụng, Bazel sẽ phân chia các tệp lớp thành các phần có kích thước gần bằng nhau và gọi
d8riêng trên các tệp đó.d8không được gọi trên các phân đoạn không thay đổi kể từ bản dựng cuối cùng. Sau đó, các phân đoạn này được biên dịch thành các APK phân đoạn riêng biệt.Truyền tệp gia tăng. Tài nguyên Android, tệp .dex và thư viện gốc bị xoá khỏi tệp .apk chính và được lưu trữ trong một thư mục mobile-install riêng biệt. Điều này giúp bạn có thể cập nhật mã và tài nguyên Android một cách độc lập mà không cần cài đặt lại toàn bộ ứng dụng. Do đó, việc truyền tệp mất ít thời gian hơn và chỉ các tệp .dex đã thay đổi mới được biên dịch lại trên thiết bị.
Cài đặt phân đoạn. Mobile-install sử dụng công cụ
apkdeployercủa Android Studio để kết hợp các APK phân đoạn trên thiết bị được kết nối và mang lại trải nghiệm gắn kết.
Tạo tệp dex phân đoạn
Việc tạo tệp dex phân đoạn khá đơn giản: sau khi tạo các tệp .jar, một
công cụ
sẽ phân chia các tệp đó thành các tệp .jar riêng biệt có kích thước gần bằng nhau, sau đó gọi
d8 trên những tệp đã thay đổi kể từ bản dựng trước. Logic xác định phân đoạn nào cần tạo tệp dex không dành riêng cho Android: logic này chỉ sử dụng thuật toán cắt tỉa thay đổi chung của Bazel.
Phiên bản đầu tiên của thuật toán phân đoạn chỉ sắp xếp các tệp .class theo bảng chữ cái, sau đó cắt danh sách thành các phần có kích thước bằng nhau, nhưng điều này không tối ưu: nếu một lớp được thêm hoặc xoá (ngay cả lớp lồng nhau hoặc lớp ẩn danh), thì tất cả các lớp theo bảng chữ cái sau đó sẽ bị dịch chuyển đi một, dẫn đến việc tạo tệp dex cho các phân đoạn đó một lần nữa. Do đó, chúng tôi quyết định phân chia các gói Java thay vì các lớp riêng lẻ. Tất nhiên, điều này vẫn dẫn đến việc tạo tệp dex cho nhiều phân đoạn nếu một gói mới được thêm hoặc xoá, nhưng điều đó ít xảy ra hơn nhiều so với việc thêm hoặc xoá một lớp.
Số lượng phân đoạn được kiểm soát bằng cấu hình dòng lệnh, sử dụng cờ --define=num_dex_shards=N. Trong một thế giới lý tưởng, Bazel sẽ tự động xác định số lượng phân đoạn tốt nhất, nhưng Bazel hiện phải biết tập hợp các hành động (ví dụ: các lệnh sẽ được thực thi trong quá trình tạo) trước khi thực thi bất kỳ hành động nào trong số đó, vì vậy, Bazel không thể xác định số lượng phân đoạn tối ưu vì không biết cuối cùng sẽ có bao nhiêu lớp Java trong ứng dụng. Nói chung, càng nhiều phân đoạn thì quá trình tạo và cài đặt sẽ càng nhanh, nhưng quá trình khởi động ứng dụng sẽ càng chậm, vì trình liên kết động phải thực hiện nhiều công việc hơn. Điểm tối ưu thường nằm trong khoảng từ 10 đến 50 phân đoạn.
Triển khai gia tăng
Việc truyền và cài đặt phân đoạn APK gia tăng hiện được xử lý bằng tiện ích
apkdeployer được mô tả trong "Phương pháp cài đặt trên thiết bị di động".
Trong khi các phiên bản (gốc) trước đó của tính năng cài đặt trên thiết bị di động yêu cầu theo dõi thủ công các lượt cài đặt lần đầu và chọn áp dụng cờ --incremental
cho các lượt cài đặt tiếp theo, thì phiên bản gần đây nhất trong rules_android
đã được đơn giản hoá rất nhiều. Bạn có thể sử dụng cùng một lệnh gọi cài đặt trên thiết bị di động bất kể số lần ứng dụng đã được cài đặt hoặc cài đặt lại.
Ở cấp độ cao, công cụ apkdeployer là một trình bao bọc xung quanh nhiều lệnh con adb. Bạn có thể tìm thấy logic điểm truy cập chính trong
com.android.tools.deployer.Deployer
lớp, với các lớp tiện ích khác được đặt cùng vị trí trong cùng một gói.
Lớp Deployer tiếp nhận, trong số những thứ khác, danh sách đường dẫn để phân tách
APK và protobuf có thông tin về quá trình cài đặt, đồng thời tận dụng
các tính năng triển khai cho gói ứng dụng Android
để tạo phiên cài đặt và triển khai gia tăng các phần phân tách ứng dụng.
Hãy xem các lớp ApkPreInstaller
và ApkInstaller
để biết thông tin chi tiết về cách triển khai.
Kết quả
Hiệu suất
Nhìn chung, bazel mobile-install giúp tăng tốc độ tạo và cài đặt các ứng dụng lớn từ 4 đến 10 lần sau một thay đổi nhỏ.
Các số sau đây được tính cho một số sản phẩm của Google:
Tất nhiên, điều này phụ thuộc vào bản chất của thay đổi: việc biên dịch lại sau khi thay đổi thư viện cơ sở sẽ mất nhiều thời gian hơn.
Các điểm hạn chế
Các mẹo mà ứng dụng trình giữ chỗ áp dụng không hoạt động trong mọi trường hợp. Các trường hợp sau đây nêu bật những trường hợp mà ứng dụng không hoạt động như mong đợi:
Tính năng cài đặt trên thiết bị di động chỉ được hỗ trợ thông qua các quy tắc Starlark của
rules_android. Hãy xem "lịch sử tóm tắt về tính năng cài đặt trên thiết bị di động" để biết thêm chi tiết.Chỉ các thiết bị chạy ART mới được hỗ trợ. Tính năng cài đặt trên thiết bị di động sử dụng các tính năng API và thời gian chạy chỉ có trên các thiết bị chạy ART, không phải Dalvik. Mọi thời gian chạy Android mới hơn Android L (API 21 trở lên) đều phải tương thích.
Bản thân Bazel phải được chạy bằng thời gian chạy Java và phiên bản ngôn ngữ của công cụ là 17 trở lên.
Các phiên bản Bazel trước 8.4.0 phải chỉ định một số cờ bổ sung cho tính năng cài đặt trên thiết bị di động. Hãy xem hướng dẫn về Bazel Android. Các cờ này cho Bazel biết khía cạnh cài đặt trên thiết bị di động của Starlark ở đâu và những quy tắc nào được hỗ trợ.
Lịch sử tóm tắt về tính năng cài đặt trên thiết bị di động
Các phiên bản Bazel trước đó theo mặc định bao gồm các quy tắc tạo và kiểm thử tích hợp cho các ngôn ngữ và hệ sinh thái phổ biến như C++, Java và Android. Do đó, các quy tắc này được gọi là quy tắc gốc. Bazel 8 (phát hành vào năm 2024) đã ngừng hỗ trợ các quy tắc này vì nhiều quy tắc trong số đó đã được di chuyển sang ngôn ngữ Starlark. Hãy xem "bài đăng trên blog về Bazel 8.0 LTS" để biết thêm chi tiết.
Các quy tắc Android gốc cũ cũng hỗ trợ phiên bản gốc cũ của chức năng cài đặt trên thiết bị di động. Chức năng này hiện được gọi là "cài đặt trên thiết bị di động phiên bản 1" hoặc "cài đặt trên thiết bị di động gốc". Chức năng này đã bị xoá trong Bazel 8, cùng với các quy tắc Android tích hợp.
Hiện tại, tất cả chức năng cài đặt trên thiết bị di động, cũng như tất cả các quy tắc tạo và kiểm thử Android, đều được triển khai trong Starlark và nằm trong kho lưu trữ GitHub rules_android. Phiên bản mới nhất được gọi là "cài đặt trên thiết bị di động phiên bản 3" hoặc "MIv3".
Lưu ý về tên: Có một "cài đặt trên thiết bị di động v2" chỉ có nội bộ tại Google vào một thời điểm, nhưng phiên bản này chưa bao giờ được xuất bản bên ngoài và chỉ có phiên bản 3 tiếp tục được sử dụng cho cả việc triển khai các quy tắc_android nội bộ của Google và OSS.