Author: doanquyet

  • [Flutter] Kiến trúc MVVM

    [Flutter] Kiến trúc MVVM

    Kiến trúc MVVM là gì?

    MVVM (Model View ViewModel) là một kiến ​​trúc thiết kế tạo điều kiện cho việc chia nhỏ các nguyên tắc thiết kế, thường được gọi là sự tách biệt phát triển của những người nghiệp dư về công nghệ, thành các phần riêng biệt của GUI. Tư tưởng cơ bản đằng sau việc triển khai các phương pháp hay nhất về kiến ​​trúc ứng dụng dành cho thiết bị di động là xây dựng “View Model” có thể đại diện cho dữ liệu thông qua một chế độ xem.

    Lý do tại sao phần lớn các nhà phát triển, nói đến thiết kế ứng dụng Android hoặc iOS, ưa thích MVVM là vì nó tách biệt Activity và Fragment  khỏi logic. Để viết một codebase linh hoạt, các nhà phát triển ứng dụng bắt buộc phải xây dựng một lớp View-Model có thể được sử dụng bởi một số ‘Views’ nhất định. Hơn nữa, kiến ​​trúc MVVM cũng giúp các nhà phát triển tự động hóa việc truyền các sửa đổi bên trong View-Model tới Views.

    Ba thành phần quan trọng của kiến ​​trúc MVVM trong Flutter

    Mẫu thiết kế MVVM được quản lý bởi ba thành phần chính là Model, View và ViewModel . Các yếu tố chính này giúp thiết lập một khối cho toàn bộ cơ sở mã của mẫu thiết kế MVVM. Mặc dù mỗi thành phần có vai trò và chức năng khác nhau, nhưng sự tương tác logic giữa các thành phần này trong quá trình phát triển ứng dụng đóng một vai trò quan trọng. Trong kiến ​​trúc MVVM, khung nhìn tương tác với mô hình khung nhìn để liên kết dữ liệu và mô hình khung nhìn giao tiếp với mô hình. Để hiểu tại sao MVVM lại quan trọng đối với dự án ứng dụng của bạn, điều cần thiết là phải chăm chỉ nhận thức từng yếu tố. Vì vậy, chúng ta hãy bắt đầu.

    1. Model

    Vai trò chính của Model trong MVVM là thực hiện logic nghiệp vụ trong mẫu thiết kế mà chỉ hoạt động dựa trên nguồn dữ liệu cần thiết trong một hoạt động. Hiểu theo cách khác, phần tử model của mẫu kiến ​​trúc MVVM được sử dụng để đại diện cho dữ liệu thời gian thực cuối cùng sẽ được sử dụng trong phát triển ứng dụng.

    Điều tốt nhất về model là hiển thị sự tương tác giữa tất cả các thành phần hoàn toàn bằng cách tìm nạp dữ liệu từ cơ sở dữ liệu phòng. Nếu chúng ta phải xác định model trong một câu duy nhất, chúng ta có thể nói – nó là một phần tử lưu trữ dữ liệu và logic liên quan của kiến ​​trúc.

    2. View

    View là viết tắt của các thành phần UI như HTML, CSS. Trong MVVM, View chịu trách nhiệm về lớp trình bày trong mẫu thiết kế và là một điểm vào ứng dụng. Khi chúng ta nói về lợi ích của kiến ​​trúc MVVM, các thuộc tính của view đã được ca ngợi. Có một tập hợp phân cấp được duy trì giữa mỗi mô hình MVVM trong khi thể hiện sự tương tác. Ví dụ: View không bao giờ tương tác trực tiếp với Model mà thông qua ViewModel. Tất cả dữ liệu được thu thập bởi Model giúp tạo dữ liệu bản trình bày cho View. View thực thi logic thiết kế UI-UX và yêu cầu mô hình gửi lại đầu ra cho người dùng.

    3. ViewModel

    Ngoài việc làm trung gian giữa các thành phần Model và View, ViewModel triển khai dữ liệu và các lệnh được kết nối với View trong kiến ​​trúc MVVM để thông báo cho phần tử sau về các thay đổi trạng thái. Có một ví dụ ViewModel Android để thực hiện các công việc khác nhau như tạo lớp con hoặc thêm phần phụ thuộc, v.v. ViewModels có thể được liên kết với một hoặc nhiều mô hình.
    Về cơ bản, vai trò của ViewModel trong kiến trúc MVVM là hỗ trợ trạng thái của View và hoạt động như một lớp logic của toàn bộ cộng đồng kiến ​​trúc MVVM. Sẽ không sai khi trích dẫn ViewModel là phần tích hợp của tất cả những gì làm cho Mô hình duy trì dữ liệu thực tế và phần View đóng gói dữ liệu cập nhật giữ bộ điều khiển như một cổng giữa chúng.

    Lợi ích của kiến ​​trúc MVVM dành cho ứng dụng Android và iOS

    Mục tiêu cơ bản của mô hình kiến ​​trúc ứng dụng dành cho thiết bị di động trong phát triển ứng dụng là củng cố các chiến lược phát triển ứng dụng dành cho thiết bị di động với nhiều kỹ thuật dựa trên các tiêu chuẩn của ngành và nhà cung cấp cụ thể để cuối cùng thúc đẩy việc xây dựng ứng dụng, Android hoặc iOS. Một câu hỏi khiến hầu hết các chủ dự án không hài lòng là – Tại sao MVVM lại quan trọng đối với ứng dụng của bạn? Nói cách khác, câu hỏi đề xuất – “điều kỳ diệu mà mẫu thiết kế này có thể làm với ứng dụng của bạn”.

    MVVM, một biến thể viết tắt của Model View ViewModel, nhằm mục đích tách ứng dụng thành ba thành phần hợp lý và sau đó xử lý các khía cạnh phát triển cụ thể của ứng dụng. Mặc dù thị trường có rất nhiều mẫu kiến ​​trúc cải thiện hiệu suất ứng dụng và khả năng của thiết bị, MVVM đặc biệt tập trung vào tầm quan trọng của kiến ​​trúc giải pháp mang lại trải nghiệm UI tốt hơn cho người dùng. Bên cạnh việc quản lý và trình bày các đối tượng dữ liệu, kiến ​​trúc MVVM có rất nhiều lợi ích để cung cấp, một số lợi ích được liệt kê dưới đây.

    1. Khả năng tái sử dụng

    Khi hiểu được toàn bộ khái niệm về việc giới thiệu kiến ​​trúc MVVM trong quá trình thiết kế ứng dụng, có thể xác định đây là mô hình giúp các nhà phát triển phân biệt rõ ràng giữa các ứng dụng được kết hợp lỏng lẻo và kết hợp chặt chẽ. Khớp nối là yếu tố phụ thuộc của thiết kế trong ứng dụng và có những thiết kế kiến ​​trúc có khớp nối chặt chẽ, điều này cuối cùng làm tăng chi phí bảo trì phát triển trang web và giảm khả năng tái sử dụng của thành phần. Kiến trúc MVVM đi kèm với khớp nối lỏng lẻo để đạt được sự phân tách trách nhiệm và nâng cao mức độ khớp nối lỏng lẻo. Mặt khác, yếu tố khả năng tái sử dụng cho phép các mã được sử dụng để xây dựng các mẫu thiết kế trong các ứng dụng khác.

    2. Thúc đẩy phát triển mã độc lập

    MVVM là một mô hình kiến ​​trúc độc lập cung cấp dữ liệu dưới dạng đầu ra thông qua View. Toàn bộ cơ sở mã của mẫu MVVM được tạo ra theo cách khắc phục các trục trặc phổ biến mà hầu hết các mẫu kiến ​​trúc trở thành nạn nhân của nó. Với ba thành phần chính của nó, kiến ​​trúc MVVM truy xuất và lưu giữ các đối tượng thông qua một dịch vụ. Dù nói đến thiết kế mô hình kiến ​​trúc MVVM Android Architecture hoặc iOS , mô hình MVVM thúc đẩy sự phát triển độc lập của ứng dụng. Vì kiến ​​trúc mã và đơn giản hóa mẫu thiết kế là mục tiêu cốt lõi của các nhà phát triển, phương pháp tiếp cận mẫu thiết kế MVVM sẽ giải quyết một số vấn đề tồn tại trong khuôn khổ thiết kế của một ứng dụng và xem xét tất cả các khía cạnh quan trọng mang lại kết quả tuyệt vời ở phần cuối của dự án.

    3. Nâng cao khả năng kiểm tra

    Mẫu thiết kế MVVM Android hoặc iOS dường như đang thu hút sự chú ý trên thị trường do các nhà phát triển có kỹ năng điều hành. Phần lớn các nhà phát triển tin rằng MVVM có thể đọc được, có thể mở rộng và có thể kiểm tra được so với các mô hình thiết kế kiến ​​trúc khác. Trong số tất cả các thành phần, ViewModel có trách nhiệm rất lớn là đại diện cho dữ liệu và khởi tạo trường hợp thử nghiệm trong mô hình kiến ​​trúc MVVM. Chính ViewModel làm cho thành phần View có thể tái sử dụng và có thể kiểm tra được, giúp cho việc khen ngợi logic nghiệp vụ kiểm thử đơn vị trở nên dễ dàng hơn. Do sự phụ thuộc của phần tử này, việc bắt đầu các trường hợp thử nghiệm trở nên ít phức tạp hơn một chút.

    4. Khả năng bảo trì

    Mặc dù một số nhà phát triển có thể thấy các chỉ số hiệu suất ứng dụng dành cho thiết bị di động và tính năng chia sẻ của kiến ​​trúc MVVM hơi khó chịu và phức tạp, nhưng khả năng bảo trì của kiến ​​trúc MVVM mang lại lợi ích cho mô hình là mạch lạc và đơn giản hóa, lưu ý các yêu cầu bổ sung. Khả năng bảo trì lồng vào nhau cung cấp khả năng mở rộng tối đa với sự phân tách ranh giới rõ ràng.
    Khả năng thay thế hoặc thêm các khối mã mới trong quá trình ứng dụng là một điều lý tưởng cần xem xét để đặt các mã trong cơ sở hạ tầng ứng dụng một cách phù hợp. Ngoài ra, tính năng ánh xạ trong kiến ​​trúc MVVM là chưa từng có. Mô hình MVVM sử dụng ánh xạ một đến nhiều giữa View và ViewModel.

  • KIẾN THỨC CƠ BẢN VỀ DART (PHẦN 4)

    KIẾN THỨC CƠ BẢN VỀ DART (PHẦN 4)

    Collections

    Bộ sưu tập rất hữu ích để nhóm dữ liệu liên quan. Dart bao gồm một số loại bộ sưu tập khác nhau, nhưng hướng dẫn này sẽ bao gồm hai loại phổ biến nhất: List và Map.

    Lists

    Lists trong Dart tương tự như arrays trong các ngôn ngữ khác. Bạn sử dụng chúng để duy trì một danh sách các giá trị có thứ tự. Danh sách dựa trên 0, vì vậy mục đầu tiên trong danh sách ở chỉ mục 0:

    Dưới đây là danh sách các món tráng miệng khác nhau:

    List desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];

    Bạn đặt các phần tử của danh sách trong dấu ngoặc vuông [ ] . Bạn sử dụng dấu phẩy để phân tách các phần tử.

    Ở đầu dòng, bạn có thể thấy rằng loại là List. Bạn sẽ nhận thấy không có loại nào được bao gồm. Dart suy luận rằng danh sách có loại List

    Đây là danh sách các số nguyên:

    final numbers = [42, -1, 299792458, 100];

    Nhập numbers vào DartPad và bạn sẽ thấy rằng Dart nhận dạng loại List của int.

    Làm việc với các phần tử trong List

    Để truy cập các phần tử của danh sách, hãy sử dụng ký hiệu chỉ số con bằng cách đặt số chỉ mục giữa dấu ngoặc vuông sau tên biến danh sách. Ví dụ:

    final firstDessert = desserts[0];
    print(firstDessert); // cookies

    Vì chỉ số danh sách dựa trên số không, desserts[0]là phần tử đầu tiên của danh sách.

    Thêm và xóa các phần tử với add và remove tương ứng:

    desserts.add('cake');
    print(desserts); 
    // [cookies, cupcakes, donuts, pie, cake]
    
    desserts.remove('donuts');
    print(desserts); 
    // [cookies, cupcakes, pie, cake]

    Chạy mã để xem kết quả.

    Trước đó, bạn đã học về forvòng lặp. for-inVòng lặp của Dart hoạt động đặc biệt tốt với các danh sách. Hãy thử nó:

    for (final dessert in desserts) {
      print('I love to eat $dessert.');
    }
    // I love to eat cookies.
    // I love to eat cupcakes.
    // I love to eat pie.
    // I love to eat cake.

    Bạn không cần sử dụng chỉ mục. Dart chỉ lặp qua mọi phần tử của dessertsvà gán nó mỗi lần cho một biến có tên dessert.

    Maps

    Khi bạn muốn một danh sách các giá trị được ghép nối, Map là một lựa chọn tốt. Dart Map tương tự như dictionaries  trong Swift và maps trong Kotlin.

    Đây là một ví dụ về map trong Dart:

    Map<String, int> calories = {
      'cake': 500,
      'donuts': 150,
      'cookies': 100,
    };

    Bạn bao quanh Maps bằng dấu ngoặc nhọn { }. Sử dụng dấu phẩy để phân tách các phần tử của bản đồ.

    Các phần tử của bản đồ được gọi là cặp khóa-giá trị , trong đó khóa ở bên trái dấu hai chấm và giá trị ở bên phải.

    Bạn tìm thấy một giá trị bằng cách sử dụng khóa để tra cứu nó, như sau:

    final donutCalories = calories['donuts'];
    print(donutCalories); // 150

    Từ khóa 'donuts'nằm trong dấu ngoặc vuông sau tên bản đồ. Trong trường hợp này, nó ánh xạ tới một giá trị 150.

    Nhập donutCalories vào DartPad và bạn sẽ thấy rằng kiểu được suy luận thì int? đúng hơn int. Đó là bởi vì, nếu một bản đồ không chứa khóa mà bạn đang tìm kiếm, nó sẽ trả về một giá trị null.

    Thêm một phần tử mới vào bản đồ bằng cách chỉ định khóa và gán cho nó một giá trị:

    calories['brownieFudgeSundae'] = 1346;
    print(calories);
    // {cake: 500, donuts: 150, cookies: 100, brownieFudgeSundae: 1346}

    Chạy mã đó và bạn sẽ thấy bản đồ được in ở định dạng ngang với món tráng miệng mới của bạn ở cuối.

    Functions

    Các hàm cho phép bạn đóng gói nhiều dòng mã liên quan vào một nội dung duy nhất. Sau đó, bạn triệu hồi hàm để tránh lặp lại những dòng mã đó trong ứng dụng Dart của mình.

    Một hàm bao gồm các phần tử sau:

    • Kiểu trả về
    • Tên chức năng
    • Danh sách tham số trong ngoặc đơn
    • Nội dung hàm được đặt trong dấu ngoặc

    Defining Functions

    Đoạn mã bạn đang chuyển thành một hàm nằm trong dấu ngoặc nhọn. Khi bạn gọi hàm, bạn truyền vào các đối số phù hợp với loại tham số của hàm.

    Tiếp theo, bạn sẽ viết một hàm mới trong DartPad sẽ kiểm tra xem một chuỗi đã cho có phải là Banana hay không :

    bool isBanana ( String fruit) {
       return fruit == 'banana' ; 
    }

    Hàm sử dụng return để trả về kiểu bool. Đối số bạn truyền vào hàm sẽ xác định bool.

    Hàm này sẽ luôn trả về cùng một kiểu giá trị cho bất kỳ đầu vào nhất định nào. Nếu một hàm không cần trả về giá trị, bạn có thể đặt kiểu trả về void.  main làm điều này, chẳng hạn.

    Làm việc với các Function

    Bạn có thể gọi hàm bằng cách truyền vào một chuỗi. Sau đó, bạn có thể chuyển kết quả của cuộc gọi đó tới print:

    void main() {
      var fruit = 'apple';
      print(isBanana(fruit)); // false
    }

    Các Function lồng vào nhau

    Thông thường, bạn xác định các hàm bên ngoài các hàm khác hoặc bên trong các lớp Dart. Tuy nhiên, bạn cũng có thể lồng các hàm Dart. Ví dụ, bạn có thể làm tổ isBanana bên trong main.

    void main() {
      bool isBanana(String fruit) {
        return fruit == 'banana';
      }
    
      var fruit = 'apple';
      print(isBanana(fruit)); // false
    }

    Bạn cũng có thể thay đổi đối số thành một hàm, sau đó gọi lại đối số đó bằng đối số mới:

    fruit = 'banana';
    print(isBanana(fruit));  // true

    Kết quả của việc gọi hàm phụ thuộc hoàn toàn vào các đối số bạn truyền vào.

    Optional Parameters

    Nếu một tham số cho một hàm là tùy chọn, bạn có thể bao quanh nó bằng dấu ngoặc vuông và đặt kiểu là vô hiệu:

    String fullName(String first, String last, [String? title]) {
      if (title == null) {
        return '$first $last';
      } else {
        return '$title $first $last';
      }
    }

    Trong chức năng này, title là tùy chọn. Nó sẽ mặc định thành null nếu bạn không chỉ định nó.

    Bây giờ, bạn có thể gọi hàm có hoặc không có tham số tùy chọn:

    print(fullName('Joe', 'Howard'));
    // Joe Howard
    
    print(fullName('Albert', 'Einstein', 'Professor'));
    // Professor Albert Einstein

    Named Parameters and Default Values

    Khi bạn có nhiều tham số, bạn có thể nhầm lẫn khi nhớ cái nào là cái nào. Dart giải quyết vấn đề này với các tham số được đặt tên , mà bạn nhận được bằng cách bao quanh danh sách tham số bằng dấu ngoặc nhọn { }.

    Các tham số này là tùy chọn theo mặc định, nhưng bạn có thể cung cấp cho chúng các giá trị mặc định hoặc yêu cầu chúng bằng cách sử dụng từ khóa required:

    bool withinTolerance({required int value, int min = 0, int max = 10}) {
      return min <= value && value <= max;
    }

    valuelà bắt buộc, trong khi minvà maxlà tùy chọn với các giá trị mặc định.

    Với các tham số được đặt tên, bạn có thể chuyển vào các đối số theo một thứ tự khác bằng cách cung cấp các tên tham số bằng dấu hai chấm:

    print(withinTolerance(value: 5)); // true

    Chạy mã của bạn để xem các chức năng mới của bạn đang hoạt động.

    Anonymous Functions

    Dart hỗ trợ first-class functions , nghĩa là nó xử lý các hàm giống như bất kỳ kiểu dữ liệu nào khác. Bạn có thể gán chúng cho các biến, chuyển chúng dưới dạng đối số và trả lại chúng từ các hàm khác.

    Để chuyển các hàm này xung quanh dưới dạng giá trị, hãy bỏ qua tên hàm và kiểu trả về. Vì không có tên nên loại hàm này được gọi là hàm ẩn danh .

    Bạn có thể gán một hàm ẩn danh cho một biến có tên onPressed như sau:

    final onPressed = () {
      print('button pressed');
    };

    onPressedcó giá trị kiểu Function. Các dấu ngoặc trống cho biết hàm không có tham số. Giống như các hàm thông thường, mã bên trong dấu ngoặc nhọn là phần thân của hàm.

    Để thực thi mã bên trong thân hàm, hãy gọi tên biến như thể nó là tên của hàm:

    onPressed(); // button pressed

    Bạn có thể đơn giản hóa các hàm có nội dung chỉ chứa một dòng duy nhất bằng cách sử dụng cú pháp mũi tên . Để thực hiện việc này, hãy xóa dấu ngoặc nhọn và thêm một mũi tên =>.

    Dưới đây là so sánh của hàm ẩn danh ở trên và phiên bản đã cấu trúc lại:

    // original anonymous function
    final onPressed = () {
      print('button pressed');
    };
    
    // refactored
    final onPressed = () => print('button pressed');

    Sử dụng Anonymous Functions

    Bạn sẽ thường thấy các hàm ẩn danh trong Flutter, giống như các hàm ở trên, được chuyển xung quanh dưới dạng lệnh gọi lại cho các sự kiện giao diện người dùng. Điều này cho phép bạn chỉ định mã chạy khi người dùng làm điều gì đó, chẳng hạn như nhấn một nút.

    Một nơi phổ biến khác mà bạn sẽ thấy các chức năng ẩn danh là với các collection. Bạn có thể cung cấp cho tập hợp một hàm ẩn danh sẽ thực hiện một số tác vụ trên mỗi phần tử của tập hợp. Ví dụ:

    // 1
    final drinks = ['water', 'juice', 'milk'];
    // 2
    final bigDrinks = drinks.map(
      // 3
      (drink) => drink.toUpperCase()
    );
    // 4
    print(bigDrinks); // (WATER, JUICE, MILK)

    Hãy xem xét từng bước:

    1. Xác định danh sách drinks có các chữ cái thường.
    2. .map nhận tất cả các giá trị danh sách và trả về một tập hợp mới với chúng.
    3. Một hàm ẩn danh được chuyển dưới dạng một tham số. Trong hàm ẩn danh đó, bạn có một drink đối số đại diện cho từng phần tử của danh sách.
    4. Phần thân của hàm ẩn danh chuyển đổi từng phần tử thành chữ hoa và trả về giá trị. Vì danh sách ban đầu là danh sách các chuỗi, nên drink cũng có kiểu String.

    Sử dụng một hàm ẩn danh và kết hợp nó với .maplà một cách thuận tiện để chuyển đổi một bộ sưu tập này thành một bộ sưu tập khác. Lưu ý : Đừng nhầm giữa .mapmethod với Maptype.

    Chạy mã để xem bộ sưu tập kết quả.

    Xin chúc mừng, bạn đã hoàn thành phần hướng dẫn. Bây giờ bạn sẽ hiểu rõ hơn về mã Dart mà bạn thấy khi học cách xây dựng ứng dụng Flutter!

  • KIẾN THỨC CƠ BẢN VỀ DART (PHẦN 3)

    KIẾN THỨC CƠ BẢN VỀ DART (PHẦN 3)

    Sang phần 3 này, chúng ta sẽ tìm hiểu về Control Flow.

    Control flow cho phép bạn ra lệnh khi nào thực thi, bỏ qua hoặc lặp lại một số dòng mã nhất định. Bạn sử dụng các điều kiện (conditionals ) và vòng lặp (loops ) để xử lý luồng điều khiển trong Dart.

    Trong phần này, bạn sẽ tìm hiểu thêm về:

    • Conditionals
    • While Loops
    • Continue and Break
    • For Loops

    Đây là những gì bạn cần biết về các phần tử luồng điều khiển trong Dart.

    Conditionals

    Hình thức cơ bản nhất của luồng điều khiển là quyết định thực thi hay bỏ qua các phần nhất định của mã của bạn, tùy thuộc vào các điều kiện xảy ra khi chương trình của bạn chạy.

    Cấu trúc ngôn ngữ để xử lý các điều kiện là câu lệnh ifelseifelse trong Dart trông gần giống với việc sử dụng nó trong các ngôn ngữ giống C khác.

    Câu lệnh If

    Giả sử bạn có một biến animal đó hiện là một con cáo. Nó trông như thế này:

    var animal = 'fox';
    

    Bạn có thể sử dụng một if câu lệnh để kiểm tra xem đó animal là mèo hay chó, sau đó chạy một số mã tương ứng.

    if (animal == 'cat' || animal == 'dog') {
      print('Animal is a house pet.');
    }

    Ở đây, bạn đã sử dụng các toán tử equality OR để tạo bool điều kiện bên trong cho if câu lệnh.

    Câu lệnh else

    Với một else mệnh đề, bạn có thể chạy mã thay thế nếu điều kiện sai:

    else {
      print('Animal is NOT a house pet.');
    }
    // Animal is NOT a house pet.

    Bạn cũng có thể kết hợp nhiều câu lệnh ifelse thành một hàm ifelse ifelse:

    if (animal == 'cat' || animal == 'dog') {
      print('Animal is a house pet.');
    } else if (animal == 'rhino') {
      print('That\'s a big animal.');
    } else {
      print('Animal is NOT a house pet.');
    }
    // Animal is NOT a house pet.

    Bạn có thể có nhiều else if nhánh giữa if và else tùy theo nhu cầu.

    While Loops

    Vòng lặp cho phép bạn lặp lại mã một số lần nhất định hoặc dựa trên các điều kiện nhất định. Bạn xử lý sự lặp lại dựa trên điều kiện bằng cách sử dụng vòng lặp while .

    Có hai dạng vòng lặp while trong Dart: while và do-while. Sự khác biệt là với while, điều kiện lặp xảy ra trước khối mã. Trong khi do-while, điều kiện xảy ra sau. Điều đó có nghĩa là do-while các vòng lặp đảm bảo khối mã chạy ít nhất một lần.

    Ví dụ While Loop

    Để thử điều này, hãy tạo một biến được i khởi tạo thành 1:

    var i = 1 ;
    

    Tiếp theo, sử dụng một while vòng lặp để in i trong khi tăng dần. Đặt điều kiện thành i nhỏ hơn 10:

    while (i < 10) {
      print(i);
      i++;
    }
    // 1
    // 2
    // 3
    // 4
    // 5
    // 6
    // 7
    // 8
    // 9

    Chạy mã và bạn sẽ thấy rằng while vòng lặp in các số từ 1 đến 9.

    Ví dụ Do-While

    Đặt lại i trong DartPad, sau đó thêm vòng lặp do-while:

    i = 1;
    do {
      print(i);
      i++;
    } while (i < 10);
    // 1
    // 2
    // 3
    // 4
    // 5
    // 6
    // 7
    // 8
    // 9
    

    Kết quả vẫn giống như trước đây. Tuy nhiên, lần này, phần thân của vòng lặp đã chạy một lần trước khi kiểm tra điều kiện thoát khỏi vòng lặp.

    Continue and Break

    Dart sử dụng continue và break từ khóa trong các vòng lặp và các nơi khác. Đây là những gì họ làm:

    • continue : Bỏ qua mã còn lại bên trong một vòng lặp và ngay lập tức chuyển sang lần lặp tiếp theo.
    • break : Dừng vòng lặp và tiếp tục thực hiện sau phần thân của vòng lặp.

    Hãy cẩn thận khi sử dụng continue trong mã của bạn. Ví dụ: nếu bạn thực hiện do-while vòng lặp từ trên và bạn muốn tiếp tục khi i bằng 5, điều đó có thể dẫn đến một vòng lặp vô hạn tùy thuộc vào vị trí bạn đặt câu lệnh continue :

    i = 1;
    do {
      print(i);
      if (i == 5) {
        continue;
      }            
      ++i;
    } while (i < 10);
    // 1
    // 2
    // 3
    // 4
    // 5
    // 5
    // 5
    // 5
    // 5
    // 5
    // 5
    // 5
    // 5
    // 5
    // ...

    Vòng lặp vô hạn xảy ra bởi vì, một khi i là 5, bạn không bao giờ tăng nó nữa, vì vậy điều kiện luôn đúng.

    Nếu bạn chạy điều này trong DartPad, vòng lặp vô hạn sẽ khiến trình duyệt bị treo. Thay vào đó, hãy sử dụng break, để vòng lặp kết thúc sau khi i đạt đến 5:

    i = 1;
    do {
      print(i);
      if (i == 5) {
        break;
      }
      ++i;
    } while (i < 10);
    // 1
    // 2
    // 3
    // 4
    // 5

    Chạy mã. Bây giờ, vòng lặp kết thúc sau năm lần lặp.

    For Loops

    Trong Dart, bạn sử dụng các vòng lặp for để lặp lại một số lần được xác định trước. Vòng lặp for bao gồm khởi tạo, một điều kiện vòng lặp và một hành động. Chúng tương tự như for các vòng lặp trong các ngôn ngữ khác.

    Dart cũng cung cấp một for-in vòng lặp, lặp lại trên một tập hợp các đối tượng. Bạn sẽ tìm hiểu thêm về những điều này sau.

    Để xem cách for hoạt động của một vòng lặp, hãy tạo một biến cho sum:

    var sum = 0 ;
    

    Tiếp theo, sử dụng một vòng lặp for để khởi tạo bộ đếm vòng lặp từ i đến 1. Sau đó, bạn sẽ kiểm tra xem i nhỏ hơn hoặc bằng 10 và tăng dần i sau mỗi vòng lặp.

    Bên trong vòng lặp, sử dụng phép gán ghép để thêm i vào tổng đang chạy:

    for (var i = 1; i <= 10; i++) {
      sum += i;  
    }
    print("The sum is $sum"); // The sum is 55
    
    

    Chạy mã của bạn trong DartPad để xem tổng.

    Kết thúc phần 3!

  • KIẾN THỨC CƠ BẢN VỀ DART(PHẦN 2)

    KIẾN THỨC CƠ BẢN VỀ DART(PHẦN 2)

    Tiếp tục phần 1, sang phần 2 này ta sẽ tìm hiểu về các toán tử có trong Dart.

    Operators

    Dart có tất cả các toán tử thông thường mà bạn quen thuộc từ các ngôn ngữ khác như C, Swift và Kotlin.

    Một số ví dụ về các toán tử của Dart bao gồm:

    • Toán tử số học
    • Toán tử so sánh
    • Toán tử logic

    Lưu ý : Dart cũng cho phép nạp chồng toán tử , như trong C ++ và Kotlin, nhưng điều đó nằm ngoài phạm vi của hướng dẫn này. Để tìm hiểu thêm về chủ đề này, hãy truy cập trang operator overloading của Wikipedia .

    Tiếp theo, bạn sẽ xem xét từng toán tử này.

    Toán tử số học

    Các toán tử số học hoạt động giống như bạn mong đợi. Hãy thử chúng bằng cách thêm một loạt các thao tác vào DartPad của bạn:

    in ( 40 + 2 ); // 42 
    
    print ( 44 - 2 ); // 42 
    
    print ( 21 * 2 ); // 
    
    42 print ( 84/2 ) ; // 42.0
    
    

    Đối với phép chia, ngay cả với số nguyên, Dart suy ra biến kết quả là a double. Đó là lý do tại sao bạn nhận được 42.0 thay vì 42 cho print câu lệnh cuối cùng.

    So sánh bằng

    Dart sử dụng toán tử double-equals ( ==) và not-equals ( !=):

    in ( 42 == 43 ); // 
    
    in sai ( 42 ! = 43 ); // true
    
    

    Toán tử so sánh

    Dart sử dụng các toán tử so sánh điển hình:

    • Nhỏ hơn (<)
    • Lớn hơn (>)
    • Lơn hơn hoặc bằng(>=)
    • Nhỏ hơn hoặc bằng(<=)

    Dưới đây là một số ví dụ:

    print ( 42 < 43 ); // true 
    print (42> = 43); // false
    
    

    Ngoài ra, nó cũng sử dụng các toán tử số học / phép gán ghép thông thường:

    var value = 42.0;
    
    value += 1; print(value); // 43.0
    
    value -= 1; print(value); // 42.0
    
    value *= 2; print(value); // 84.0
    
    value /= 2; print(value); // 42.0
    
    
    

    Toán tử số học / phép gán ghép thực hiện hai nhiệm vụ. +=thêm giá trị ở bên phải vào biến ở bên trái và sau đó gán kết quả cho biến.

    Một dạng rút gọn của += 1 là ++:

    value++;
    
    print(value); // 43.0
    
    

    Và Dart có toán tử modulo thông thường ( %) để trả về phần còn lại sau khi một số đã được chia cho một số khác:

    print( 392 % 50 ); // 42
    
    

    392 ÷ 50 = 7,84 nhưng 42 đó trong ngăn kết quả đến từ đâu? Nó dễ dàng hơn để xem với sự phân chia dài.

    Toán tử logic

    Dart sử dụng các toán tử logic giống như các ngôn ngữ khác, bao gồm và có kí hiệu là &&, OR  có kí hiệu là ||

    print (( 41 < 42 ) && ( 42 < 43 )); // true 
    
    print (( 41 < 42 ) || ( 42 > 43 )); // true
    
    

    Toán tử phủ định là dấu chấm than , biến false thành true và true thành false.

    print (! ( 41 < 42 )); // false
    
    

    Xem tài liệu Dart để biết danh sách đầy đủ các toán tử được hỗ trợ .

    Strings

    Loại chuỗi Dart là String. Các chuỗi được thể hiện trong Dart bằng cách sử dụng văn bản được bao quanh bởi dấu ngoặc kép đơn hoặc kép .

    Bạn có thể sử dụng var và nhập suy luận hoặc String để tạo biến chuỗi, giống như các kiểu khác mà bạn đã thấy:

    var firstName = 'Albert' ; String lastName = "Einstein" ;
    
    
    
    

    Tương tự như các ngôn ngữ như Kotlin và Swift, bạn có thể nhúng giá trị của một biểu thức bên trong một chuỗi bằng cách sử dụng ký hiệu ký hiệu đô la: $ { biểu thức } .

    Nếu biểu thức là một số nhận dạng, bạn có thể bỏ qua dấu {} . Thêm những điều sau:

    var physicist = "$firstName $lastName likes the number ${84 / 2}";
    
    print(physicist); // Albert Einstein
    
    

    $firstName và $lastName được thay thế bằng các giá trị biến. Trả về kết quả được tính toán.

    Escaping Strings

    Các trình tự thoát được sử dụng trong Dart tương tự như các trình tự được sử dụng trong các ngôn ngữ giống C khác. Ví dụ, bạn sử dụng \n cho một dòng mới.

    Nếu có các ký tự đặc biệt trong chuỗi, hãy sử dụng \ để thoát khỏi chúng:

    var quote = 'If you can\'t explain it simply\nyou don\'t understand it well enough.';
    
    print(quote);
    // If you can't explain it simply
    
    // you don't understand it well enough.
    
    

    Ví dụ này sử dụng các dấu ngoặc kép, vì vậy nó cần một chuỗi thoát \', để nhúng các dấu nháy đơn cho can’t và don’t vào chuỗi. Bạn sẽ không cần phải thoát khỏi dấu nháy đơn nếu thay vào đó bạn sử dụng dấu ngoặc kép.

    Nếu bạn cần hiển thị trình tự thoát trong chuỗi, bạn có thể sử dụng raw strings , có tiền tố là r.

    var rawString = r"If you can't explain it simply\nyou don't understand it well enough.";
    
    print(rawString); 
    
    // If you can't explain it simply\nyou don't understand it well enough.
    
    

    Ở đây, Dart được coi `\n`là văn bản bình thường vì chuỗi bắt đầu bằng r.

    Nhấp vào RUN trong DartPad để xem tất cả các chuỗi của bạn trong bảng điều khiển.

    Immutability

    Dart sử dụng các từ khóa constvà finalcác giá trị không thay đổi.

    Sử dụng constcho các giá trị đã biết tại thời điểm biên dịch. Sử dụng finalcho các giá trị không cần biết tại thời điểm biên dịch nhưng không thể gán lại sau khi được khởi tạo.Lưu ý : finalhoạt động giống như valtrong Kotlin hoặc lettrong Swift.

    Bạn có thể sử dụng constvà finalthay cho varvà để phép suy luận kiểu xác định kiểu:

    const speedOfLight = 299792458 ;
    
    in (speedOfLight); // 299792458
    
    

    Ở đây, Dart cho rằng speedOfLight là một biến kiểu int, như bạn có thể thấy trong bảng thông tin của DartPad.

    final cho biết rằng một biến là không thể thay đổi , nghĩa là bạn không thể gán lại final các giá trị. Bạn có thể nêu rõ loại với một trong hai final hoặc const:

    final planet = 'Jupiter';
    
    // planet = 'Mars';
    
    // error: planet chỉ có thể khởi tạo 1 lần
    
    final String moon = 'Europa';
    
    print('$planet has a moon, $moon');
    
    // Jupiter has a moon, Europa
    

    Nullability

    Trước đây, nếu bạn không khởi tạo một biến, Dart đã cấp cho nó giá trị null, có nghĩa là không có gì được lưu trữ trong biến. Tuy nhiên, kể từ Dart 2.12, Dart kết hợp với các ngôn ngữ khác, như Swift và Kotlin, để không thể null theo mặc định.

    Ngoài ra, Dart đảm bảo rằng kiểu không thể null sẽ không bao giờ chứa giá trị null. Điều này được gọi là sound null safety. .

    Thông thường, nếu bạn muốn khai báo một biến, bạn phải khởi tạo nó:

    String middleName = 'May';
    
    print(middleName); // May
    
    

    Tuy nhiên, không phải tất cả mọi người đều có tên đệm, vì vậy việc tạo middleName một giá trị vô hiệu là rất hợp lý. Để nói với Dart rằng bạn muốn cho phép giá trị null, hãy thêm ? vào sau kiểu giữ liểu.

    String? middleName = null;
    
    print(middleName); // null
    
    

    Giá trị mặc định cho kiểu nullable là null, vì vậy bạn có thể đơn giản hóa biểu thức thành như sau:

    String? middleName;
    
    print(middleName); // null
    
    

    Run nó và null in ra bảng điều khiển.

    Toán tử Null-Aware

    Dart có một số toán tử nhận biết null mà bạn có thể sử dụng khi làm việc với các giá trị null.

    Toán tử dấu hỏi kép ?? giống như toán tử Elvis trong Kotlin: Nó trả về toán hạng bên trái nếu đối tượng không phải là null. Nếu không, nó trả về giá trị bên phải:

    var name = middleName ?? 'none';
    
    print(name); // none
    
    

    Vì middleName là null, Dart chỉ định giá trị bên phải của 'none'.

    Toán tử ?. bảo vệ bạn khỏi việc truy cập các thuộc tính của các đối tượng null. Nó trả về null nếu bản thân đối tượng là null. Nếu không, nó trả về giá trị của thuộc tính ở phía bên phải:

    print(middleName?.length); // null
    

    Ngày trước khi chưa có null safety, nếu bạn quên dấu chấm hỏi và viết middleName.length, ứng dụng của bạn sẽ gặp sự cố trong thời gian chạy nếu middleNametrống. Đó không còn là vấn đề nữa, vì Dart giờ đây sẽ cho bạn biết ngay lập tức khi nào bạn cần xử lý các giá trị null.

    Kết thúc phần 2.

  • Kiến thức cơ bản về Dart(Phần 1)

    Giới thiệu

    Giới thiệu về kiến ​​thức cơ bản của ngôn ngữ lập trình Dart, được sử dụng để phát triển với Flutter SDK dành cho thiết bị di động, web và hơn thế nữa.

    Flutter là một bộ công cụ giao diện người dùng thú vị của Google cho phép bạn viết ứng dụng cho các nền tảng khác nhau bao gồm iOS, Android, web và hơn thế nữa, tất cả đều sử dụng một cơ sở mã. Flutter sử dụng ngôn ngữ Dart.

    Nếu bạn chưa quen với Dart, hướng dẫn này sẽ giới thiệu cho bạn các khái niệm cơ bản của nó và cho bạn thấy nó tương tự như thế nào với các ngôn ngữ lập trình khác mà bạn có thể đã biết.

    Trong suốt quá trình hướng dẫn này, bạn sẽ được giới thiệu về những điều cơ bản của Dart chẳng hạn như:

    • Variables, data types, and operators
    • Conditionals and loops
    • Collections
    • Functions

    Khi bạn hoàn thành, bạn sẽ sẵn sàng đi sâu vào phát triển Flutter bằng cách sử dụng Dart.

    Bắt Đầu

    Để bắt đầu nhanh chóng, cách tốt nhất của bạn là sử dụng công cụ mã nguồn mở DartPad , cho phép bạn viết và kiểm tra mã Dart thông qua trình duyệt web:

    DartPad được thiết lập giống như một IDE thông thường. Nó bao gồm các thành phần sau:

    • Khung trình soạn thảo : Nằm ở bên trái. Mã của bạn sẽ xuất hiện ở đây.
    • Nút RUN : Chạy mã trong trình chỉnh sửa.
    • Bảng điều khiển : Nằm ở phía trên bên phải, bảng này hiển thị đầu ra.
    • Bảng tài liệu : Nằm ở dưới cùng bên phải, bảng này hiển thị thông tin về mã.
    • Samples: Trình đơn thả xuống này hiển thị một số mã mẫu.
    • Nút Null Safety: Sử dụng nút này để chọn tham gia vào tính năng an toàn không có âm thanh mới của Dart.
    • Thông tin phiên bản : Ở phía dưới cùng bên phải, DartPad hiển thị phiên bản Flutter và Dart mà nó hiện đang sử dụng.

    Nếu muốn, bạn có thể cài đặt Dart SDK cục bộ trên máy của mình. Một cách để làm như vậy là cài đặt Flutter SDK . Cài đặt Flutter cũng sẽ cài đặt Dart SDK.

    Để cài đặt trực tiếp SDK Dart, hãy truy cập https://dart.dev/get-dart .

    Tại sao nên chọn Dart

    Dart có nhiều điểm tương đồng với các ngôn ngữ khác như Java, C #, Swift và Kotlin. Một số tính năng của nó bao gồm:

    • Statically typed
    • Type inference
    • String expressions
    • Multi-paradigm including object-oriented and functional programming
    • Null safe

    Dart được tối ưu hóa để phát triển các ứng dụng nhanh trên nhiều nền tảng.

    Variables, Comments and Data Types

    Điều đầu tiên bạn sẽ thêm vào main là một câu lệnh gán biến. Các biến giữ dữ liệu mà chương trình của bạn sẽ hoạt động.

    Bạn có thể coi một biến như một hộp trong bộ nhớ máy tính của bạn chứa một giá trị. Mỗi hộp có một tên, đó là tên của biến. Để biểu thị một biến bằng Dart, hãy sử dụng var từ khóa.

    Thêm một biến mới vào main:

    var myAge = 35 ;  
    
    

    Mỗi câu lệnh Dart kết thúc bằng dấu chấm phẩy, giống như các câu lệnh trong C và Java. Trong đoạn mã trên, bạn đã tạo một biến myAge và đặt nó bằng 35 .

    Bạn có thể sử dụng print Dart tích hợp sẵn để in biến vào bảng điều khiển. Thêm lệnh gọi đó sau biến:

    in (myAge); // 35
    
    

    Nhấp vào RUN trong DartPad để chạy mã. Bạn sẽ thấy giá trị của biến 35 được in trong bảng điều khiển.

    Comments

    Comments trong Dart giống như trong C và các ngôn ngữ khác. Văn bản sau // là một nhận xét một dòng, trong khi văn bản bên trong /* ... */ là một khối nhận xét nhiều dòng.

    Đây là một ví dụ:

    // Đây là một nhận xét một dòng. 
    
    in (myAge); // Đây cũng là một nhận xét một dòng. 
    
    / * 
     Đây là một khối bình luận nhiều dòng. Điều này rất hữu ích cho những 
     bình luận dài kéo dài vài dòng. 
     * /
    
    

    Data Types

    Dart là statically typed , nghĩa là mỗi biến trong Dart có một kiểu mà bạn phải biết khi biên dịch mã. Loại biến không thể thay đổi khi bạn chạy chương trình. C, Java, Swift và Kotlin cũng có statically typed .

    Điều này trái ngược với các ngôn ngữ như Python và JavaScript, được gõ động . Điều đó có nghĩa là các biến có thể chứa các loại dữ liệu khác nhau khi bạn chạy chương trình. Bạn không cần biết kiểu khi bạn biên dịch mã.

    Nhấp vào myAge cửa sổ trình chỉnh sửa và tìm trong bảng Tài liệu . Bạn sẽ thấy Dart được suy ra là myAge kiểu int vì nó được khởi tạo với giá trị số nguyên 35 .

    Nếu bạn không chỉ định rõ ràng một kiểu dữ liệu, Dart sẽ sử dụng suy luận kiểu để cố gắng xác định nó, giống như Swift và Kotlin.

    Dart cũng sử dụng kiểu suy luận cho các kiểu khác int. Nhập một biến pi bằng 3,14:

    var pi = 3,14 ; in (pi); // 3,14
    
    
    
    

    Dart pi được cho là double bởi vì bạn đã sử dụng một giá trị dấu phẩy động để khởi tạo nó. Bạn có thể xác minh điều đó trong bảng thông tin Dart bằng cách nhấp vào pi.

    Các kiểu dữ liệu cơ bản

    Dart sử dụng các loại cơ bản sau:

    • int : Số nguyên
    • double : Số phức
    • bool : Booleans
    • String: Chuỗi ký tự

    Dưới đây là một ví dụ về từng loại trong Dart:

    int và double cả hai đều bắt nguồn từ một kiểu được đặt tên numnum sử dụng dynamic từ khóa để bắt chước cách nhập động trong Dart.

    Thực hiện việc này bằng cách thay thế varbằng loại bạn muốn sử dụng:

    int yourAge = 27 ;
    
    in (yourAge); // 27
    
    

    Từ khóa Dynamic

    Nếu bạn sử dụng từ khóa dynamic từ khóa thay vì var, bạn sẽ nhận được một biến được nhập động một cách hiệu quả:

    dynamic numberOfKittens;
    
    

    Tại đây, bạn có thể đặt numberOfKittensthành một String dấu ngoặc kép. Bạn sẽ tìm hiểu thêm về String loại này sau trong hướng dẫn.

    numberOfKittens = 'There are no kittens!';
    
    print(numberOfKittens); // There are no kittens!
    
    

    numberOfKittenscó một kiểu, vì Dart có kiểu gõ tĩnh. Nhưng kiểu dynamicđó, có nghĩa là bạn có thể gán các giá trị khác với các kiểu khác cho nó. Vì vậy, bạn có thể chỉ định một intgiá trị bên dưới câu lệnh in của mình.

    numberOfKittens = 0 ; print (numberOfKittens); // 0
    
    
    
    

    Hoặc, nếu bạn có một con mèo con trong hộp của Schrödinger , bạn có thể gán một double giá trị:

    numberOfKittens = 0,5 ; print (numberOfKittens); // 0,5
    
    
    
    
    

    Nhấp vào RUN để xem ba giá trị khác nhau numberOfKittens được in trong bảng điều khiển. Trong mỗi trường hợp, kiểu của numberOfKittens phần còn lại dynamic, mặc dù bản thân biến đó giữ các giá trị của các kiểu khác nhau.

    Booleans

    Kiểu bool chứa các giá trị của một trong hai true hoặc false.

    bool areThereKittens = false ; print (areThereKittens); // false
    
    
    
    

    Nhưng, nếu bạn nhìn vào bên trong hộp của Schrödinger, bạn có thể chuyển sang có một con mèo con thực sự có:

    numberOfKittens = 1 ; 
    
    areThereKittens = true ; print (areThereKittens); // true
    
    
    
    

    Chạy lại mã để xem các giá trị Boolean của bạn trong bảng điều khiển.