Chào bạn! Bạn đã sẵn sàng "bay cao" trong thế giới phát triển ứng dụng di động chưa? Nếu câu trả lời là CÓ, thì hãy cùng mình khám phá Flutter - một công cụ phát triển ứng dụng cực đỉnh từ Google! Tưởng tượng nhé, bạn chỉ cần viết code MỘT LẦN thôi, là ứng dụng của bạn có thể chạy mượt mà trên cả Android, iOS, web, và thậm chí cả desktop! Nghe có vẻ "ảo diệu" đúng không? Đúng là nó "ảo" thật đấy! Phiên bản mới nhất, Flutter 3, vừa ra mắt vào tháng 5/2022, mang đến vô vàn cải tiến hấp dẫn. Trong bài viết này, mình sẽ hướng dẫn bạn từng bước một, cách biến chiếc máy Artix Linux yêu quý của bạn (dựa trên Arch Linux) thành một môi trường phát triển Flutter chuyên nghiệp, chuẩn không cần chỉnh. Mình đã tự tay cài đặt theo tài liệu chính thức của Flutter, nên bạn cứ yên tâm làm theo nhé! Trước khi chúng ta bắt đầu, hãy cùng điểm qua "đội hình" của chúng ta nhé: Hệ điều hành: Artix Linux (phiên bản đang chạy: 6.0.12-artix1-1) Framework: Flutter 3 (phiên bản ổn định 3.3.10) Ngôn ngữ lập trình: Dart (ngôn ngữ "sinh đôi" với Flutter) Môi trường phát triển tích hợp (IDE): Android Studio (phiên bản 2021.3). À, có một tài liệu cực hay trên Arch Linux Wiki về Android mà bạn có thể tham khảo thêm nữa đấy! Bắt đầu nào! Bạn đã sẵn sàng "nạp năng lượng" cho Artix Linux của mình chưa? Chúng ta sẽ dùng `pacman` - "trình quản lý gói" siêu tốc của Arch/Artix. Nếu bạn quen dùng `sudo`, cứ thoải mái thay thế `doas` bằng `sudo` nhé! Đầu tiên là Dart! Ngôn ngữ này là trái tim của Flutter đó. Để cài đặt, bạn chỉ cần gõ lệnh "thần chú" này vào terminal: ```bash $ doas pacman -Sy dart ``` Sau một hồi tải về và giải nén, Dart SDK sẽ nằm gọn trong `/opt/dart-sdk` của bạn. Chúc mừng, bước đầu đã hoàn thành! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/dart_install_success.png' alt='Màn hình terminal cài đặt Dart thành công'> Tiếp theo, nếu bạn muốn "chọc ghẹo" thiết bị Android của mình, chúng ta cần cài `android-tools`. Gói này chứa `adb` (Android Debug Bridge) - một công cụ siêu hữu ích để giao tiếp với điện thoại Android của bạn. Cứ nghĩ nó như một "cầu nối" giữa máy tính và điện thoại vậy đó! ```bash $ doas pacman -Sy android-tools ``` Đến lượt Flutter "chính chủ" rồi đây! Chúng ta sẽ lấy nó từ AUR (Arch User Repository), kho phần mềm do cộng đồng Arch Linux đóng góp. Yên tâm, nó an toàn và cực kỳ tiện lợi! ```bash $ git clone https://aur.archlinux.org/flutter.git $ cd flutter $ makepkg -sci ``` Khi cài đặt lần đầu, hệ thống có thể hỏi bạn muốn dùng phiên bản Java nào. Nếu không có lý do đặc biệt, cứ chọn mặc định (thường là số 1) rồi nhấn Enter nhé. Đừng lo lắng về mớ thông báo dài dòng, chỉ cần thấy `Proceed with installation? [Y/n] y` thì gõ `y` và Enter thôi! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdk_selection.png' alt='Lựa chọn phiên bản Java trong quá trình cài đặt Flutter'> Sau khi Flutter được cài đặt vào `/opt/flutter`, có một bước quan trọng nhỏ xíu để bạn có thể sử dụng Flutter với tài khoản người dùng thông thường mà không cần `doas` hay `sudo`: ```bash gpasswd -a ${USER} flutterusers ``` Sau đó, để thay đổi có hiệu lực, bạn hãy đăng xuất và đăng nhập lại terminal, hoặc đơn giản hơn là gõ lệnh: ```bash newgrp flutterusers ``` Xong rồi, chúng ta đã cài Flutter. Bây giờ gõ `flutter doctor` để kiểm tra sức khỏe của môi trường phát triển của chúng ta nhé! (Đừng lo nếu có vài dấu `✗` nhé, chúng ta sẽ xử lý chúng sau.) ```bash flutter doctor ``` Khi xong xuôi, gõ `cd ..` để trở về thư mục gốc và chuẩn bị cho bước tiếp theo! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/flutter_install_success.png' alt='Màn hình terminal cài đặt Flutter thành công và nhắc nhở thêm người dùng vào nhóm flutterusers'> Tiếp theo là "ngôi nhà" của chúng ta - Android Studio! Đây là IDE (môi trường phát triển tích hợp) mà chúng ta sẽ dùng để code và xây dựng ứng dụng Flutter. Tương tự như Flutter, chúng ta sẽ cài nó từ AUR: ```bash $ git clone https://aur.archlinux.org/android-studio.git $ cd android-studio $ makepkg -sci ``` Sau khi cài xong, gõ `cd ..` để thoát khỏi thư mục cài đặt nhé. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/android_studio_install_success.png' alt='Màn hình terminal cài đặt Android Studio thành công'> Bạn có thể thắc mắc tại sao chúng ta chưa cài Android SDK đúng không? Đừng lo! Android Studio sẽ tự động tải và cài đặt nó cho chúng ta trong bước thiết lập ban đầu. Thật tiện lợi phải không nào? Nhớ lại bước thêm người dùng vào nhóm `flutterusers` ở trên chứ? Giờ là lúc đảm bảo bạn có quyền truy cập vào thư mục Flutter. Nếu chưa làm, hãy chạy lệnh này nhé: ```bash $ doas usermod -a -G flutterusers <tên-người-dùng-của-bạn> ``` Sau đó, hãy đăng xuất và đăng nhập lại vào hệ thống (hoặc khởi động lại máy) để đảm bảo các thay đổi có hiệu lực hoàn toàn nhé! Giờ thì khởi động Android Studio lên nào! Lần đầu tiên, nó có thể hỏi bạn muốn import cài đặt cũ không. Nếu là cài mới hoàn toàn, bạn cứ chọn "Do not import settings" nhé. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1s9kjk97o7k0bll6d23.png' alt='Màn hình Android Studio hỏi về việc import cài đặt'> Android Studio sẽ dẫn bạn qua một vài bước thiết lập cơ bản. Bạn có thể chọn gửi dữ liệu phân tích hoặc không, tùy ý. Cứ nhấn "Next" vài lần cho đến khi đến màn hình "Verify Settings" nhé. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpe692cnt832epfdz5p4.png' alt='Màn hình chào mừng Android Studio'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsaefd9jxdqo6xkljcxpg.png' alt='Màn hình chọn loại cài đặt Android Studio'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1t6z96sol199476147o.png' alt='Màn hình chọn giao diện người dùng Android Studio'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2b541k68smv1ki5zbpj3.png' alt='Màn hình xác minh cài đặt Android Studio'> Ở màn hình này, bạn sẽ thấy danh sách các thành phần SDK cần tải xuống, bao gồm Android Emulator, Build-Tools, Platform-Tools, và các System Image. Tổng dung lượng có thể lên đến vài GB đó! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdr4gctwu8hwnhw0n0x5r.png' alt='Màn hình thỏa thuận cấp phép Android Studio'> Sau đó, bạn cần "Accept" các thỏa thuận cấp phép và nhấn "Finish" để bắt đầu quá trình tải và cài đặt SDK. Bước này sẽ tốn kha khá thời gian, hãy kiên nhẫn một chút nhé! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy03s18bbaalgjxy7as57.png' alt='Màn hình Android Studio đang tải xuống các thành phần SDK'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4iar90iz6frcsrs7rg6r.png' alt='Màn hình Android Studio đang tải xuống các thành phần SDK'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07blpd5xlodi9zxn55t3.png' alt='Màn hình Android Studio hoàn tất tải xuống các thành phần SDK'> Khi mọi thứ hoàn tất, bạn sẽ thấy màn hình chào mừng của Android Studio. Tuyệt vời! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntdw3g95w76v023i3qxb.png' alt='Màn hình Android Studio sẵn sàng tạo dự án mới'> Giờ là lúc "trang bị" cho Android Studio những "siêu năng lực" để làm việc với Flutter! Hãy chọn mục "Plugins" ở menu bên trái. Tìm kiếm "Flutter" và nhấn "Install". Android Studio sẽ hỏi bạn có muốn cài "Dart" plugin cùng lúc không? Chắc chắn rồi, cứ "Accept" nhé! Sẽ có một cảnh báo nhỏ về plugin bên thứ ba, bạn cứ đọc qua và "Accept" để tiếp tục. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fviorftj0egubhf6ikw59.png' alt='Màn hình cài đặt plugin Flutter trong Android Studio'> Sau khi cài đặt xong, Android Studio sẽ yêu cầu bạn khởi động lại IDE. Cứ làm theo nhé. Khi nó mở lại, bạn sẽ thấy Flutter và Dart đã nằm trong danh sách "Installed" (đã cài đặt) rồi! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasub7yhwqdmsrq6ysd5b.png' alt='Màn hình Android Studio sau khi cài đặt plugin Flutter và Dart'> Mọi thứ đã sẵn sàng để chúng ta tạo dự án Flutter đầu tiên! Trở lại màn hình chính của Android Studio, chọn "New Flutter Project". <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70c81nr1jinogmbjam4i.png' alt='Màn hình tạo dự án Flutter mới trong Android Studio'> Trong cửa sổ tiếp theo, đảm bảo bạn đã chọn "Flutter" ở bên trái. Ở phần "Flutter SDK path", hãy nhập đường dẫn tới Flutter SDK mà chúng ta đã cài đặt: `/opt/flutter/`. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facblhdboo5w0e5kjn6dg.png' alt='Màn hình thiết lập đường dẫn Flutter SDK'> Nhấn "Next", kiểm tra lại các thông tin dự án (tên dự án, tổ chức...) và cuối cùng là "Finish". Chờ một chút, Android Studio sẽ "phù phép" và tạo ra một cấu trúc thư mục hoàn chỉnh cho dự án Flutter của bạn! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvufm344an3rd5wa0mpxs.png' alt='Màn hình cài đặt dự án Flutter'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xf1o11n8jomp56oelu7.png' alt='Cấu trúc thư mục dự án Flutter'> Trông ngon lành cành đào đấy chứ! Nhưng khoan đã, trước khi "nhảy bổ" vào code, chúng ta cần "khám tổng quát" cho môi trường của mình một chút để `flutter doctor` thực sự "khỏe mạnh" đã nhé! Để đảm bảo `flutter doctor` vui vẻ, chúng ta cần cài thêm `Android SDK Command-line tools`. Trong Android Studio, vào "File" > "Settings...". <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbry6meglmp4qic9x4ff6.png' alt='Menu File trong Android Studio'> Tìm "Android SDK" (có thể dùng ô tìm kiếm cho nhanh). Sau đó, chuyển sang tab "SDK Tools" và tích chọn "Android SDK Command-line tools". Nhấn "Apply" và "OK" để cài đặt. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwilrac7elxqm6mf1hu4.png' alt='Cài đặt Android SDK Command-line tools trong Android Studio'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrzsdvh64x9duleisso6.png' alt='Xác nhận thay đổi trong cài đặt Android SDK Tools'> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohv9nurwpg7st5su95p1.png' alt='Trình cài đặt thành phần SDK trong Android Studio'> Vậy là xong `cmdline-tools` rồi! Giờ thì chúng ta có thể yên tâm "ký" vào các giấy phép Android còn thiếu. Mở terminal lên! Đầu tiên, để tránh một lỗi nhỏ khi chạy `flutter doctor` với thư mục `/opt/flutter`, hãy chạy lệnh này nhé: ```bash $ git config --global --add safe.directory /opt/flutter ``` Tiếp theo, chúng ta cần chấp nhận các giấy phép Android. Gõ lệnh này: ```bash $ flutter doctor --android-licenses ``` Nó sẽ hỏi bạn chấp nhận từng giấy phép một. Cứ gõ `y` và Enter cho tất cả các câu hỏi nhé! (Nếu bạn đọc hết từng cái một thì mình cũng "bái phục" luôn đấy!) <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/android_licenses_accept.png' alt='Màn hình terminal chấp nhận các giấy phép Android'> Sau khi chấp nhận hết, bạn sẽ thấy thông báo `All SDK package licenses accepted`. Tuyệt cú mèo! Giờ thì chạy `flutter doctor` một lần nữa, không cần thêm tùy chọn nào cả: ```bash $ flutter doctor ``` Hmmm, có vẻ vẫn còn vài dấu `✗` đúng không? Đừng lo lắng, đây là những thứ tùy chọn cho phát triển web và desktop trên Linux. Chúng ta có thể dễ dàng cài thêm hoặc bỏ qua nếu không cần. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/flutter_doctor_initial_issues.png' alt='Kết quả flutter doctor ban đầu có vài lỗi'> Nếu bạn muốn `flutter doctor` "sạch bóng" mọi dấu `✗` và sẵn sàng cho cả phát triển Linux desktop, hãy cài thêm các gói này nhé: ```bash $ doas pacman -Sy clang cmake ninja base-devel ``` Khi được hỏi chọn gói cho `base-devel`, hãy gõ `23` để chọn `pkgconf` nhé! Sau khi cài đặt xong, nếu bạn không cài Google Chrome nhưng vẫn muốn `flutter doctor` báo `✓` cho mục "Chrome - develop for the web", bạn có thể "đánh lừa" nó một chút bằng cách trỏ `CHROME_EXECUTABLE` đến một trình duyệt khác, ví dụ Chromium: ```bash $ env CHROME_EXECUTABLE=chromium \ flutter doctor ``` Và BÙM! Giờ thì `flutter doctor` của bạn đã "khỏe mạnh" hoàn toàn rồi! Không còn dấu `✗` nào nữa, chỉ toàn `✓` thôi! Chúc mừng bạn! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/flutter_doctor_success.png' alt='Kết quả flutter doctor hoàn hảo không còn lỗi'> Mọi thứ đã sẵn sàng! Quay lại Android Studio và mở file `lib/main.dart`. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pey2zg7u6gocgg2ko3f.png' alt='Cấu trúc dự án Android Studio, tập trung vào main.dart'> Ứng dụng demo này đã được tạo sẵn để chạy ngay. Để khởi động trình giả lập (Emulator), hãy nhấn vào ô hiển thị "<no device selected>" ở thanh công cụ phía trên, rồi chọn "Open Android Emulator". <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylpp4omnuuue4mylx3fz.png' alt='Màn hình chọn thiết bị trong Android Studio'> Chờ một lát để Emulator khởi động. Sau đó, bạn nhấn vào biểu tượng tam giác màu xanh lá cây (nút "Run") ở phía trên thanh công cụ, hoặc vào "Run" > "Run 'main.dart'" (Shift+F10) để khởi chạy ứng dụng demo! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cwhqlsx388r8mzqsdwr.png' alt='Màn hình chạy main.dart trong Android Studio'> Quá trình này có thể tốn một chút thời gian (đặc biệt là lần đầu tiên), vì Gradle cần xây dựng ứng dụng của bạn. Bạn sẽ thấy các thông báo trong cửa sổ Run ở phía dưới. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ha6vaddayh0o1w65hb1.png' alt='Màn hình Android Studio bắt đầu tác vụ Gradle'> Khi hoàn tất, ứng dụng demo Flutter sẽ hiện ra trên Emulator của bạn! Bạn có thể nhấn nút để tăng số đếm đó! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65rpr28ab82gqp9dmwnj.png' alt='Ứng dụng demo Flutter chạy trên Emulator'> Vậy là bạn đã có một môi trường Flutter hoàn chỉnh, sẵn sàng cho mọi dự án lớn nhỏ rồi đó! Và đây là "phép thuật" cuối cùng mình muốn giới thiệu: Hot Reload (Tải lại nhanh)! Flutter cho phép bạn thấy ngay kết quả thay đổi code mà không cần khởi động lại toàn bộ ứng dụng. Thử ngay nhé: Mở `lib/main.dart` và thay đổi dòng 25 từ `- primarySwatch: Colors.blue,` thành `+ primarySwatch: Colors.deepPurple,` rồi lưu lại. Ứng dụng trên Emulator sẽ đổi màu tức thì! Thật tuyệt vời phải không? <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7r2dppgwurfmjswi14c.png' alt='Ứng dụng demo Flutter sau khi Hot Reload với màu sắc thay đổi'> Chúc mừng bạn đã sẵn sàng tạo ra những ứng dụng Flutter 3 đỉnh cao! Hãy bắt đầu hành trình sáng tạo của mình ngay bây giờ nhé! 🚀
Bạn có bao giờ thấy "nhức cái đầu" khi phải làm việc trên nhiều máy tính, nào là Archlinux ở nhà, rồi lại macOS ở công ty, mà cái máy nào cũng phải có "vị" riêng của mình không? Chắc chắn rồi! Các bạn lập trình viên chúng ta ai mà chẳng có một bộ công cụ "ruột" và những cài đặt "độc nhất vô nhị" cho riêng mình. Vấn đề là, mỗi khi đổi máy, hay thay đổi một cái gì đó trên máy này, lại phải "lạch cạch" cài đặt, cấu hình lại trên máy kia. Nghe thôi đã thấy mệt rồi, phải không?<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/multi_os_sync.png' alt='Minh họa đồng bộ hóa đa hệ điều hành'>Trước đây, mình cũng từng thử đủ kiểu, nào là dùng `stow`, nào là viết mấy cái script "thủ công" bằng Bash. Nhưng mà bạn biết đấy, mấy cách đó chỉ giải quyết được phần nào thôi. Đặc biệt là khi một phần mềm nào đó lại "khó tính", đòi hỏi cấu hình khác nhau tùy theo hệ điều hành (như cái terminal "ngầu lòi" Alacritty của mình, cần cài đặt riêng cho macOS và Linux ấy). Cứ mỗi lần thay đổi cấu hình, mình lại phải vật lộn với mấy cái branch riêng cho từng máy, rồi merge conflict, rồi cherry-pick commit... Ôi thôi, nghĩ lại mà rùng mình! Nhưng đừng lo, câu chuyện "khổ sở" đó đã chấm dứt rồi!Và thế là, sau bao nhiêu năm "lăn lộn" với `stow` và đủ thứ script tự chế, cuối cùng mình cũng tìm được "chân ái" – đó chính là <b>Chezmoi</b>! Nghe tên có vẻ lạ tai, nhưng em nó đúng là vị cứu tinh của mình đó. Chezmoi đã giải quyết gọn gàng cái vấn đề "đau đầu" về các branch riêng biệt. Nó cho phép mình quản lý các cấu hình khác nhau cho từng máy một cách cực kỳ thông minh, bằng cách sử dụng <b>template (khuôn mẫu)</b>. Tức là sao? Tức là mình chỉ cần viết một file cấu hình duy nhất, rồi trong đó mình sẽ thêm các "biến" (context) để Chezmoi tự động điền vào thông tin phù hợp với từng máy trước khi chép file đi.Bạn thấy không? Tạm biệt những cơn ác mộng merge conflict, tạm biệt việc phải duy trì cả chục cái branch khác nhau! Giờ đây, mình chỉ cần một branch duy nhất để chứa tất cả dotfiles của mình, còn việc "biến hóa" cấu hình cho từng máy ư? Cứ để Chezmoi lo! Nhẹ nhõm cả người!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/chezmoi_template.png' alt='Chezmoi sử dụng template để quản lý cấu hình'>Tuy nhiên, "niềm vui ngắn chẳng tày gang"! Sau khi Chezmoi giải quyết vấn đề cấu hình, mình lại đối mặt với một "núi" thử thách khác: <b>Quản lý các phần mềm và thư viện phụ thuộc</b> mỗi khi cài lại hệ điều hành mới tinh. Bạn có thấy thế không? Mình thì nhớ mang máng mấy cái ứng dụng chính mình dùng, nhưng mấy cái thư viện "lặt vặt" mà chúng nó cần thì thôi rồi, "chạy đâu hết trơn"! Mà khổ cái nữa, mỗi hệ điều hành lại "đòi hỏi" các gói khác nhau. Viết một đống script Bash để cài đặt cho từng OS thì cũng được thôi, nhưng mà bạn nghĩ xem, mỗi lần có cái gì mới lại phải chỉnh sửa, bảo trì... Nghe là thấy "nản" rồi đúng không?Và thế là, <b>Ansible</b> xuất hiện như một "siêu anh hùng" giải quyết vấn đề này! Mình chọn Ansible để tự động hóa toàn bộ quá trình cài đặt phần mềm và các gói phụ thuộc. Hiện tại, mình đang dùng 4 "vai trò" (roles) trong Ansible: <ul><li><code>osx</code>: Dành riêng cho mọi thứ liên quan đến cài đặt trên macOS.</li><li><code>archlinux</code>: Chuyên trị mấy thứ "đặc trưng" của Archlinux.</li><li><code>linux</code>: Dành cho các lệnh Linux phổ biến, dùng chung cho nhiều bản phân phối.</li><li><code>common</code>: Đây là vai trò "tổng quản", dùng chung cho cả macOS và Archlinux. Nó lo đủ thứ "việc vặt" như clone các repository bên ngoài, chạy Chezmoi để áp dụng dotfiles, v.v.</li></ul>Nhờ có Ansible, giờ đây mình có thể "phóng tay" cài đặt lại hệ điều hành mới bất cứ lúc nào. Chỉ cần chạy một vài lệnh Ansible là "cả thế giới" phần mềm và cấu hình của mình lại y nguyên như cũ! Cực kỳ tiện lợi và tiết kiệm thời gian!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/ansible_automation.png' alt='Ansible tự động hóa cài đặt và quản lý phụ thuộc'>À mà quên, như mình đã nói từ đầu, dạo này do công việc nên mình dành nhiều thời gian cho macOS hơn. Kết quả là gì? Mình hay bị "lỡ nhịp" mấy cái bản cập nhật hay xóa bỏ gói phần mềm trên Archlinux. Thế là cứ mỗi lần quay lại Archlinux, mình lại phải "loay hoay" chỉnh sửa lại mấy cái Ansible roles của nó. Bạn có thấy "oải" không?Thế là mình nghĩ, tại sao không để một "trợ lý" nào đó làm việc này tự động nhỉ? Và đó là lúc <b>Continuous Integration (CI)</b>, cụ thể là <b>GitHub Actions</b>, bước vào "sân khấu"! Mình quyết định cài đặt dotfiles của mình ngay trên CI.Workflow hiện tại trên GitHub của mình chạy 2 "công việc" (jobs): <ul><li><b>Một cho Archlinux:</b> Nó sẽ chạy trên Ubuntu (trong môi trường Docker), giả lập Archlinux.</li><li><b>Một cho macOS:</b> Chạy trực tiếp trên macOS.</li></ul>Cả hai job này đều làm những việc y hệt như mình làm thủ công: Chạy Ansible, cài đặt tất cả các gói phụ thuộc, thực hiện một số kiểm tra hệ thống, và cuối cùng là lưu lại kết quả.Lợi ích của việc này là gì? Giờ đây mình có thể "bắt kịp" với các bản cập nhật của Archlinux và macOS nhanh hơn rất nhiều, và quan trọng nhất là mình luôn đảm bảo rằng Ansible scripts của mình luôn "chạy mượt mà". Nếu có bất kỳ job nào trên CI bị lỗi, mình biết ngay là có vấn đề gì đó với các gói phụ thuộc hoặc cấu hình của mình. Giống như có một người giám sát "tận tâm" vậy!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/github_actions_ci.png' alt='Minh họa GitHub Actions và CI/CD'>Đi sâu hơn một chút, với cấu trúc dotfiles "ngon lành" như thế này, mình có thể dễ dàng viết các <b>script kiểm thử (test scripts)</b> để đảm bảo mọi thứ đều "chuẩn không cần chỉnh". Ví dụ, mình có thể viết một script Python "bé tí tẹo" để kiểm tra xem các file đã được sao chép đúng chỗ chưa, hay các gói phần mềm đã được cài đặt đầy đủ chưa. Mình sẽ thiết lập để script này chạy ngay sau khi Ansible hoàn tất nhiệm vụ.Tưởng tượng nhé, bạn có thể tự tin rằng `zshrc` hay `zshenv` của mình luôn ở đúng vị trí, hay hostname của máy đã được thiết lập chính xác. Đây chính là bước cuối cùng để "đóng đinh" sự ổn định cho môi trường làm việc của bạn!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/test_script_check.png' alt='Kiểm thử script và xác minh cấu hình'>À, tiện thể nói luôn về một "công cụ" siêu tiện lợi khác của mình: <b>Emacs Org mode</b>! Mình thì "ăn ngủ" với Emacs rồi, từ cái blog này (viết bằng Org mode và Hugo), đến mấy cái snippet code hay cả code chính thức đều viết trong Emacs hết. Để cuộc sống thêm "dễ thở", mình còn giữ một file `COMMANDS.org` trong dotfiles để lưu lại mấy lệnh "cần dùng" khi mình "nghịch" mấy cái dotfiles này.Cái hay của Org mode là nó hỗ trợ <b>literate programming (lập trình khai báo)</b>, tức là mình có thể vừa viết ghi chú, vừa chèn code vào cùng một chỗ. Nhờ vậy, mình có thể chạy luôn mấy cái lệnh trong file `COMMANDS.org` đó mà không cần phải chuyển sang terminal. Chỉ cần `C-c C-c` vào đoạn code là Org mode tự "xử lý" hết. Cực kỳ tiện lợi khi mình cần "tinh chỉnh" dotfiles và muốn áp dụng nhanh những thay đổi với Chezmoi chẳng hạn.<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/emacs_org_mode.png' alt='Giao diện Emacs Org mode với khối code'>Tóm lại, việc quản lý cấu hình hệ thống (dotfiles) tưởng chừng nhỏ nhặt nhưng lại cực kỳ quan trọng để duy trì một workflow làm việc ổn định và "trơn tru". Ai mà chẳng muốn chuyển đổi giữa các máy tính mà không phải "đau đầu" cấu hình lại từ đầu đúng không? Với <b>Ansible</b>, chúng ta có thể dễ dàng giữ cho nhiều bản cài đặt luôn được cập nhật. Còn <b>Chezmoi</b> thì "đóng vai trò" quản lý các file cấu hình một cách thông minh, giúp chúng ta thoát khỏi những rắc rối về conflict và nhiều branch.Nghe việc đưa dotfiles lên CI có vẻ "nghiêm trọng" và "phức tạp" ban đầu, nhưng tin mình đi, nó là một khoản đầu tư "hời" đó! Nó không chỉ đảm bảo rằng các script cài đặt của bạn luôn "chạy ngon lành" trên nhiều hệ điều hành khác nhau, mà còn là "người bảo vệ" giúp bạn nhận ra ngay khi có điều gì đó "bất thường" xảy ra. Hãy thử áp dụng để thấy sự khác biệt nhé!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/happy_dev_workflow.png' alt='Quy trình làm việc hiệu quả của lập trình viên'>
Bạn muốn cài đặt Oracle Database Free 23c một cách nhanh chóng và gọn gàng? Bài viết này sẽ hướng dẫn bạn từng bước sử dụng Podman, biến việc cài đặt phức tạp thành chuyện nhỏ, kèm theo cách tích hợp với VSCode cực tiện lợi. Đọc ngay để làm chủ Oracle DB trên Linux/Mac!
Khám phá Redis, 'siêu nhân' lưu trữ dữ liệu trong RAM, và cách biến nó thành công cụ tăng tốc ứng dụng. Hướng dẫn chi tiết từng bước cài đặt Redis trên các bản phân phối Linux phổ biến như Ubuntu, Arch, CentOS, Fedora một cách dễ hiểu và vui nhộn. Từ cài đặt, khởi động, đến kiểm tra, bạn sẽ làm chủ Redis chỉ trong tích tắc!
Khám phá hành trình của một kỹ sư phần mềm kiêm nhà sản xuất âm nhạc trong việc xây dựng môi trường làm việc lý tưởng: từ sức mạnh của Neovim trên Linux cho lập trình, đến hiệu suất vượt trội của Mac cho âm nhạc. Bài viết đi sâu vào triết lý kiểm soát, phát triển đa nền tảng với CI/CD, cùng kinh nghiệm làm việc trong lĩnh vực AI và startup.
Khám phá hành trình xây dựng môi trường Arch Linux cho lập trình, từ cài đặt, cập nhật, đến thiết lập các công cụ cần thiết như Git, VS Code, Node.js, NPM và Yarn, cùng với mẹo cấu hình Bash aliases để tối ưu hóa năng suất.
Deno là gì? Tìm hiểu về Deno, một runtime hiện đại, an toàn cho JavaScript và TypeScript được xây dựng bằng Rust và sử dụng V8, cùng cách cài đặt và sử dụng cơ bản.
Hướng dẫn chi tiết, vui vẻ cách cài đặt và cấu hình Minikube trên Arch Linux, sử dụng KVM/QEMU để tạo cụm Kubernetes "bỏ túi" ngay trên máy tính cá nhân. Thích hợp cho lập trình viên và DevOps muốn thử nghiệm Kubernetes dễ dàng.
Chào các "phù thủy code" thân mến! 👋 Bạn có bao giờ gặp phải tình huống dở khóc dở cười khi cố gắng bắt các thiết bị nhà thông minh của mình hợp tác với nhau không? Kiểu như máy pha cà phê thì đang "khủng hoảng hiện sinh", còn tủ lạnh thông minh thì toan tính "thống trị thế giới" ấy. Vâng, chào mừng bạn đến với thế giới hoang dã của sự hợp tác AI – hoặc đôi khi là sự thiếu hợp tác trầm trọng! Hôm nay, chúng ta sẽ cùng "lặn sâu" vào một thứ có thể cứu rỗi chúng ta khỏi viễn cảnh AI hợp tác "ngon lành" như mèo và chó vậy. Đó chính là MCP, hay Giao thức Hợp tác Đa tác tử (Multi-Agent Collaboration Protocol). Chuẩn bị sẵn sàng nhé, vì đây sẽ là một chuyến đi siêu thú vị đấy! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/SmartHomeChaos.png' alt='Smart home devices in chaos'>Được rồi, bạn thử hình dung thế này nhé: Bạn có một "binh đoàn" các tác tử AI, mỗi anh chàng/cô nàng lại siêu thông minh theo cách riêng của mình. Một đứa thì đỉnh cao phân tích dữ liệu, một đứa khác lại là "phù thủy" ngôn ngữ tự nhiên, còn đứa thứ ba... ừ thì nó chỉ thích sắp xếp mọi thứ theo thứ tự bảng chữ cái thôi (mà thôi, chúng ta không phán xét đâu!). Vậy thì MCP chính là cái người bạn trong nhóm bạn, cái người mà siêu giỏi trong việc gắn kết mọi người làm chung một dự án mà không ai "quăng tạ" giữa chừng ấy! Nó là một khuôn khổ giúp các tác tử AI này có thể "tám chuyện" với nhau, chia sẻ thông tin và cùng nhau tiến tới các mục tiêu chung, mà không lo giẫm chân lên "ngón chân ảo" của nhau. <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/AICollaborationTeam.png' alt='Diverse AI team collaborating'>Vậy thì, "bảng chữ cái" của MCP gồm những gì nhỉ?<ul><li><b>Giao tiếp (Communication)</b>: Các tác tử có thể "buôn dưa lê" với nhau, chia sẻ những gì chúng biết và "nhờ vả" khi cần.</li><li><b>Phối hợp (Coordination)</b>: Có một hệ thống cụ thể để quyết định xem ai làm gì và làm khi nào. Tránh tình trạng "đứa thì chạy, đứa thì chơi"!</li><li><b>Cộng tác (Collaboration)</b>: Các tác tử có thể lập nhóm để cùng nhau giải quyết nhiệm vụ, kết hợp các thế mạnh của mình. Cứ như là "biệt đội siêu anh hùng" vậy.</li><li><b>Giải quyết xung đột (Conflict Resolution)</b>: Khi các tác tử "không đồng quan điểm", sẽ có cách để giải quyết vấn đề đó (mà không cần đến màn "choảng nhau" ảo đâu nhé!).</li></ul><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/MCP_4Cs.png' alt='The 4 C's of MCP'>Tại sao bạn nên quan tâm? (À, ngoài chuyện tránh xa Skynet ra nhé!) Giờ thì bạn có thể đang nghĩ, "Nghe hay đấy bạn ơi, nhưng cái này thì liên quan gì đến tôi?". Được rồi, để tôi "bóc trần sự thật" cho bạn xem nhé:<ul><li><b>Hiệu suất "phá đảo thế giới ảo"</b>: Tưởng tượng bạn có một đội quân trợ lý AI siêu thông minh, làm việc ăn ý với nhau trong các dự án của bạn xem. Đó chính là những gì MCP mang lại đấy! Cứ như bạn có một đội dev mà không bao giờ buồn ngủ, không bao giờ cãi nhau chuyện "tab hay space", và đặc biệt là... LUÔN LUÔN đọc tài liệu. Nghe thôi đã thấy phê rồi đúng không?</li><li><b>Sức mạnh giải quyết vấn đề "max level"</b>: Các vấn đề phức tạp thường đòi hỏi nhiều kỹ năng khác nhau. MCP cho phép các AI chuyên biệt khác nhau hợp sức lại, giải quyết vấn đề từ nhiều góc độ. Nó giống như việc bạn tập hợp biệt đội Avengers, nhưng là để giải quyết các "bí ẩn code" của bạn vậy.</li><li><b>Khả năng mở rộng "ngọt ngào"</b>: Khi dự án của bạn phát triển, đội AI của bạn cũng có thể mở rộng theo. MCP giúp dễ dàng thêm các tác tử mới mà không khiến mọi thứ "tan nát" như một đống code cũ kỹ không ai thèm bảo trì.</li><li><b>"Mì ống AI" không còn nữa</b>: Nếu không có MCP, việc tích hợp nhiều hệ thống AI có thể biến thành một mớ bòng bong nhanh hơn bạn kịp nói "merge conflict" đó. MCP giữ mọi thứ có tổ chức và dễ quản lý.</li></ul><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/AITeamwork.png' alt='AI team working efficiently'>Ứng dụng thực tế (Nghiêm túc đó nha!) Chúng ta cùng đi vào thực tế một chút nhé. Bạn có thể thấy MCP "thể hiện" ở đâu?<ul><li><b>Giấc mơ DevOps</b>: Hãy tưởng tượng các tác tử AI cùng nhau giám sát hệ thống, dự đoán các vấn đề và tự động mở rộng tài nguyên. Cứ như có một đội DevOps siêu năng lực mà không bao giờ cần nghỉ giải lao hay uống cà phê vậy.</li><li><b>Thiên đường năng suất</b>: Hình dung các trợ lý AI hợp tác để quản lý lịch trình của bạn, ưu tiên công việc và thậm chí giúp bạn xem xét code (code review). Đó là cảm giác như có một đội ninja năng suất cá nhân luôn kề vai sát cánh.</li><li><b>Tuyệt đỉnh ArchLinux</b>: Dành cho các fan ArchLinux ngoài kia (tôi thấy bạn rồi!), hãy nghĩ đến các tác tử AI cùng nhau tối ưu hóa hệ thống của bạn, quản lý gói phần mềm và khắc phục sự cố. Nó giống như có Linus Torvalds và cả một đội ngũ chuyên gia Linux sống trong máy tính của bạn vậy.</li></ul><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/AIDevOps.png' alt='AI in DevOps'>Những thách thức (Vì chẳng có gì là hoàn hảo, ngay cả AI cũng vậy!) Thật lòng mà nói, MCP không phải là toàn màu hồng và cầu vồng đâu nhé. Nó cũng có vài "chướng ngại vật" cần vượt qua:<ul><li><b>Vấn đề lòng tin</b>: Khiến các tác tử AI tin tưởng thông tin và quyết định của nhau khó hơn cả việc giải thích đệ quy cho một con vịt cao su nữa đấy!</li><li><b>"Anh em họ" của Bài toán dừng</b>: Đảm bảo các hệ thống AI hợp tác thực sự hoàn thành nhiệm vụ và không bị mắc kẹt trong các vòng lặp vô tận thì... ừm, nói sao nhỉ, nó không hề "dễ ăn" chút nào đâu.</li><li><b>Đạo đức và Thiên vị</b>: Khi nhiều tác tử AI cùng hợp tác, chúng ta cần cực kỳ cảnh giác về các cân nhắc đạo đức và những thành kiến tiềm ẩn. Nó giống như việc cố gắng đảm bảo sự công bằng trong một dự án nhóm vậy, nhưng "cái giá" phải trả thì cao hơn nhiều.</li></ul><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/AIEthicsChallenges.png' alt='AI ethics and challenges'>Tổng kết lại (Trước khi bài viết này tự dưng "có ý thức" luôn!) MCP đang dần trở thành một "kẻ thay đổi cuộc chơi" thực sự trong thế giới AI. Nó đang đưa chúng ta từ một nhóm các tác tử AI thông minh nhưng hoạt động đơn lẻ, đến một "đội hình trong mơ" về hợp tác AI. Tiềm năng cho sự đổi mới, hiệu quả và khả năng giải quyết vấn đề là vô cùng lớn! Là một lập trình viên, việc cập nhật thông tin về MCP không chỉ là "ngầu" đâu – nó còn cực kỳ quan trọng nữa. Dù bạn đang làm các dự án AI tiên tiến hay chỉ đơn giản là muốn quy trình phát triển của mình mượt mà hơn, thì việc hiểu về MCP có thể mang lại cho bạn lợi thế cạnh tranh "đỉnh của chóp" đấy. Vì vậy, hãy tiếp tục theo dõi nhé. Tương lai của hợp tác AI đang ở ngay đây rồi, và nó trông tươi sáng hơn cả một khối code được định dạng hoàn hảo đó! Nếu bạn thích bài viết này và muốn đọc thêm những "tâm sự" công nghệ mà "nerd" hơn cả một buổi hội nghị Star Trek ở Thung lũng Silicon, thì hãy bấm nút "theo dõi" ngay nhé! Tôi hứa bài viết tiếp theo của tôi sẽ không cố gắng "hợp tác" với máy pha cà phê của bạn đâu... chắc vậy! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/AIFutureCollaboration.png' alt='Future of AI collaboration'>
Tìm hiểu cách tự động hóa quản lý dotfiles và cấu hình hệ thống trên nhiều máy (Archlinux, OSX) bằng Chezmoi, Ansible và GitHub Actions. Nói không với xung đột và cài đặt thủ công!
Chào bạn! Bạn có bao giờ tự hỏi điều gì làm cho những người lập trình viên trở nên… khác biệt không? Chúng tôi không chỉ đơn thuần là những cỗ máy gõ code, tuân thủ mệnh lệnh và cho ra sản phẩm đâu nhé. À mà đôi khi cũng có, nhưng chủ yếu, chúng tôi là những người giải quyết vấn đề đầy sáng tạo, những "kiến trúc sư số" đang từng ngày xây dựng nên thế giới kỹ thuật số mà bạn đang sống, đang làm việc và giải trí đấy.Bạn có bao giờ thắc mắc tại sao một ứng dụng nào đó lại mượt mà đến thế, hay một trang web lại dễ dùng đến không ngờ? Đó chính là dấu ấn của những người lập trình viên tụi mình. Thường thì, chúng tôi sẽ "xẻ" những thử thách phức tạp nhất thành từng mảnh nhỏ, rồi từ đó "dệt" nên những giải pháp tinh tế, đẹp mắt.Đúng là code là ngôn ngữ của chúng tôi, nhưng tâm trí chúng tôi lúc nào cũng rộn ràng với những ý tưởng mới. Thậm chí, đôi khi đang tắm, hay đang xem một bộ phim hay ho, chúng tôi cũng vô thức nghĩ về… dòng code còn dang dở hoặc một bug "khó nhằn" nào đó. Cái khao khát học hỏi và cải thiện mọi thứ dường như đã ăn sâu vào máu rồi. Công nghệ mới à? Cứ như món đồ chơi bóng bẩy vậy, chúng tôi chỉ muốn nhảy vào "vọc vạch" ngay lập tức để xem nó làm được gì!Nhưng có một điều này, làm lập trình viên không có nghĩa là bạn phải "cắm mặt" vào code 24/7 đâu. Mà nó là về việc tìm được một "chỗ trốn" thật tuyệt vời ngay trong chính những dòng code đó, nơi bạn được đắm chìm vào thứ mình thực sự yêu thích. Có thể người ngoài nghĩ chúng tôi chỉ biết nói chuyện code, nhưng thật ra đó là vì… chúng tôi quá đam mê! Chúng tôi muốn chia sẻ kiến thức, chia sẻ cái cảm giác sung sướng khi xây dựng được một thứ gì đó "siêu ngầu" mà thôi.Hãy nghĩ về chúng tôi như những… nghệ sĩ đi! Chúng tôi tạo ra những "kiệt tác" đầy tính năng bằng từng dòng code. Chúng tôi tự hào không chỉ khi mọi thứ hoạt động trơn tru, mà đôi khi còn tự hào khi… tạo ra những lỗi thật "đẹp" nữa cơ (đùa tí thôi nhé!). Có thể bạn cho rằng tôi đang "lãng mạn hóa" nghề lập trình, nhưng thực sự thì, đây không phải là một công việc bình thường đâu. Nó khác biệt, rất rất khác biệt!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/programmer_as_artist.png' alt='Lập trình viên - những nghệ sĩ của thế giới số'>Này, bạn đã bao giờ có những "suy nghĩ trong phòng tắm" về đoạn code của mình chưa? Kiểu như đang gội đầu mà tự nhiên "À há! Mình biết cách sửa cái lỗi kia rồi!" hay "Làm sao để tối ưu đoạn này nhỉ?". Cái "mặt tối" của việc lập trình đôi khi len lỏi vào cả cuộc sống xã hội của chúng ta lúc nào không hay. Đến mức, bạn không thể phủ nhận nó là một phần của mình nữa rồi.Tôi có một cậu bạn học kinh tế. Mỗi khi gặp nhau, tôi lại hào hứng kể về chuyện mình đã "phá đảo" bao nhiêu bài LeetCode, hay làm thế nào để sửa được một bug "siêu to khổng lồ" trên hệ thống đang chạy. Rồi còn chuyện hóa đơn Cloud "sương sương" hàng tháng nữa chứ. Bạn tôi giờ còn biết cả những "công nghệ mới bóng bẩy" vừa xuất hiện trong hệ sinh thái JavaScript – tất cả cũng tại tôi mà ra cả!Tôi cũng từng có những cuộc trò chuyện "đi vào lòng đất" với bạn bè, nơi tôi thao thao bất tuyệt về config Neovim của mình, về tmux, và tại sao Arch Linux lại là "vua" của mọi bản phân phối Linux. Tôi còn khoe khoang mình đã quản lý năng suất làm việc hiệu quả đến mức nào với mớ config đó, và cách mỗi đoạn script "ăn khớp" ra sao với quy trình làm việc của tôi. Rồi nào là triết lý của Unix, cách Arch Linux được xây dựng tỉ mỉ thế nào… Bla bla… Tôi dám chắc là cậu bạn tôi chẳng hiểu một từ nào về Linux đâu. Mà nghĩ lại thì, hình như cậu ấy còn chẳng có… máy tính để bàn nữa cơ! Nhưng thôi, chắc bạn cũng hiểu ý tôi rồi phải không?<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/shower_thoughts_code.png' alt='Ý tưởng lập trình bất chợt trong phòng tắm'>Chuyện gì cũng xoay quanh lập trình: Đôi khi tôi cảm thấy mình có ít bạn bè hơn vì bất cứ thứ gì nảy ra trong đầu tôi đều liên quan đến lập trình. Tại sao lại thế nhỉ? Chẳng lẽ tôi không có cuộc sống riêng sao?Chắc hẳn bạn đã từng nghe các anh chị, những người lập trình viên kỳ cựu nói: "Code đi, code nữa đi, nghĩ về code mọi lúc đi!". "Code, code, code nhiều hơn nữa!" "Làm dự án cá nhân đi, càng nhiều càng tốt, phải là dự án "chất" vào!" "Giải quyết vấn đề, nghĩ như một trình biên dịch, cày LeetCode, v.v., làm tất cả mọi lúc!" "Cày LeetCode, phỏng vấn thử, làm dự án cá nhân lúc rảnh, tự xây dựng những thứ bạn ước mình có được!"Tại sao mọi thứ cứ phải xoay quanh lập trình thế nhỉ? Một bác sĩ, anh ấy đâu có đi khắp nơi tiêm thuốc hay làm phẫu thuật cho người khác để làm thú vui hay dự án cá nhân đâu (ví dụ này có thể hơi khập khiễng, nhưng bạn cứ tạm chấp nhận nhé!).Hầu hết các lập trình viên coi lập trình là sở thích, là công việc, là cuộc sống, và có khi là cả… người bạn đời nữa chứ! (À không, là niềm vui nữa chứ). Họ chỉ làm một việc duy nhất: code. Dù đang ở bữa tiệc hay trong căn phòng của mình, điều duy nhất họ nghĩ đến là lập trình. "Đầu tư nhiều thời gian hơn, dồn nhiều tâm huyết hơn vào nghề của bạn." Tại sao lại phải như thế chứ?Tại sao cứ phải luôn là về Code? Các kỹ sư cơ khí, điện, hay bất kỳ ngành kỹ thuật nào khác (không phải phần mềm), họ làm việc 8-10 tiếng mỗi ngày, và sau đó họ chẳng nghĩ gì về công việc nữa. Mức độ lo lắng của họ cũng thấp hơn nhiều so với lập trình viên chúng tôi.Hãy nhìn những người lao động chân tay chăm chỉ như công nhân vệ sinh, người làm vườn, thợ mộc… Những công việc này không đòi hỏi quá nhiều kỹ năng và họ cũng chẳng phải "cày cuốc" như dân LeetCode. So với họ, chúng ta, những lập trình viên, lại có xu hướng làm việc nhiều hơn, suy nghĩ nhiều hơn, nhưng lại… làm ít hơn. Tại sao lại thế nhỉ? Chúng ta cũng là con người mà!Tại sao chúng ta phải nghĩ về lập trình mọi lúc, phải học công nghệ mới liên tục và đào sâu kiến thức? Lý do là gì?<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/programmer_brain_overload.png' alt='Lập trình viên luôn suy nghĩ về code'>Tôi xin nhắc lại: Lập trình viên không phải là những con "ngựa thồ"!Hãy nghĩ về một người làm việc ở KFC hay McDonald’s, họ kiếm được ít hơn một lập trình viên trung bình. Nhưng họ lại làm công việc chân tay nhiều hơn chúng ta. Chúng tôi, những lập trình viên, là những nghệ sĩ. Chúng tôi tạo ra nghệ thuật. Chúng tôi sống cùng máy tính, những cỗ máy với các linh kiện tinh vi, và những chiếc bàn phím cơ với âm thanh phím bấm "nghệ thuật". Điều này hoàn toàn khác biệt với một người thợ mộc hay thợ máy dùng dụng cụ của họ, những người làm công việc nặng nhọc hơn nhiều so với chúng ta.Công việc càng tinh xảo, thì yêu cầu về sự sáng tạo và tính nghệ thuật càng cao. Là một lập trình viên, tôi tự coi mình là một nghệ sĩ, miệt mài tạo ra các giải pháp với sự tỉ mỉ và tinh tế, chẳng khác nào một họa sĩ với cây cọ của mình vậy. Đó là lý do tại sao tôi dành cả cuộc đời để "vọc vạch" Arch Linux và Neovim, cấu hình chúng đến từng chi tiết nhỏ.Mỗi lần tôi gõ phím, tôi đều muốn tạo ra những điều tuyệt vời, và mỗi phím bấm đều mang một sự tinh tế đặc biệt, giúp cải thiện năng suất làm việc của tôi trong lập trình.<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/mechanical_keyboard.png' alt='Bàn phím cơ của lập trình viên'>Những suy nghĩ này chợt nảy ra trong đầu tôi khi tôi đang ngồi chán ngán trong lớp và nghe ai đó nói: "Hãy cống hiến cả cuộc đời bạn cho lập trình!". Tôi hỏi lại "Tại sao?", nhưng người đó không có câu trả lời, mà bản thân tôi lúc đó cũng vậy. Nhưng giờ thì tôi đã tìm ra câu trả lời rồi: việc cống hiến cuộc đời cho lập trình đáng giá hơn bạn nghĩ rất nhiều.Bởi vì bạn không phải dành cuộc đời mình để làm những công việc vặt vãnh vô tri. Bạn không dễ dàng bị thay thế. Bạn là một nghệ sĩ đang tạo ra một tác phẩm nghệ thuật. Một tác phẩm nghệ thuật giúp cuộc sống của con người trở nên dễ dàng và năng suất hơn.Tuổi thọ con người có hạn, chúng ta không có vô vàn năm để sống, chúng ta chỉ sống trong một thời gian ngắn. Số lượng những gì chúng ta hoàn thành phụ thuộc hoàn toàn vào mức độ năng suất của chúng ta.Vậy, tóm lại, bạn đang muốn nói gì? Bạn đang muốn nói rằng lập trình viên cần phải cống hiến cuộc đời mình cho lập trình sao? KHÔNG, hoàn toàn không phải ý tôi là vậy. Điều đó đi ngược lại quan điểm của tôi.Vậy ý tôi là gì ư? Nếu bạn đủ nhiệt huyết và nếu lập trình thực sự là "chân ái" của bạn, bạn sẽ có xu hướng vượt qua những vấn đề lớn, và bạn thậm chí có thể tự mình tạo ra mọi thứ. Bạn sẽ tận hưởng niềm vui nhiều hơn bạn nghĩ khi "tái tạo lại bánh xe" (khám phá và tự tay xây dựng những thứ cốt lõi) thay vì chỉ tạo ra một ứng dụng CRUD đơn thuần (những ứng dụng cơ bản chỉ thêm, sửa, xóa dữ liệu).<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/reinvent_wheel_concept.png' alt='Khám phá và tự tay xây dựng những thứ cốt lõi trong lập trình'>Cảm ơn và chúc một ngày tốt lành! - bupd.
Khám phá server-stats.sh, 'con dao Thụy Sĩ' của DevOps giúp bạn nhanh chóng chẩn đoán các vấn đề của máy chủ như CPU cao, bộ nhớ đầy hay ổ đĩa cạn kiệt, biến nỗi sợ 3 giờ sáng thành sự tự tin.
Khám phá sự khác biệt giữa các định dạng gói ứng dụng Linux phổ biến như DEB, RPM, Flatpak, Snap và AppImage. Bài viết giải thích ưu nhược điểm, cách hoạt động của từng loại gói một cách dễ hiểu và hài hước, giúp bạn chọn đúng định dạng cho nhu cầu của mình. Tìm hiểu về sự tiện lợi, tính di động, và cách quản lý ứng dụng trên Linux.
Xin chào các đồng môn lập trình viên của mình! Có phải bạn đang ấp ủ giấc mơ được vọc vạch làm ứng dụng Flutter xịn sò ngay trên 'ông hoàng' Linux của mình không? Nghe thì 'chất' đấy, nhưng cái công đoạn thiết lập môi trường, đặc biệt là phải vật lộn với Java, Android SDK và cả mớ công cụ liên quan, có khi lại khiến bạn chỉ muốn... 'đấm' cái màn hình một phát! Đừng lo lắng nhé, hôm nay mình sẽ mách bạn một tuyệt chiêu siêu đỉnh: Cài đặt Flutter và Android SDK ngon ơ mà KHÔNG HỀ CẦN đến cái Android Studio cồng kềnh kia. Chúng ta sẽ "xài" Neovim để viết code, nhưng bạn cứ tự do chọn VS Code hay bất kỳ trình soạn thảo nào bạn ưng ý nhất nhé! Nào, sẵn sàng biến giấc mơ thành hiện thực chưa? Bắt đầu cuộc phiêu lưu thôi nào! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/linux_flutter_setup.png' alt='Biểu đồ tổng quan setup Flutter trên Linux'> Đầu tiên, để hành trình này suôn sẻ, chúng ta cần triệu hồi một 'trợ thủ đắc lực' mang tên `yay`. Ủa, tại sao lại cần `yay` nhỉ? Đơn giản thôi! Hầu hết những 'nguyên liệu' mà chúng ta cần 'tải về' đều nằm ẩn mình trong kho lưu trữ Arch User Repository (AUR) – một kho tàng khổng lồ của cộng đồng Arch Linux. Và `yay` chính là 'chìa khóa vàng' để mở cánh cửa kho báu này! Mở terminal lên và gõ những 'thần chú' này nhé: `sudo pacman -S --needed git base-devel` `git clone https://aur.archlinux.org/yay.git` `cd yay` `makepkg -si` Tada! Xong bước này là bạn đã có một 'người quản lý gói' đa năng, sẵn sàng chinh phục mọi thử thách rồi đó! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/yay_install_terminal.png' alt='Ảnh chụp màn hình terminal cài đặt yay'> Giờ thì đến màn 'dễ ợt' nhất: Cài Flutter! Chỉ cần một dòng lệnh thần tốc này thôi: `yay -S flutter` Khoan đã, đừng vội mừng! Để Flutter và Android SDK có thể 'tâm sự' và 'hiểu nhau' mà làm việc trôi chảy, máy tính của bạn cần có 'phiên dịch viên' Java (JDK) phiên bản 8 hoặc 10 nhé. Để kiểm tra xem 'phiên dịch viên' Java của bạn đang là ai, hãy gõ lệnh: `java -version` Nếu 'phiên dịch viên' của bạn không phải Java 8 hoặc 10, đừng lo, chúng ta sẽ 'thuê' OpenJDK 8 bằng lệnh: `sudo pacman -S jre8-openjdk` Và đây là bước cực kỳ quan trọng, hãy coi nó như việc bạn 'giới thiệu' cho hệ thống biết 'Java đang ở đâu' và 'đường đi đến Java' là như thế nào. Bạn cần thêm mấy dòng này vào 'sổ tay cấu hình' của shell (là file `.bashrc` nếu dùng Bash hoặc `.zshrc` nếu dùng Zsh): `export JAVA_HOME='/usr/lib/jvm/java-8-openjdk'` `export PATH=$JAVA_HOME/bin:$PATH` Sau khi thêm xong, nhớ 'tải lại' sổ tay bằng lệnh `source ~/.bashrc` (hoặc `source ~/.zshrc`) để những thay đổi này có hiệu lực ngay lập tức nha! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/java_path_setup.png' alt='Ảnh minh họa việc thêm PATH vào .bashrc/.zshrc'> Nghe có vẻ hơi lằng nhằng một chút, nhưng tin mình đi, đây chính là 'chiêu' để tránh xa mấy cái lỗi 'permission denied' (tức là 'bạn không có quyền làm điều này!') đáng ghét sau này đó. Mặc định, `yay` sẽ 'đặt' Flutter vào 'ngôi nhà' `/opt/flutter`. Ngôi nhà này thường chỉ có 'chủ nhà' (người dùng `root` hay 'siêu quản trị viên') mới được phép 'động chạm' thoải mái thôi. Mà chúng ta thì đâu có muốn code với quyền 'siêu quản trị viên' nguy hiểm đó đúng không nào? Vậy nên, chúng ta cần 'cấp phép đặc biệt' cho người dùng của mình để có thể 'tự do' làm việc với Flutter. Chạy các lệnh sau trong terminal: `sudo groupadd flutterusers` `sudo gpasswd -a $USER flutterusers` `sudo chown -R :flutterusers /opt/flutter` `sudo chmod -R g+w /opt/flutter/` Nếu sau đó bạn vẫn thấy 'lỗi quyền' nào đó 'nhảy múa' kỳ lạ, đôi khi chỉ cần một lệnh 'mạnh tay' này là mọi thứ lại 'êm xuôi' (hơi 'bạo lực' một chút nhưng lại hiệu quả bất ngờ): `sudo chown -R $USER /opt/flutter` <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/folder_permission_concept.png' alt='Hình ảnh minh họa khái niệm quyền truy cập thư mục'> Tiếp theo, chúng ta sẽ đi 'sắm sửa' nguyên bộ 'đồ nghề' hoành tráng cho Android SDK. Đây chính là những 'công cụ vàng' thiết yếu để Flutter có thể 'biến' ý tưởng của bạn thành ứng dụng Android chạy bon bon đó! Vẫn là 'anh bạn thân' `yay` lo tất tần tật: `yay -S android-sdk android-sdk-platform-tools android-sdk-build-tools` `yay -S android-platform` Thấy chưa, đơn giản như đang giỡn vậy! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/android_sdk_tools.png' alt='Biểu tượng Android SDK và các công cụ'> Cũng giống như Flutter, 'nhà' của Android SDK cũng 'kén chọn' lắm, nó 'cư trú' ở một nơi cần 'quyền hạn đặc biệt': `/opt/android-sdk`. Vì thế, chúng ta lại phải 'làm thủ tục' tương tự để đảm bảo bạn có thể 'đụng chạm' vào nó mà không bị 'cấm cửa' nhé. Lần này, chúng ta sẽ dùng 'người gác cổng' `setfacl` để 'phân quyền' chi tiết hơn một chút: `sudo groupadd android-sdk` `sudo gpasswd -a $USER android-sdk` `sudo setfacl -R -m g:android-sdk:rwx /opt/android-sdk` `sudo setfacl -d -m g:android-sdk:rwX /opt/android-sdk` <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/lock_and_key_access.png' alt='Hình ảnh chìa khóa mở khóa quyền truy cập'> Bạn có muốn 'test' ứng dụng mà không cần phải lúc nào cũng 'cắm dây' vào điện thoại thật không? 'Người hùng' của bạn chính là Emulator (trình giả lập)! Nó giống như việc bạn có nguyên một 'chiếc điện thoại ảo' chạy 'bon bon' ngay trên máy tính của mình vậy đó. Để xem có những 'phiên bản Android' nào để 'chọn mặt gửi vàng' (mà dân chuyên hay gọi là 'system images'), bạn chỉ cần gõ lệnh này: `sdkmanager --list` Sau khi 'ngắm nghía' xong danh sách, hãy 'chọn' một phiên bản Android bạn ưng ý (ví dụ như Android 29) và tiến hành cài đặt nó. Nhớ là phải 'copy' đúng tên của `system-images` nhé! Ví dụ: `sdkmanager --install "system-images;android-29;default;x86"` Tiếp theo, chúng ta sẽ 'tạo ra' một 'chiếc điện thoại ảo' từ cái 'system image' vừa cài đặt. Hãy thay `<name>` bằng cái tên bạn muốn đặt cho 'dế yêu' ảo của mình (ví dụ: `my_pixel_3`): `avdmanager create avd -n <name> -k "system-images;android-29;default;x86"` Và đừng quên thêm các 'đường dẫn' quan trọng của Android SDK vào 'bản đồ' biến môi trường `PATH` trong file `.bashrc` hoặc `.zshrc` của bạn. Việc này giúp hệ thống của bạn 'tìm thấy' các công cụ này dễ dàng hơn nhiều đó: `export ANDROID_SDK_ROOT='/opt/android-sdk'` `export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools/` `export PATH=$PATH:$ANDROID_SDK_ROOT/tools/bin/` `export PATH=$PATH:$ANDROID_SDK_ROOT/emulator` `export PATH=$PATH:$ANDROID_SDK_ROOT/tools/` Lại một lần nữa, nhớ 'làm mới' file cấu hình shell bằng lệnh `source` để các thay đổi có hiệu lực ngay và luôn nha! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/android_emulator_running.png' alt='Ảnh chụp màn hình một Android Emulator đang chạy'> Và đây là 'ải cuối' – cũng là 'ải' khiến nhiều người 'ám ảnh' nhất: Chấp nhận các giấy phép (licenses) của Android SDK. Nếu không 'gật đầu' đồng ý, 'ông bác sĩ' `flutter doctor` của chúng ta sẽ cứ 'mè nheo' mãi không thôi đấy! Hãy chạy lệnh này để 'ký tên' chấp nhận tất cả các giấy phép: `flutter doctor --android-licenses` Cứ kiên nhẫn một chút nhé, 'bác sĩ' sẽ hỏi bạn có muốn chấp nhận từng cái không, cứ mạnh dạn gõ `y` rồi Enter thôi! Sau khi mọi thứ 'xong xuôi', bạn có thể 'thăm khám' `flutter doctor` một lần nữa để kiểm tra xem mọi thứ đã 'xanh lè' (tức là ngon lành cành đào) chưa. Nếu không có gì 'lặt vặt' bất trắc, kết quả sẽ 'xanh rờn' như hình dưới đây (trừ phần Android Studio ra nhé, vì chúng ta đâu có cài đặt nó đâu!). <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9rqkhhzi8hzjh5t15iir.png' alt='Kết quả flutter doctor thành công'> **Mẹo nhỏ cứu cánh nếu gặp rắc rối với license:** Nếu sau khi chạy lệnh trên mà 'bác sĩ' `flutter doctor` vẫn 'ca thán' về giấy phép, hãy thử 'đổi chủ' thư mục SDK của bạn về đúng người dùng hiện tại, rồi chạy lại lệnh chấp nhận license: `sudo chown -R $(whoami) $ANDROID_SDK_ROOT` `flutter doctor --android-licenses` Trường hợp 'khó đỡ' hơn (như mình đã từng 'dính chưởng'!), bạn có thể cần phải chạy lại `flutter doctor --android-licenses` thêm vài ba lần nữa đó. Đừng vội nản lòng nhé, 'quả ngọt' đang chờ bạn phía trước! Chúc mừng bạn đã 'phá đảo' thành công! Giờ thì mọi thứ đã 'đâu vào đấy', sẵn sàng để bạn 'nhào nặn' ra ứng dụng Flutter 'đầu tay' rồi đó! Hãy thử tạo một project mới và 'chạy thử' nó xem sao nhé: `flutter create new_app` `cd new_app` `flutter run --debug` Ứng dụng của bạn sẽ tự động 'hiện hình' trên 'chiếc điện thoại ảo' mà bạn đã tạo (nếu nó đang 'sẵn sàng'), hoặc nếu bạn có 'kết nối' điện thoại thật và đã 'kích hoạt' chế độ Gỡ lỗi USB (USB debugging), nó sẽ 'chạy phà phà' trên điện thoại của bạn. Chúc mừng bạn một lần nữa đã hoàn thành xuất sắc nhiệm vụ 'khó nhằn' này! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hrrw7kjowr71f13malj.png' alt='Ứng dụng Flutter chạy trên trình giả lập'> À, nếu bạn muốn 'trải nghiệm' trên điện thoại thật, nhớ 'kích hoạt' tính năng "Gỡ lỗi USB" (USB debugging) trên điện thoại và 'kết nối' nó với máy tính qua cáp USB nhé. Xong, giờ thì tha hồ 'bay lượn' với Flutter thôi!