Bảng Điều Khiển Ôn Tập Android

Kotlin • MVVM • Flow • REST API • Compose • Testing

Về Lộ trình kiến thức
P0 - Bắt buộc vững

Git / Debugging

Công việc hằng ngày: Git, PR, resolve conflict, đọc Logcat, build variants.

1Luồng làm việc Git: làm trên bản nháp riêng, không đụng bản chính

Hãy hình dung nhánh chính (main) là bản đang chạy thật, mọi người đều dựa vào nó — nếu bạn sửa thẳng lên đó mà code còn dang dở hoặc có bug, cả team dính theo ngay lập tức. Vì vậy, mỗi khi làm một việc mới (vd thêm màn hình ProductList), bạn tạo một NHÁNH RIÊNG — một bản nháp của bạn, tha hồ sửa, commit, thử sai mà không ảnh hưởng tới bản chính.

Mỗi commit nên nhỏ và có message rõ nghĩa — giống việc ghi chú lại "đã làm gì" ở từng bước, để sau này người khác (hoặc chính bạn vài tuần sau) đọc lại biết ngay bước nào làm gì, và nếu cần revert thì chỉ lùi đúng một bước thay vì gỡ cả một khối lớn không rõ ràng. Xong việc, bạn mở Pull Request (PR) — một lời đề nghị chính thức "tôi muốn đưa nhánh này vào bản chính" — để đồng đội review trước khi merge, không tự ý gộp vào khi chưa ai xem qua.

Các lệnh thường dùng khi làm một tính năng mới

git checkout -b feature/product-list   # tạo nhánh nháp riêng cho tính năng ProductList
git add . && git commit -m "add product list screen"
git push -u origin feature/product-list

# đồng bộ với nhánh chính trước khi mở PR, tránh review xong mới phát hiện đã lệch quá xa
git fetch origin
git rebase origin/main                 # hoặc git merge origin/main

2Resolve conflict: khi hai người cùng sửa một chỗ

Conflict giống tình huống hai người cùng sửa một đoạn văn bản dùng chung, cùng lúc, ở đúng một chỗ — hệ thống không tự biết ai đúng ai sai, nên nó dừng lại và bắt bạn tự quyết định. Git đánh dấu rõ vùng xung đột bằng <<<<<<<, =======, >>>>>>> để bạn thấy chính xác đâu là bản của bạn, đâu là bản của người kia.

Việc cần làm là đọc kỹ CẢ HAI phía để hiểu mỗi bên đang cố làm gì — có khi câu trả lời đúng là giữ CẢ HAI (mỗi bên sửa một ý khác nhau trong cùng một hàm), không phải luôn luôn chỉ chọn một bên. Xoá hết dấu marker, ráp lại đúng ý, rồi chạy thử lại trước khi commit tiếp — đừng coi conflict đã xong chỉ vì không còn dấu <<<<<<< nữa.

Lưu ý

Đừng bấm bừa 'giữ bên mình' (ours) hay 'giữ bên họ' (theirs) chỉ để cho xong — cách này rất dễ âm thầm xoá mất một đoạn code của đồng đội mà không ai biết, cho tới khi bug xuất hiện ở production. Luôn đọc hiểu ngữ cảnh trước khi quyết định.

3Pull request và code review: một cặp mắt khác soi trước khi vào bản chính

Một PR tốt giống một bài nộp gọn gàng, dễ chấm: nhỏ, chỉ làm ĐÚNG MỘT việc (đừng nhét luôn 3 tính năng không liên quan vào một PR), có mô tả rõ đã đổi gì và test bằng cách nào, kèm test tự động nếu có thể — người review không phải tự đoán ý định của bạn.

  • Khi review, kiểm tra: đúng yêu cầu đề ra chưa, có tuân theo kiến trúc đang dùng không (vd đúng luồng MVVM: state đi xuống, event đi lên như đã học), xử lý lifecycle và lỗi có ổn không, có lỗ hổng bảo mật rõ ràng nào không (vd log token nhạy cảm), code có dễ đọc, và có test đi kèm không.
  • Trao đổi trong review nên lịch sự và tập trung vào CODE, không phải vào người viết — một câu hỏi "chỗ này mình chưa hiểu vì sao làm vậy?" luôn tốt hơn phán xét thẳng.

4Gradle, build variant và đóng gói: hai phiên bản của cùng một app

Cùng một codebase nhưng bạn cần hai "phiên bản" khác nhau tuỳ mục đích: debug là bản dùng khi tự phát triển — chạy nhanh, giữ nguyên log để dễ soi lỗi; release là bản đóng gói để đưa cho người dùng thật — đã được tối ưu và ký tên chính thức, không lộ log nội bộ.

  • versionCode: một số nguyên chỉ tăng dần, dùng để CHÍNH Google Play nhận biết đâu là bản mới hơn — người dùng không nhìn thấy số này.
  • versionName: chuỗi hiển thị cho người dùng thấy (vd "1.2.0") — không bắt buộc phải tăng đều, chỉ cần dễ hiểu với người dùng.
  • R8/ProGuard: ở bản release, công cụ này tự động rút gọn code không dùng tới (minify) và đổi tên các class/hàm thành những cái tên vô nghĩa (obfuscate) — vừa giảm dung lượng app, vừa khiến ai đó cố dịch ngược app khó đọc hiểu hơn.
  • APK là gói cài đặt trực tiếp lên máy; AAB (Android App Bundle) là định dạng bạn nộp lên Play Store — Google giữ nó lại và tự đóng gói ra đúng bản APK tối ưu riêng cho từng loại máy, thay vì bắt mọi máy tải cùng một gói to chứa đủ thứ không cần.

5Debug: đọc dấu chân trong stacktrace, đặt trạm dừng để soi từng bước

Khi app crash, ví dụ vừa bấm vào một sản phẩm ở ProductList thì văng ra ngay, Logcat sẽ in ra một stacktrace — hãy coi nó như DẤU CHÂN để lại đúng đường đi của lỗi. Đọc từ TRÊN XUỐNG: dòng đầu tiên (loại Exception, vd NullPointerException) cho biết chuyện gì đã xảy ra; các dòng 'at ...' phía dưới cho biết lỗi đã đi qua những đâu — bạn cần tìm dòng ĐẦU TIÊN thuộc code CỦA MÌNH (không phải code của thư viện Android/Kotlin), vì đó thường mới là nơi thật sự cần sửa.

Nếu chỉ đọc stacktrace vẫn chưa rõ vì sao, đặt breakpoint trong Android Studio ngay tại dòng nghi ngờ — coi nó như đặt một TRẠM DỪNG dọc đường đi của code. Chạy tới đó, chương trình tự dừng lại, bạn xem được giá trị THẬT của từng biến ngay lúc đó, và có thể step qua từng dòng tiếp theo để xem chính xác chỗ nào bắt đầu sai — thay vì đoán mò bằng cách đọc code suông.

Mẹo

Lọc Logcat theo đúng tag/level và đúng process của app để không bị ngập trong hàng nghìn dòng log của hệ thống và app khác. Chủ động thêm log có ý nghĩa ở các nhánh xử lý quan trọng (vd log rõ đang ở nhánh Success hay Error) — lúc cần debug, log tốt đỡ mất công đặt lại breakpoint từ đầu.

Checklist

Tick những gì bạn đã nắm chắc

0/6

Lỗi thường gặp

  • Commit lớn, message không rõ, khó review và revert.
  • Force push đè lên nhánh chung.
  • Không biết `versionCode` (số tăng dần cho store) khác `versionName` (hiển thị cho user).

Câu trả lời mẫu

Em làm việc theo nhánh feature, commit nhỏ và rõ, mở PR để teammate review. Khi conflict em đọc kỹ cả hai phía trước khi merge. Debug crash em đọc stacktrace trong Logcat, đặt breakpoint và kiểm tra lại theo state.