Những kinh nghiệm với lập trình Android - Phần I
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.
Mình thực sự chưa hiểu rõ về navigates và utils trong phần cấu mục cho code Android. Bạn có thể giải thích rõ hơn được không? Cụ thể là các class trong đó để làm gì? Nếu ví dụ cụ thể thì quá tốt.
Mình cũng đã không ít lần thắc mắc về cấu trúc thư mục trong Android sao cho phù hợp với MVC. Cũng có người bạn trên facebook chia sẽ cho mình 1 cấu trúc thư mục. Mình sẽ dán nó ở đây để các bạn cùng tham khảo.
Hi GDG
Mình có góp ý phần Log thay vì đặt biến như vậy bạn có thể dùng proguard để unuse hết các method use Log object trước khi submit app.
Mở file proguard-rules.pro và thêm vào :
Log
Sau đó save lại và nhớ cấu hình run proguard khi build app ở Build Variant release nhé.
Link hướng dẫn tại đây : http://stackoverflow.com/questions/13218772/removing-log-call-using-proguard
Và cho mình hỏi là mất storgekey và keyPassword như thế nào ? 2 key này mình nhớ đâu có chỉnh sửa đc, ví dụ có người biết 2 key này thì tác hại như thế nào bạn ?
Òa cách này của bạn hay quá. Nó giải quyết được luôn vấn đề phát sinh từ phương pháp của mình.
Còn cái key thì là mấy bác bên Google bảo thế mình cũng chẳng biết.
Util là class chứa các phương thức dùng chung. Ví dụ như hàm để cắt chuỗi hay đơn cử nhất là TextUtils trong Android.
Navigate là phương thức xử lí việc điều hướng ví dụ như update screen name hay các tác vụ liên quan.
Hay nhá bạn. Mình cảm ơn
Em chưa bao giờ dùng Log, em toàn dùng Toast để debug thôi
Toast là những cái show ra với người dùng. Những không tin như id, facebook id hay kiểu kiểu thế chẳng lẽ cũng show ra cho họ biết sao?
Chắc là bạn ấy viết Toast để test xong rồi xoá
Thực ra là toast hiện lên rồi biến mất, thời gian khá nhanh lại không copy được vào máy tính hoặc tính lưu triwx không cao.
Anh cố gắng viết thêm nhiều bài thế này nữa. Rất hữu ích
Đợt này anh bận dự án quá vẫn chưa viết được thêm. Hic hic.
Em dùng xong xóa, hoặc thay nội dung Toast sau khi đã test thành một nội dung nào đó dành cho user
Khi cần liệt ra nhiều giá trị thì toast không ổn một tí nào
Một câu trả lời trên Stackoverflow khá hay
https://davidng94.files.wordpress.com/2016/01/2016-01-28_00-55-13.jpg?w=640
Tại sao trong cấu trúc thư mục cho code Android lại không có thư mục controllers vậy GDGHN_AndroidTeam?
Mình chưa hiểu chỗ thư mục example lắm, tại sao tên project lại đặt ngang hàng với những thư mực khác vậy.
Không biết mọi người thấy thế nào chứ mình phản đối cách dựng skeleton tùy ý. Ngồi debug mấy dự án này siêu khoai vì logic nhảy lung tung, viết function cũng ngẫu nhiên, thích là đặt chẳng qui chuẩn gì cả.
Nên dùng các tool làm scaff folding, vừa tiện, vừa gõ command tạo skeleton nhanh.
Vậy bạn có thể cho biết 1 vàu cái tool được không?
bài viết rất bổ ích, có 1 chức năng mà trước giờ em hok tài nào hiểu nổi là debug bằng breakpoint trong android studio,dubug breakpoint giống như là mình chỉ chạy 1 đoạn nhỏ code trong android nhưng nó hoạt động rất lạ và khó nắm bắt. Trước giờ toàn debug bằng log.java, logcat là chính
Với Web thì mình hay dùng Yoman.
Còn với Android thì mình hay dùng Androton, https://www.indiegogo.com/projects/androton-open-source#/
Mình thấy cái skeleton của @nhatchimai111 dễ hiểu hơn nhiều (khá giống với androton).
Hoặc tổ chức kiểu này mình cũng thấy rất thích, đơn giản, dễ hiểu và dễ flow luồng
GitHub
nickbutcher/plaid
An Android app which provides design news & inspiration as well as being an example of implementing material design. - nickbutcher/plaid
Cái này cũng khá hay.
GitHub
groupsky/generator-android
Yeoman based android scaffolding. Contribute to groupsky/generator-android development by creating an account on GitHub.
Các anh/bạn cho mình hỏi có cách nào để cấu trúc thư mực được cái đống layout xml ko
Mình đang dùng cách đặt tiền tố ban đầu theo từng nhóm