Skip to content

Instantly share code, notes, and snippets.

@nguyenducduy
Forked from coder7eeN/dart_flutter_why_not.md
Created February 17, 2020 16:08
Show Gist options
  • Select an option

  • Save nguyenducduy/fbc34cdac99455bca708cb1eebe5787d to your computer and use it in GitHub Desktop.

Select an option

Save nguyenducduy/fbc34cdac99455bca708cb1eebe5787d to your computer and use it in GitHub Desktop.

Revisions

  1. @coder7eeN coder7eeN revised this gist Mar 27, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dart_flutter_why_not.md
    Original file line number Diff line number Diff line change
    @@ -124,7 +124,7 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó
    numbers.add(2);
    numbers.add(7);

    var age = {1, 'a', true};
    var age = {1, 'a', true};
    ```

    - Queue - 1 collection có thể thao tác cả 2 đầu vào của mình. 1 đầu để đưa dữ liệu và 1 đầu xóa dữ liệu. Hữu dụng khi xây dựng collection theo kiểu first in, fist out.
  2. @coder7eeN coder7eeN revised this gist Mar 27, 2019. 1 changed file with 17 additions and 16 deletions.
    33 changes: 17 additions & 16 deletions dart_flutter_why_not.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    ## Part 1. Mọi thứ đều bắt đầu từ những thứ cơ bản nhất

    Khi nhắc đến việc làm sao để tạo ra 1 ứng dụng mobile thì thứ mọi người sẽ lặp tức nghĩ ngay đến là **native app (Android và iOS)**, nhưng bên cạnh đó vẫn còn rất nhiều công nghệ có thể giúp bạn tạo ra 1 ứng dụng mobile như **Cordova, Webview (WeChat), Ionic, Xamarin và React Native**. Tất cả các framework, platform đó đều hổ trợ người dùng tạo ra được 1 ứng dụng mobile theo ý muốn của mình. Và để không bỏ lỡ cuộc vui thì Google cũng đã mang đến cho người dùng đứa con mới nhất của mình - **Flutter** - nó kế thừa cũng như nổi bật hơn các công nghệ hybrid app kia. Vậy thì làm sao để có thể sử dụng, có thể tạo ra được những sản phẩm theo ý muốn của mình? Bài viết với những kiến thức của bản thâm mình sẽ đem đến cho bạn có được 1 số kiến thức cơ bản nhất để có thể tự mình "chiến" và "khám phá" Flutter.
    Khi nhắc đến việc làm sao để tạo ra 1 ứng dụng mobile thì thứ mọi người sẽ lặp tức nghĩ ngay đến là **native app (Android và iOS)**, nhưng bên cạnh đó vẫn còn rất nhiều công nghệ có thể giúp bạn tạo ra 1 ứng dụng mobile như **Cordova, Webview (WeChat), Ionic, Xamarin và React Native**. Tất cả các framework, platform đó đều hổ trợ người dùng tạo ra được 1 ứng dụng mobile theo ý muốn của mình. Và để không bỏ lỡ cuộc vui thì Google cũng đã mang đến cho người dùng đứa con mới nhất của mình - **Flutter** - nó kế thừa cũng như nổi bật hơn các công nghệ hybrid app kia. Vậy thì làm sao để có thể sử dụng, có thể tạo ra được những sản phẩm theo ý muốn của mình? Bài viết với những kiến thức của bản thân mình sẽ đem đến cho bạn có được 1 số kiến thức cơ bản nhất để có thể tự mình "chiến" và "khám phá" Flutter.

    ## Dart Language

    @@ -23,7 +23,7 @@ Dart là ngôn ngữ đơn giản, dễ tiếp cận và cũng khá dễ hiểu.
    Đây là phần chú ý đầu tiên khi bạn đọc trên trang chủ của Dart. Vì thế hãy đọc kỹ hướng dẫn trước khi liều.

    1. Bất kì thứ gì có thể đặt vào 1 biến đều là `object` và mọi object đều là thể hiện của 1 `class`. Số, hàm, `null` đều là object. Mọi object thì đều xuất phát từ Object class.
    2. Mặc dầu Dart là strong typed nhưng Dart vẫn hỗ trợ loose typed. Có nghĩa là nếu bạn chưa chắc chắn về kiểu dữ liệu cho biến thì vẫn có thể khai báo với kiểu dynamic.
    2. Tuy Dart là strong typed nhưng Dart vẫn hỗ trợ loose typed. Có nghĩa là nếu bạn chưa chắc chắn về kiểu dữ liệu cho biến thì vẫn có thể khai báo với kiểu dynamic.
    3. Dart hỗ trợ generic type, ví dụ `List<int>``List<dynamic>`.
    4. Dart hỗ trợ top-level function (như hàm main()). Bạn có thể tạo ra 1 hàm bên trong hàm khác (nested hoặc local function).
    5. Dart cũng hỗ trợ top-level variables.
    @@ -44,7 +44,7 @@ Dart là ngôn ngữ đơn giản, dễ tiếp cận và cũng khá dễ hiểu.

    ```dart
    num number = 17;
    num number1 = 69.96;
    num number1 = 17.03;
    ```

    - int - để thao tác với số nguyên.
    @@ -104,7 +104,7 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó
    List mixin = [69, 'kimochi', true]; // List<dynamic>
    ```

    - Map - 1 object thông dụng khác, chứa cặp key-value. Dart hỗ trợ map literals và kiểu dự liệu Map.
    - Map - 1 object thông dụng khác, chứa cặp key-value. Dart hỗ trợ map literals và kiểu dữ liệu Map.

    ```dart
    Map roles = {'H': 'dev', 'U': 'tester', 'Y': 'designer'};
    @@ -124,7 +124,7 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó
    numbers.add(2);
    numbers.add(7);

    var age = {1, 'a', true};
    var age = {1, 'a', true};
    ```

    - Queue - 1 collection có thể thao tác cả 2 đầu vào của mình. 1 đầu để đưa dữ liệu và 1 đầu xóa dữ liệu. Hữu dụng khi xây dựng collection theo kiểu first in, fist out.
    @@ -242,7 +242,7 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó
    - Optional unnamed parameter function - bạn có thể tạo ra 1 tham số tùy chọn khi khởi tạo hàm, lúc gọi làm bạn có thể truyền hoặc không truyền đối số vào cho nó và phải gọi đúng thứ tự như lúc khởi tạo.

    ```dart
    void void declareYourCharacter(bool isHumorous, [bool isQuiet, bool isKind = false]) {
    void declareYourCharacter(bool isHumorous, [bool isQuiet, bool isKind = false]) {
    // do something
    }

    @@ -265,7 +265,7 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó

    #### 7. Null aware operation

    - `?:` (Tenary Operator) - đa số ngôn ngữ đều hỗ trợ, thay thế cho if else.
    - `?:` (Ternary Operator) - đa số ngôn ngữ đều hỗ trợ, thay thế cho if else.

    ```dart
    height < 175 ? 'Short' : 'Tall';
    @@ -297,7 +297,6 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó

    #### 8. Classes

    <!--Class và constructor vẫn còn nhiều cái để nói nhưng chỉ nêu ra cái cơ bản nhất-->
    Dart là ngôn ngữ hướng đối tượng với các class và thừa kế dựa trên mixin (mixin-based inheritance). Mỗi object đều là thể hiện của 1 class và tất cả class đều xuất phát từ Object class. *Thừa kế dựa trên mixin* có nghĩa là mỗi class đều có 1 superclass (trừ Object class), phần bên trong của mỗi class đều có thể được tái sử dụng trong nhiều class được phân cấp.

    - Create a class
    @@ -344,7 +343,8 @@ Dart là ngôn ngữ hướng đối tượng với các class và thừa kế d
    class Bike extends Vehicle {
    @override
    void countNumberOfWheels(int wheel) {
    super.countNumberOfWheels(wheels); }
    super.countNumberOfWheels(wheels);
    }
    }
    ```

    @@ -398,8 +398,8 @@ Dart là ngôn ngữ hướng đối tượng với các class và thừa kế d
    }
    ```

    - Mixin và mixin - đây là khái niệm khiến nhiều người khi tiếp xúc với Dart khá lúng túng. Vậy mixin là gì? Mixin là gì? và liệu một chiếc xe máy có thể chạy trên nước?
    - Mixin - cách để trừu tượng hóa và tái sử dụng code trong các class khác nhau.
    - Mixins và mixin - đây là khái niệm khiến nhiều người khi tiếp xúc với Dart khá lúng túng. Vậy mixin là gì? Mixins là gì? và liệu một chiếc xe máy có thể chạy trên nước?
    - Mixins - cách để trừu tượng hóa và tái sử dụng code trong các class khác nhau.

    ```dart
    class Motobike {
    @@ -494,8 +494,8 @@ Sau gần 1 năm với các phiên bản preview thì phiên bản stable 1.0 c
    onPressed: _onPressed,
    child: Icon(Icons.add),
    ),
    );
    }
    );
    }
    ```

    - Như ví dụ trên, Scaffold là parent Widget chứa 3 children widgets là Center, Column và Text. Ta sẽ có được sơ đồ widget tree như sau:
    @@ -537,7 +537,7 @@ Sau gần 1 năm với các phiên bản preview thì phiên bản stable 1.0 c
    #### 4. StatefulWidget

    - Trái ngược với StatelessWidget thì StatefulWidget sẽ xử lí các dữ liệu bên trong nó, lắng nghe những thay đổi, dữ liệu này sẽ liên tục thay đổi (mutable) trong suốt lifecycle của widget.
    - Tập hợp những dữ liệu thay đổi được giữ bởi StatefulWidget, thay đổi trong suốt lifecycle của widget này và dữ liệu có không thể đọc 1 cách đồng bộ khi widget đã được build thì ta gọi đó là State. State định nghĩa ra phần hành vi mà StatefulWidget thể hiện. 1 State chứa các thông tin tương tác với widget thông qua các khía cạnh về hành vi (behavior) và layout. Mỗi khi thay đổi State thì widget đó sẽ thay đổi theo.
    - Tập hợp những dữ liệu thay đổi được giữ bởi StatefulWidget, thay đổi trong suốt lifecycle của widget và dữ liệu có thể đọc 1 cách đồng bộ khi widget đã được build thì ta gọi đó là State. State định nghĩa ra phần hành vi mà StatefulWidget thể hiện. 1 State chứa các thông tin tương tác với widget thông qua các khía cạnh về hành vi (behavior) và layout. Mỗi khi thay đổi State thì widget đó sẽ thay đổi theo.
    - Giữa State và BuildContext có 1 mối quan hệ khá khăn khít. Mỗi khi 1 State được tạo ra thì nó sẽ gắn với 1 BuildContext và lúc này State là *mounted*.

    #### 5. StatefulWidget lifecycle
    @@ -614,12 +614,12 @@ Sau gần 1 năm với các phiên bản preview thì phiên bản stable 1.0 c
    - dispose() - gọi khi State đã được xóa hoàn toàn.
    - mounted == false - khi này State không thể nào remount lại được nữa.

    #### 5. StatefulWidget or StatelessWidget?
    #### 6. StatefulWidget or StatelessWidget?

    - Nếu widget của bạn sẽ phải thường xuyên thay đổi State và khi thay đổi thì widget của bạn sẽ được rebuild thì bạn nên sử dụng StatefulWidget. Còn nếu widget của bạn State từ lúc khởi tạo đến lúc kết thúc vẫn không có gì thay đổi thì bạn nên sử dụng StatelessWidget.
    - Ví dụ widget của bạn là 1 TextField, bạn cần phải biết được State lúc nào nó được nhập, lúc nào nó đã được nhập xong, State của nó thay đổi liên tục. Còn nếu widget của bạn chỉ là 1 Text hiển thị thông báo và nó không bao giờ thay đổi thì bạn nên sử dụng StatelessWidget.

    #### 5. Some common widgets
    #### 7. Some common widgets

    Ở bài viết này mình chỉ liệt kê và giới thiệu tên vào widget thường hay dùng nên sẽ không đi sâu vào các thuộc tính của nó. Sẽ có 1 bài viết hoặc nhiều bài viết khác mình giới thiệu về các widget trong Flutter. Thế giới widget trong Flutter rất đa dạng nên 1 bài viết chẳng thể nào nói hết được sự thú vị của nó. Đây là thứ hấp dẫn mình đến với Flutter, cảm giác khi làm việc với các widget y như khi bạn chơi với một bộ lego, bạn tha hồ lắp ghép và sáng tạo với nó.

    @@ -735,3 +735,4 @@ Sau gần 1 năm với các phiên bản preview thì phiên bản stable 1.0 c
    ## Tham khảo

    - [Widget — State — BuildContext — InheritedWidget](https://medium.com/flutter-community/widget-state-buildcontext-inheritedwidget-898d671b7956)
    - [Dart: What are mixins?](https://medium.com/flutter-community/dart-what-are-mixins-3a72344011f3)
  3. @coder7eeN coder7eeN revised this gist Mar 25, 2019. No changes.
  4. @coder7eeN coder7eeN revised this gist Mar 25, 2019. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion dart_flutter_why_not.md
    Original file line number Diff line number Diff line change
    @@ -184,7 +184,7 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó
    } while(condition);
    ```

    - For loop
    - for loop

    ```dart
    List alphabets = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'];
    @@ -257,6 +257,10 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó
    alphabets.forEach((String item) {
    print('${alphabets.indexOf(i)item);
    });

    var sayHello = () => print('Hello guys');

    sayHello();
    ```

    #### 7. Null aware operation
  5. @coder7eeN coder7eeN revised this gist Mar 25, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dart_flutter_why_not.md
    Original file line number Diff line number Diff line change
    @@ -44,7 +44,7 @@ Dart là ngôn ngữ đơn giản, dễ tiếp cận và cũng khá dễ hiểu.

    ```dart
    num number = 17;
    num number1 = 17.03;
    num number1 = 69.96;
    ```

    - int - để thao tác với số nguyên.
  6. @coder7eeN coder7eeN revised this gist Mar 25, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dart_flutter_why_not.md
    Original file line number Diff line number Diff line change
    @@ -124,7 +124,7 @@ Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó
    numbers.add(2);
    numbers.add(7);

    var age = {1, 'a', true};
    var age = {1, 'a', true};
    ```

    - Queue - 1 collection có thể thao tác cả 2 đầu vào của mình. 1 đầu để đưa dữ liệu và 1 đầu xóa dữ liệu. Hữu dụng khi xây dựng collection theo kiểu first in, fist out.
  7. @coder7eeN coder7eeN created this gist Mar 25, 2019.
    733 changes: 733 additions & 0 deletions dart_flutter_why_not.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,733 @@
    ## Part 1. Mọi thứ đều bắt đầu từ những thứ cơ bản nhất

    Khi nhắc đến việc làm sao để tạo ra 1 ứng dụng mobile thì thứ mọi người sẽ lặp tức nghĩ ngay đến là **native app (Android và iOS)**, nhưng bên cạnh đó vẫn còn rất nhiều công nghệ có thể giúp bạn tạo ra 1 ứng dụng mobile như **Cordova, Webview (WeChat), Ionic, Xamarin và React Native**. Tất cả các framework, platform đó đều hổ trợ người dùng tạo ra được 1 ứng dụng mobile theo ý muốn của mình. Và để không bỏ lỡ cuộc vui thì Google cũng đã mang đến cho người dùng đứa con mới nhất của mình - **Flutter** - nó kế thừa cũng như nổi bật hơn các công nghệ hybrid app kia. Vậy thì làm sao để có thể sử dụng, có thể tạo ra được những sản phẩm theo ý muốn của mình? Bài viết với những kiến thức của bản thâm mình sẽ đem đến cho bạn có được 1 số kiến thức cơ bản nhất để có thể tự mình "chiến" và "khám phá" Flutter.

    ## Dart Language

    Bao giờ cũng vậy, bạn muốn "chiến" hoặc "chỉ học để biết" 1 library, 1 framework, 1 platform thì **ngôn ngữ (language)** sử dụng để build lên nó là cái bạn cần phải quan tâm và tìm hiểu, cũng giống như 1 chiếc xe nếu không có xăng thì cũng chỉ để ngắm.

    Flutter sử dụng ngôn ngữ Dart để lập trình, ngôn ngữ Dart ra đời từ năm 2011, nhắm đến tạo ra ứng dụng chạy đa nền tảng - web, mobile, desktop và IoT nhưng lúc ấy cộng đồng còn khá nhỏ và cũng không phải là sự lựa chọn cho các công ty (vì đây là ngôn ngữ phát triển bởi chính Google và các công ty cũng rất e dè điều này). Khi Google phát triển 1 os mới (operation system) - **Fuchsia** - thì Flutter được chọn làm nền tảng cho các ứng dụng đến lúc này thì Dart mới có được nhiều người biết đến và cộng đồng được mở rộng hơn.

    Phiên bản hiện tại lúc viết bài này là 2.2. Những bản 1.x và 2.0 vẫn còn khá nhiều lỗi khiến coder lúc viết khá lúng túng, trình biên soạn vẫn còn chưa support tốt, tuy nhiên với việc ra bản 2.1 thì mọi thứ đã tốt hơn rất nhiều.

    Dart là ngôn ngữ đơn giản, dễ tiếp cận và cũng khá dễ hiểu. Dart là ngôn ngữ tĩnh, theo hướng đối tượng (object oriented programming), functional programming và lexical scoped. Nó như 1 sự kết hợp giữa Java và JavaScript nên khi học nó nếu ai đã có nền tảng 1 trong 2 ngôn ngữ kia thì lúc tiếp cận sẽ khá dễ. Dart hỗ trợ khai báo biến linh hoạt (loose and strong typing) với cú pháp (syntax) kiểu C và biên dịch kiểu JavaScript. Okay, vài dòng giới thiệu về ngôn ngữ, giờ sẽ không mất thêm thời gian hãy đi vào coi thử làm sao để "code" với Dart.

    #### 1. Project structure

    - Thư mục bin: đây là nơi chứa các file public tools để chạy Dart scripts.
    - Thư mục lib: đây là nơi chứa các file public libraries để import vào trong các file ở thư mục bin.
    - pubspec.yaml: nơi import dependency, quản lí phiên bản của Dart, etc.. nó tương tự gradle trong Android và được viết bằng YAML language.

    #### 2. Important concepts

    Đây là phần chú ý đầu tiên khi bạn đọc trên trang chủ của Dart. Vì thế hãy đọc kỹ hướng dẫn trước khi liều.

    1. Bất kì thứ gì có thể đặt vào 1 biến đều là `object` và mọi object đều là thể hiện của 1 `class`. Số, hàm, `null` đều là object. Mọi object thì đều xuất phát từ Object class.
    2. Mặc dầu Dart là strong typed nhưng Dart vẫn hỗ trợ loose typed. Có nghĩa là nếu bạn chưa chắc chắn về kiểu dữ liệu cho biến thì vẫn có thể khai báo với kiểu dynamic.
    3. Dart hỗ trợ generic type, ví dụ `List<int>``List<dynamic>`.
    4. Dart hỗ trợ top-level function (như hàm main()). Bạn có thể tạo ra 1 hàm bên trong hàm khác (nested hoặc local function).
    5. Dart cũng hỗ trợ top-level variables.
    6. Không như Java, Dart không có các từ khóa để set access modifier. Nếu 1 indentifier bắt đầu với ( _ ) thì nó là *private* trong library của nó.
    7. Identifier có thể bắt đầu bằng một chữ cái hoặc dấu gạch dưới ( _ ).
    8. Dart vừa hỗ trợ *expressions*, vừa hỗ trợ *statements*. Bạn có thể sử dụng biểu thức `? exp1 : exp2` và cũng có thể sử dụng câu lệnh`if else`.
    9. Dart tools có thể báo cho bạn 2 loại vấn đề: warnings và errors. Warnings là những dấu hiểu chỉ ra rằng code của bạn có thể không hoạt động, nhưng chương trình của bạn vẫn có thể chạy. Errors có thể là error lúc compile-time hoặc run-time. Error lúc compile-time hiển nhiên sẽ khiến code bạn không chạy được, còn kết quả của error run-time sẽ là những exceptions được throw ra khi chạy.

    #### 3. Variables

    - String - để thao tác với chuỗi và kí tự.

    ```dart
    String name = 'huy pham';
    ```

    - num - để thao tác với số.

    ```dart
    num number = 17;
    num number1 = 17.03;
    ```

    - int - để thao tác với số nguyên.
    - double - để thao tác với số thập phân.
    - bool - để khai báo biến boolean.

    ```dart
    bool isCheck = true;
    ```

    - const - để khai báo biến hằng.

    ```dart
    const int id = 123;
    ```

    - dynamic - có thể dùng để khai báo cả chuỗi và số.

    ```dart
    dynamic name = 'huy pham';
    dynamic age = 25;
    dynamic isHandsome = true;
    ```

    - var - để khai báo biến khi chưa biết là chuỗi hay số, không thể dùng để khai báo kiểu trả về của hàm.

    ```dart
    var text = 'hello guys';
    ```

    - Runes - để sử dụng các emoji.

    ```dart
    Runes clap = Runes('\u{1f44f}');
    print(String.fromCharCodes(clap));
    ```
    Tất cả biến trong Dart đều không phải là dạng nguyên thủy nó đều là đối tượng.

    #### 4. Collection

    - Enumerated types - còn được gọi là enum, một kiểu class đặc biệt sử dụng để biểu diễn một tập hợp giá trị không đổi.

    ```dart
    enum color {
    red,
    blue,
    green,
    orange
    }
    ```

    - List - một collection thông dụng, dùng để tập hợp các phần tử vào 1 mảng, trong Dart chi có object list và nó làm hết công việc của ArrayList như add, remove, insert.

    ```dart
    List<num> numbers = [0, 1, 2, 3, 4, 5];
    List mixin = [69, 'kimochi', true]; // List<dynamic>
    ```

    - Map - 1 object thông dụng khác, chứa cặp key-value. Dart hỗ trợ map literals và kiểu dự liệu Map.

    ```dart
    Map roles = {'H': 'dev', 'U': 'tester', 'Y': 'designer'};

    Map<String, int> languages = Map();
    languages.putIfAbsent('java', () => 1890);
    languages.putIfAbsent('dart', () => 2011);
    languages.putIfAbsent('java', () => 1995);
    ```

    - Set - tập hợp các giá trị không theo thứ tự và không lặp lại giá trị đã có.

    ```dart
    Set<int> numbers = new Set<int>();
    numbers.add(3);
    numbers.add(2);
    numbers.add(2);
    numbers.add(7);

    var age = {1, 'a', true};
    ```

    - Queue - 1 collection có thể thao tác cả 2 đầu vào của mình. 1 đầu để đưa dữ liệu và 1 đầu xóa dữ liệu. Hữu dụng khi xây dựng collection theo kiểu first in, fist out.

    ```dart
    Queue numbers = new Queue();
    ```

    #### 5. Flow control

    - assert - ngắt 1 thực thi thông thường khi điều kiện trả về sai.

    ```dart
    assert(name == 'huy');
    ```

    - if else - như mọi ngôn ngữ khác, sử dụng để điều hướng.

    ```dart
    if(condition) {
    // do something
    } else {
    // do another
    }
    ```

    - switch case - như mọi ngôn ngữ khác, cũng sử dụng để điều hướng.

    ```dart
    var condition;
    switch(condition) {
    case decision:
    // do something;
    break;
    case decison1:
    // do another thing;
    break;
    default:
    // do default result;
    break;
    ```

    - Loop - vòng lặp.
    - while

    ```dart
    while(condition) {
    // do something
    }
    ```

    - do while

    ```dart
    do {
    // do something
    } while(condition);
    ```

    - For loop

    ```dart
    List alphabets = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'];

    // for with index
    for(int i = 0; i < alphabets.length; i++) {
    // do something
    }

    // for each item
    for(var word in alphabets) {
    // do something
    }

    alphabets.forEach((String item) {
    // do something
    });
    ```

    #### 6. Function

    - Basic function - Dart là ngôn ngữ hướng đối tượng, hàm trong Dart cũng là một object và có một kiểu dữ liệu cho nó. Điều đó có nghĩa là có thể gán 1 function cho 1 biến hoặc dùng nó làm đối số (argument) cho 1 hàm khác.

    ```dart
    bool isYourName(String name) {
    return name == 'huy pham';
    }
    ```

    - Nếu không khai báo kiểu dự liệu thì sẽ mặc định là void hoặc tùy vào kết quả trả về của hàm.

    ```dart
    isYourName(String name) {
    return name == 'huy pham';
    }
    ```

    - Để rút gọn thì ta nên dùng cú pháp `=>` đối với hàm không có block code.

    ```dart
    isYourName(String name) => name == 'huy pham';
    ```

    - Optional named parameter function - khi gọi hàm bạn có thể chỉ định tên tham số đã khai báo trong hàm và gọi tham số tùy ý không cần quan tâm đến thứ tự của nó.

    ```dart
    void declareYourCharacter(bool isHumorous, {bool isQuiet, bool isKind = false}) {
    // do something
    }

    declareYourCharacter(true, isKind: true, isQuiet: true);

    ```

    - Optional unnamed parameter function - bạn có thể tạo ra 1 tham số tùy chọn khi khởi tạo hàm, lúc gọi làm bạn có thể truyền hoặc không truyền đối số vào cho nó và phải gọi đúng thứ tự như lúc khởi tạo.

    ```dart
    void void declareYourCharacter(bool isHumorous, [bool isQuiet, bool isKind = false]) {
    // do something
    }

    declareYourCharacter(true, true, true);
    ```

    - Anonymous function - hầu hết mọi hàm đều có 1 cái tên để thể hiện hàm đó làm gì nhưng chúng ta vẫn có thể khởi tạo 1 hàm không tên và gọi nó là anonymous function hoặc có thể là lambda hoặc là closure. Anonymous function được khởi tạo lúc chạy runtime, nó có thể gán cho 1 biến, gọi 1 hàm khác.

    ```dart
    var alphabets = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'];

    alphabets.forEach((String item) {
    print('${alphabets.indexOf(i)item);
    });
    ```

    #### 7. Null aware operation

    - `?:` (Tenary Operator) - đa số ngôn ngữ đều hỗ trợ, thay thế cho if else.

    ```dart
    height < 175 ? 'Short' : 'Tall';
    ```

    - `??` - toán tử kiểm tra null, nếu biến trả về bằng null thì nó sẽ gán biến đó cho 1 giá trị mặc định.

    ```dart
    String name = user.name() ?? 'huy pham';
    ```

    - `??=` - kiểm tra biến có null không, nếu biến null thì gán giá trị nếu không thì không thực thi.

    ```dart
    Alphabet alphabet;
    alphabet ??= Alphabet('alpha');
    ```

    - `?.` - truy cập vào 1 method hoặc 1 object, nếu nó không null, ngược lại thì trả về null.

    ```dart
    Alphabet alphabet;
    // nếu aphabet có giá trị character thì gán cho biến character ngược lại quăng ra exception
    String character = alphabet?.character;

    // tốt hơn thì nên gán giá trị mặc định nếu giá trị trả về là null
    String character = alphabet?.character ?? 'alpha';
    ```

    #### 8. Classes

    <!--Class và constructor vẫn còn nhiều cái để nói nhưng chỉ nêu ra cái cơ bản nhất-->
    Dart là ngôn ngữ hướng đối tượng với các class và thừa kế dựa trên mixin (mixin-based inheritance). Mỗi object đều là thể hiện của 1 class và tất cả class đều xuất phát từ Object class. *Thừa kế dựa trên mixin* có nghĩa là mỗi class đều có 1 superclass (trừ Object class), phần bên trong của mỗi class đều có thể được tái sử dụng trong nhiều class được phân cấp.

    - Create a class

    ```dart
    class Vehicle {
    int wheel;
    int speed;
    }
    ```

    - Constructor

    ```dart
    class Vehicle {
    int wheel;
    int speed;
    }

    Vehicle(this.wheel; this.speed);
    ```

    #### 9. Object oriented programming

    - Encapsulation - tính bao đóng là đối tượng được bảo vệ không cho các truy cập từ code bên ngoài như thay đổi trạnng thái hay nhìn trực tiếp. Tính bao đóng của Dart được thể hiện bằng cách khai báo ( _ )trước biến hoặc hàm, phạm vi hoạt động của nó là trong library chứa nó và kể cả khi import thì bạn cũng không thể gọi trực tiếp được.

    ```dart
    int _x;

    void _init() {
    // do something
    }
    ```

    - Inheritance - tính kế thừa là khả năng cho ta xây dựng class dựa trên tính chất của class đã có. Đó là class Cha, các class Con phát sinh từ class Cha và đương nhiên nó cũng sẽ được thừa kế tính chất của Cha. Class Con có thể sử dụng các tính chất như định nghĩa ở class Cha thông qua super hoặc có thể định nghĩa lại.

    ```dart
    class Vehicle {
    void countNumberOfWheels(int wheel) {
    print('This vehicle has $wheel wheels');
    }
    }

    class Bike extends Vehicle {
    @override
    void countNumberOfWheels(int wheel) {
    super.countNumberOfWheels(wheels); }
    }
    ```

    - Polymorphism - tính đa hình là các object trong cùng 1 họ tuân thủ theo 1 thể hiện nhưng có thể thực thi theo nhiều cách khác nhau.
    - Override - khi cùng 1 phương thức nhưng cách bên trong phương thức đó thực hiện ở từng nơi lại khác nhau. Ví dụ phương thức `countNumberOfWheels` ở ví dụ trên, xe máy sẽ trả về 2 nhưng xe ô tô lại trả về 4.
    - Overload - không được support trong Dart nhưng bạn có thể sử dụng optional parameter để thay thế, cùng 1 phương thức nhưng có tham số khai báo trong nó có thể được xài hay không được xài.
    - Abstraction - tính trừu tượng là sự tập trung vào các tính chất cối lõi nhất của 1 object, loại bỏ đi những tính chất rườm rà xung quanh.

    ```dart
    abstract class Vehicle {
    void honk();
    void speed();
    }

    // extend toàn bộ phương thức được khai báo trong Vehicle
    // có thể thừa kế lại những tính chất đã định nghĩa trong class Vehicle thông qua super
    class Motobike extends Vehicle {
    @override
    void honk() {
    super.honk();
    }
    @override
    void speed() {
    print('Very fast');
    }
    }
    ```

    - Interface - Dart không hổ trợ từ khóa interface để khai báo nhưng mỗi class đều định nghĩa là một interface.

    ```dart
    class Vehicle {
    //phải định nghĩa phương thức đó để làm gì
    void honk() => print('honk honk);
    void speed() => print('322 km/h');
    }

    // implement toàn bộ phương thức được khai báo trong Vehicle
    // nó sẽ không thừa kế lại từ Vehicle và bạn phải định nghĩa lại phương thức đó sẽ làm gì
    class Motobike implements Vehicle {
    @override
    void honk() {
    print('beep beep');
    }
    @override
    void speed() {
    print('Very fast');
    }
    }
    ```

    - Mixin và mixin - đây là khái niệm khiến nhiều người khi tiếp xúc với Dart khá lúng túng. Vậy mixin là gì? Mixin là gì? và liệu một chiếc xe máy có thể chạy trên nước?
    - Mixin - cách để trừu tượng hóa và tái sử dụng code trong các class khác nhau.

    ```dart
    class Motobike {
    bool isRunFast() {
    return true;
    }
    void show() {
    print('This is a motobike');
    }
    }

    class Plane {
    bool isFlyHigh() {
    return true;
    }
    void show() {
    print('This is a plane');
    }
    }

    class Ship() {
    bool isRunInWater() {
    return true;
    }
    void show() {
    print('This is a ship');
    }
    }

    mixin Mixin on Ship {
    @override
    bool isRunInWater() {
    super.isRunInWater();
    }
    bool isHaveSail() {
    return true;
    }
    }

    class Scooter extends Motobike with Plane, Ship {...}

    main() {
    Scooter myScooter = Scooter();
    myScooter.isRunFast(); // true
    myScooter.isFlyHigh(); // true
    myScooter.isFlyHigh(); // true
    myScooter.show(); // This is a ship
    }
    ```

    - Như ví dụ trên, class Scooter có thể sử dụng các thương thức được khai báo ở các class Motobike, Plane, Ship mà không gặp phải một trở ngại gì. Đây chỉ là cách để tái sử dụng lại code trong Dart chứ không phải là đa thừa kế, đừng nhầm lẫn chỗ này.
    - Tương tự, khi gọi phương thức `show()` thì kết quả trả về là `This is a ship`, bởi vì khi extend qua các class như vậy thì các class đó sẽ được sếp vào 1 stack theo tuyến tính. Class Motobike được extend đầu tiên sẽ nằm trên đầu, sau đó lần lượt các class Plane và Ship sẽ xếp sau trong stack. Vì là last in, first out nên khi thực thi thì phương thức `show()` ở class Ship sẽ được thực thi.
    - mixin - khai báo việc có thể áp dụng mixin vào class. Class Mixin có thể extends hoặc implements các phương thức được khai báo ở class Ship(). Khi khởi tạo với từ khóa mixin thì trong class đó chỉ có khai báo các phương thức, bạn không thể khởi tạo constructor hoặc getter, setter. Đây giống như 1 chiếc thùng chứa tất cả các phương thức, khi nào bạn cần sử dụng phương thức nào thì extends hoặc implements đến nó và lấy ra sử dụng.

    **All right, hy vọng với những kiến thức cơ bản này thì mình mong bạn đã có thể tự tin tự mình tiếp tục "khám phá" Dart. Và những kiến thức nâng cao hơn như asynchronous, generic, socket hoặc BLoC pattern thì mình sẽ nói đến ở những bài viết theo, hy vọng các bạn tiếp tục ủng hộ :)**

    ## Flutter framework

    Flutter là 1 mobile SDK do Google phát triển, nó giúp người dùng có thể tạo ra được 1 ứng dụng chạy trên cả iOS và Android. Là một Cross-flatform framework nhưng khác với các Cross-flatform hiện tai, Flutter không thông qua bridge, mà nó sẽ chạy engine render riêng (viết bằng C++) và dùng Flutter framework (viết bằng Dart) để giao tiếp với các service. Cả 2 bộ này sẽ được đóng gói cùng ứng dụng và thông qua SDK nó có thể chạy trên đa nền tảng. Kì vọng mà team phát triển Flutter nhắm đến là có thể chạy trên đa nền tảng, Flutter ngoài chạy trên mobile thì còn có thể chạy trên nền web thông qua dự án mang tên Hummingbird, chạy trên các thiết bị IoT và cả desktop. Tuy vậy, Flutter cũng còn rất "non trẻ", nó cần thêm thời gian để có thể phát triển hơn nữa và việc chọn Flutter để học cũng là 1 cách để đầu tư cho tương lai.

    ![alt](https://cdn-images-1.medium.com/max/800/1*UpoHX3az39ZqkFwBr_gndA.png)

    Sau gần 1 năm với các phiên bản preview thì phiên bản stable 1.0 của nó được ra mắt vào sự kiện Flutter Live (4/12/2018) và phiên bản hiện tại lúc mình viết bài này là 1.2.2.

    Để bắt đầu tìm hiểu thì chúng ta sẽ đi vào tìm hiểu về lifecycle cụ thể là stateful widget lifecycle và stateless widget lifecycle, đối với mình tìm hiểu về lifecycle là điều đầu tiên mình quan tâm khi tìm hiểu về framework nào đó. Bởi vì hiểu được lifecycle thì chúng ta sẽ dễ dàng tiếp cận và biết được nó sẽ hoạt động như thế nào. Ở đây mình sẽ viết theo những gì mình biết và mình hiểu nên có sai sót hoặc thiếu xót cần góp ý thì hãy comment phía dưới cho mình :)

    #### 1. Widget and Widget tree

    - Trong Flutter, mọi thứ đều là **Widget**. Widget là thứ mà bạn có thể nhìn thấy, có thể tương tác với ứng dụng của bạn.
    - Widget được tổ chức thành dạng cây, gồm có parent Widget và children Widgets.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
    title: Text('Demo'),
    ),
    body: Center(
    child: Column(
    children: <Widget>[
    Text('Hello guys'),
    Text('Welcome to my article'),
    ],
    ),
    ),
    floatingActionButton: FloatingActionButton(
    onPressed: _onPressed,
    child: Icon(Icons.add),
    ),
    );
    }
    ```

    - Như ví dụ trên, Scaffold là parent Widget chứa 3 children widgets là Center, Column và Text. Ta sẽ có được sơ đồ widget tree như sau:

    ![alt](https://cdn-images-1.medium.com/max/800/1*z_A9htJmE6THrxZeloVRiw.png)
    ###### *Ảnh của Didier Boelens*

    #### 2. BuildContext

    - BuildContext là tham chiếu đến vị trí của mỗi widget trên widget tree. Mỗi widget có 1 BuildContext thể hiện. Nếu 1 widget có các children widgets thì BuildContext của widget đó cũng sẽ là parent BuildContext của các children BuildContexts chứa trong nó. Điều đó có nghĩa chúng ta sẽ có một BuildContext tree.

    ![alt](https://cdn-images-1.medium.com/max/800/1*Tc0kB9YXL4Bj6tonRJlH0w.png)
    ###### *Ảnh của Didier Boelens*

    #### 3. StatelessWidget

    - Đây là những widget không quan tâm đến việc thay đổi, tạo ra 1 lần duy nhất hoặc hiểu cách đơn giản hơn thì đây là widget chỉ nhận khởi tạo có sẵn rồi thực thi nó và không có thay đổi State. Ví dụ như widget Text, Center, MaterialApp, ...
    - Cấu trúc của một StatelessWidget như sau:

    ```dart
    class MyWidget extends StatelessWidget {
    MyWidget({Key key, this.param,}) : super(key: key);
    String param;
    @override
    Widget build(BuildContext context) {
    return Container(
    child: Text('Hello guys'),
    );
    }
    }
    ```

    - Bạn có thể thấy, chúng ta có thể thêm vài tham số vào constructor. Tuy nhiên, hãy nhớ rằng những tham số này sẽ không thay đổi (immutable) ở những lần build sau.
    - Lifecycle của StatelessWidget gồm:
    - Khởi tạo
    - Render widget thông qua build()

    #### 4. StatefulWidget

    - Trái ngược với StatelessWidget thì StatefulWidget sẽ xử lí các dữ liệu bên trong nó, lắng nghe những thay đổi, dữ liệu này sẽ liên tục thay đổi (mutable) trong suốt lifecycle của widget.
    - Tập hợp những dữ liệu thay đổi được giữ bởi StatefulWidget, thay đổi trong suốt lifecycle của widget này và dữ liệu có không thể đọc 1 cách đồng bộ khi widget đã được build thì ta gọi đó là State. State định nghĩa ra phần hành vi mà StatefulWidget thể hiện. 1 State chứa các thông tin tương tác với widget thông qua các khía cạnh về hành vi (behavior) và layout. Mỗi khi thay đổi State thì widget đó sẽ thay đổi theo.
    - Giữa State và BuildContext có 1 mối quan hệ khá khăn khít. Mỗi khi 1 State được tạo ra thì nó sẽ gắn với 1 BuildContext và lúc này State là *mounted*.

    #### 5. StatefulWidget lifecycle

    - Lifecycle của StatefulWidget được thể hiện như sau:
    - createState()
    - mounted == true
    - initState()
    - didChangeDependencies()
    - build()
    - didUpdateWidget()
    - setState()
    - deactivate()
    - dispose()
    - mounted == false

    ```dart
    class MyWidget extends StatefulWidget {
    @override
    _MyWidgetState createState() => _MyWidgetState();
    }

    class _MyWidgetState extends State<MyWidget> {

    @override
    void initState() {
    super.initState();
    }

    @override
    void didChangeDependencies() {
    super.didChangeDependencies();
    }

    @override
    Widget build(BuildContext context) {
    return null;
    }

    @override
    void didUpdateWidget(TestMain oldWidget) {
    super.didUpdateWidget(oldWidget);
    }

    @override
    void setState(fn) {
    super.setState(fn);
    }

    @override
    void deactivate() {
    super.deactivate();
    }

    @override
    void dispose() {
    super.dispose();
    }
    }
    ```

    - createState() - khi tạo ra 1 StatefulWidget thì createState() sẽ được gọi để tạo ra State cho widget và thêm widget vào widget tree.
    - mounted == true - khi chúng ta đã tạo ra State thì 1 BuildContext sẽ được gán cho State.
    - initState() - đây là phương thức đầu tiên được gọi lúc ta khởi tạo widget. Nó được gọi 1 và chỉ 1 lần duy nhất và khi override lại thì cần phải gọi lại super.initState(). Chúng ta sử dụng phương thức này cho:
    - Khởi tạo dữ liệu cho 1 BuildContext cụ thể
    - Khởi tạo các thuộc tính cho parent widget
    - Khi chúng ta đăng kí 1 Stream, khởi tạo dữ liệu hoặc thay đổi dữ liệu của widget
    - didChangeDependencies() - đây là phương thức tiếp theo sẽ được gọi sau khi initState() được khởi tạo. Override phương thức này có nghĩa là widget đã được liên kết với 1 InheritedWidget hoặc bạn muốn State lắng nghe sự thay đổi của widget được thừa kế . Một khi đã liên kết widget với InheritedWidget thì mỗi khi widget rebuild thì phương thức này sẽ được gọi.
    - build() - đây là phương thức sẽ được gọi mỗi khi State thay đổi hoặc là khi InheritedWidget cần thông báo cho các widget đã đăng kí.
    - didUpdateWidget() - phương thức được gọi nếu parent widget thay đổi hoặc có widget cần rebuild, nhưng nó cần phải cùng runtimeType. Flutter có cơ chế tái sử dụng State trong thời gian dài, do đó, trong trường hợp này ta cần khởi tạo lại dữ liệu.
    - setState() - đây là phương thức mà bạn sẽ phải "vọc" khá nhiều khi làm việc với Flutter. Nó thông báo cho framework biết dữ liệu đã thay đổi và widget nên rebuild lại. setState() nhận 1 callback đồng bộ.
    - deactivate() - hiếm khi ta phải đụng đến phương thức này, bởi vì nó được gọi khi 1 widget bị xóa khỏi widget tree nhưng có thể thêm vào lại nếu frame vẽ lên widget đó chưa kết thúc. Phương thức này được tạo để phục vụ việc di chuyển State từ điểm này đến điểm khác trên widget tree.
    - dispose() - gọi khi State đã được xóa hoàn toàn.
    - mounted == false - khi này State không thể nào remount lại được nữa.

    #### 5. StatefulWidget or StatelessWidget?

    - Nếu widget của bạn sẽ phải thường xuyên thay đổi State và khi thay đổi thì widget của bạn sẽ được rebuild thì bạn nên sử dụng StatefulWidget. Còn nếu widget của bạn State từ lúc khởi tạo đến lúc kết thúc vẫn không có gì thay đổi thì bạn nên sử dụng StatelessWidget.
    - Ví dụ widget của bạn là 1 TextField, bạn cần phải biết được State lúc nào nó được nhập, lúc nào nó đã được nhập xong, State của nó thay đổi liên tục. Còn nếu widget của bạn chỉ là 1 Text hiển thị thông báo và nó không bao giờ thay đổi thì bạn nên sử dụng StatelessWidget.

    #### 5. Some common widgets

    Ở bài viết này mình chỉ liệt kê và giới thiệu tên vào widget thường hay dùng nên sẽ không đi sâu vào các thuộc tính của nó. Sẽ có 1 bài viết hoặc nhiều bài viết khác mình giới thiệu về các widget trong Flutter. Thế giới widget trong Flutter rất đa dạng nên 1 bài viết chẳng thể nào nói hết được sự thú vị của nó. Đây là thứ hấp dẫn mình đến với Flutter, cảm giác khi làm việc với các widget y như khi bạn chơi với một bộ lego, bạn tha hồ lắp ghép và sáng tạo với nó.

    - Text - hiển thị nội dung bạn muốn thông báo và bạn có thể custom nó thông qua thuộc tính style với khá nhiều thứ thú vị.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Text('Hello guys');
    }
    ```

    - TextField - giúp bạn có thể nhập nội dung từ bàn phím.

    ```dart
    @override
    Widget build(BuildContext context) {
    return TextField();
    }
    ```

    - RaisedButton - nút bấm giúp bạn có thể truy cập đến các phần khác nhau tùy theo ý muốn của bạn. Widget này bắt buộc bạn phải truyền vào 1 callback cho thuộc tính onPressed.

    ```dart
    @override
    Widget build(BuildContext context) {
    return RaisedButton(onPressed: _onPressed,);
    }
    ```

    - Scaffold - đây là 1 widget cung cấp cho bạn một giao diện hoàn chỉnh gồm phần appbar, body và 1 floatingActionButton chính hiệu Google.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Scaffold();
    }
    ```

    - Container - widget thông dụng cung cấp 1 widget con, nó là wiget vừa có các thuộc tính để padding và có các thuộc tính để margin, width và height. Nếu sử dụng widget này bạn sẽ tốn khá nhiều thời gian để bạn ngồi canh chỉnh view sao cho đẹp nhất.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Container(
    child: Text('Hi guys'),
    );
    }
    ```

    - Center - widget giúp bạn canh giữa cho widget con bên trong, lúc đầu mình cũng khá "bối rối" với widget này vì việc canh giữa bây giờ đã được nâng lên một tầm cao mới nhưng đến khi xài nó thì cảm thấy khá tiện lợi.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Center(
    child: Text('Hi guys'),
    );
    }
    ```

    - Padding - widget đúng như tên của nó là padding widget con bên trong. Bạn bắt buộc phải khai báo thuộc tính padding của nó thông qua class EdgeInsetsGeometry.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Padding(
    padding: EdgeInsets.all(69.96),
    child: Text('Hi guys'),
    );
    }
    ```

    - Expanded - widget giúp bạn bọc widget con bên nó và phân vùng hiển thị để không bị bể giao diện. Nó tương tự như *layout_weight* bên Android.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Expanded(
    child: Text('Hi guys'),
    );
    }
    ```

    - Row và Column - đây là 2 widget giúp bạn hiển thị tập hợp nhiều widget sắp xếp theo hàng hoặc cột. Nó tương tự như thuộc tính *orientation* trong *LinearLayout* của Android.

    ```dart
    @override
    Widget build(BuildContext context) {
    return Row(
    children: <Widget>[
    Text('Hello guys'),
    Text('This is row'),
    ],
    );
    }
    ```

    ```dart
    @override
    Widget build(BuildContext context) {
    return Column(
    children: <Widget>[
    Text('Hello guys'),
    Text('This is column'),
    ],
    );
    }
    ```

    **Okay, mong rằng 1 vài hiểu biết cơ bản của mình về Flutter sẽ giúp bạn có hiểu được Flutter là gì và các khái niệm cơ bản khi bạn tiếp cận với Flutter.**

    ## Tham khảo

    - [Widget — State — BuildContext — InheritedWidget](https://medium.com/flutter-community/widget-state-buildcontext-inheritedwidget-898d671b7956)