Tóm tắt
[Có một vài topic như thế này][1] khiến mình rất bối rối không biết phải trả lời như thế nào cho hợp lí. Vậy nên lập thêm một topic mới chia sẻ kinh nghiệm chung nhất của mình về lập trình Android. Đây là những kinh nghiệm khi mình thực hiện maintain lại một dự án trong hai năm và làm một vài dự án nhỏ nữa nên không chắc là những kinh nghiệm tốt nhất. Tuy nhiên vẫn hi vọng chúng có ích
[1]: Cần tài liệu phần giao diện Android
Cấu trúc thư mục cho code Android
Mục này mình có tham khảo ở nhiều nguồn để ghép vào phần dự án mình đang làm. Theo mình thấy thì dự án chia cây thư mục như sau sẽ rõ ràng hơn các cách chia khác.
Android_structure
├─ gdg.lbs
│ ├─ activities
│ ├─ adapters
│ ├─ fragments
│ ├─ example
│ ├─ interfaces
│ ├─ models
│ ├─ navigates
│ ├─ networks
│ ├─ notifications
│ ├─ utils
│ └─ views
Trong đó mỗi một thành phần sẽ có một ý nghĩa riêng như sau:
gdg: Tên công ty (đồng thời nằm trong root package name)
lbs: Viết tắt của Lương Sơn Bạc là tên của team
activities: Các activity sẽ được đưa vào đây.
adapters: Dành cho các custom adapter.
fragments: Toàn bộ các fragment
example: Tên của project. Trong này sẽ chứa tất cả những gì liên quan tới project bao gồm file Config.java, Application.java…
interfaces: Khai báo các interface được dùng trong dự án
models: Làm việc với preference, làm việc với SQLlite
navigates: Các phương thức điều khiển vào ra của fragment sẽ được đưa vào đây.
networks: Picaso. Volley, OKHttp sẽ được đưa vào đây.
notifications: Tất cả mọi hoạt động liên quan đến notification, GCM.
utils: Các lớp hỗ trợ trọng quá trình sử dụng như StorageUtil.java, ImageUtil.java…
views: Khai báo các custom view
Ngoài những thư mục (package) kể trên thì mình còn sử dụng thêm một vài package nữa tuy nhiên không phổ biến lắm nên mình không có liệt kê tại đây.
Sử dụng DebugLog.java thay vì Log.java
Thông thường khi muốn viêt lại log để hỗ trợ việc debug android được tốt hơn, các bạn sẽ sử dụng lớp được cũng cấp sẵn là Log.i(String, String);
. Tuy nhiên vấn đề bạn đang gặp phải là những đoạn log này chỉ hữu ích với việc debug mà thôi. Khi sản phẩm được tung ra thị trường thì những đoạn log này vô tình lại đang làm hại chính các bạn. Vậy trong trường hợp này ta phải làm sao? Chẳng lẽ lại tìm từng chỗ viết log rồi xóa tay trước khi build?
Một gợi ý nhỏ đó là chúng ta sẽ sử dụng một biến static có tên là IS_DEBUG
như sau:
if (Config.IS_DEBUG) {
Log.i(String, String);
}
Cũng khá ổn rồi nhưng mà bây giờ mỗi lần sử dụng chẳng lẽ lại viết đi viết lại mất công quá. Chưa kể là thành viên mới vào team có khi còn quên việc phải sử dụng code như vậy nữa. Vậy nên chăng ta nên sử dụng một lớp là DebugLog.java
như sau:
public class DebugLog {
public static void i(String tag, String msg) {
if (Config.IS_DEBUG) {
Log.i(tag, msg);
}
}
}
Tốt rồi, code đã trở nên sáng sủa hơn nhiều.Thế nhưng có một vấn đề nhỏ với DebugLog.
DebugLog.i(TAG, "String: " + numberOfString);
Đoạn code trên tưởng chừng như vô hai nhưng lại khiến cho ta tốn thêm 4 bước thuật toán cộng chuỗi trong khi chuỗi mới chẳng được sử dụng nếu cờ IS_DEBUG
được đặt bằng false
. Vậy cách giải quyết ở đây là gì nhỉ?
Chẳng có cách nào để khắc phục việc này đâu. Hãy coi đây là một cái giá phải trả cho việc quản lí dễ dàng hơn.
Lưu mật khẩu signing key vào file gradle.properties
Nếu có bạn nào tìm hiểu sâu đến grade thì đều biết đây là một nền tảng hỗ trợ việc build tự động theo kịch bản. Thông thường khi release, bạn sẽ tạo ra một kịch bản build như sau:
signingConfigs {
release {
storeFile file("release.keystore")
storePassword "storepassword"
keyAlias "myproject"
keyPassword "keypassword"
}
}
Sau đó bạn đẩy file này lên version control như GIT hoặc SVN. Tình cờ thế nào ai đó có quyền truy cập vào version control của bạn. Và bạn mất đi signing key, một trong những chìa khóa cốt lõi cho file apk của bạn trên GooglePlay.
Một giải pháp cho vấn đề này là chúng ta sẽ sử dụng file gradle.properties
như sau:
KEYSTORE_PASSWORD=storepassword
KEY_PASSWORD=keypassword
Và thay vì viết một kịch bản như trên, bạn có cách viết lại khác hơn nhiều:
signingConfigs {
release {
try {
storeFile file("release.keystore")
storePassword KEYSTORE_PASSWORD
keyAlias "myproject"
keyPassword KEY_PASSWORD
}
catch (ex) {
throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
}
}
}
Lúc này, chúng ta chỉ cần pull kịch bản lên version control và giữ lại password cho riêng mình.