Flutter

Flutter, Bài 3: Giới thiệu về Dart

Lần này, chúng ta sẽ tìm hiểu một số khái niệm cần biết cuối cùng của Dart trước khi vào Flutter. Trong bài này, tôi chủ yếu giới thiệu về async operations.

Cũng như các ngôn ngữ khác, hỗ trợ Dart asynchronous operations là không thể không có. Nếu bạn chưa rõ về tại sao cần phải có async ops và tầm quan trọng của chúng, hãy đọc lại bài lí thuyết thuần của tôi tại đây. Việc thực hiện các async ops trên Dart rất gần gũi với JavaScript. Vì vậy, nếu bạn đã có kinh nghiệm về JS, bạn sẽ không mất quá 10 phút để làm quen với Dart async. Nhưng nếu bạn đến từ Android với Java thuần hay Swift thì có thể bạn sẽ mất một khoảng thời gian để “thích nghi”.

Để tạo một async function, bạn cần từ khóa async. Đương nhiên, async phải đi với function rồi, không thể có trường hợp một async op lại được thực hiện dưới một biến được. Với JavaScript, bạn đặt async trước từ khóa function để thông báo cho trình duyệt biết đây là một function được thực hiện dưới nền. Còn đối với Dart, từ khóa async sẽ nằm trước dấu mở ngoặc nhọn, hơi “ngược ngạo” một chút. Chẳng hạn:

Với Dart, bạn sẽ có 2 concepts gốc và phổ biến nhất là Stream và Future, nhưng bạn cũng có thể tạo một async function mang tính “bình thường”, tức là giống như một sync function nhưng chạy ngầm và không cần trực tiếp đả động gì tới hai tên Stream và Future kia với những methods đã return Stream và Future sẵn. Ngoài ra, bạn còn có await và yield hoạt động giống với await và yield trong JavaScript ECMA6 2015 vậy.

Bạn có thể hiểu ngắn gọn Stream<T> là phiên bản async của Iterator (Iterator trong Dart tương tự như Iterator trong Java) vậy, tức là một Object lớn phát ra (emits) các object con theo từng sự kiện (event). Ngoài ra, nếu bạn đã có kiến thức sơ bộ về Rx programming pattern thì sẽ không quá khó hiểu về Stream này, nó tương tự như một Observable mà thôi.

Còn Future<T> là cái bạn thường gặp hơn. Nó cũng có một phần tương tự như Future trong Java, nhưng nó giống JavaScript Promise hơn. Điển hình là nó có syntax Future().then((res) { }).catchError((error) { }) như JavaScript Promise, và nếu bạn đã quen thuộc với Promise, bạn sẽ dễ dàng tận dụng thế mạnh của Future, nhưng việc viết một Future trên Dart là không dễ dàng chút nào, đặc biệt là đối với những bạn chỉ có kiến thức vừa đủ với Android Java và Swift để code được một app đủ ở mức hoàn chỉnh, mà chưa thực hiện nghiên cứu sâu về ngôn ngữ.

Trước hết, tôi sẽ trình bày một async function đơn giản. Function này sẽ request data từ một url về và print ra trong console. Bản chất của HttpRequest.getString trong Dart đã return một Future<String> instance rồi:

Ngoài ra, bạn có thể nối chuỗi Future trong Dart như chuỗi Promise trong JavaScript để mọi thứ trở nên dễ nhìn hơn hẳn. Còn nếu bạn đang thắc mắc cách muốn tự viết một Future<T>, bạn sẽ dùng cách nào? Trước hết, bạn tham khảo phẩn reference của Future class trong Dart ở đây. Bạn sẽ để ý constructor đầu tiên là Future<T>(FutureOr<T> computation). Thực chất, FutureOr chỉ đơn giản là một cấu trúc lambda mà thôi, bên trong bo đì của nó sẽ return một giá trị <T>. Chẳng hạn:

Giá trị return trong cấu trúc lambda đó chính là giá trị sẽ được truyền vào function trong .then, rất tương tự với Promise.resolve(res) trong JavaScript vậy. Và mặc định, mọi thứ trong block FutureOr này sẽ được thực hiện dưới nền. Bạn có thể làm tương tự với các constructors khác. Còn với awaityield, chúng hoạt động rất tương tự như awaityield trong JavaScript ECMA 6 2015, do đó, nếu bạn chưa có kinh nghiệm về JavaScript, bạn có thể học nhanh qua hai khái niệm trên.

Ngoài ra, để nâng cao tay nghề, bạn có thể tự tìm hiểu thêm về Future.wait và Stream tại document chính chủ của DartLang ở đây. Đối với những ứng dụng Flutter đơn giản chỉ gửi request và nhận response dưới dạng JSON, bạn có thể chỉ cần tìm hiểu mỗi method http.get(String url) với http thuộc gói http mà thôi, không cần thiết phải đi sâu vào Future hay Stream APIs. Tuy nhiên, về sau, bạn muốn tối ưu hóa các request và response để đẩy nhanh quá trình như các thư viện Volley hay Retrofit với Android, việc cần đào sâu vào Future và Stream là không thể không có được.

Cá nhân tôi xin chia sẻ về cách học Dart của tôi: Đó là bạn nên đi từ góc độ JavaScript hơn là Java hay Swift, mặc dù Dart có những chỗ nổi bật giống Java hơn là JavaScript làm cho bạn nghĩ nó gần với Java hơn. Tuy nhiên, khởi thủy của Dart là làm Web, và thực tế, nếu bạn để ý kĩ, các constructors trong Dart với optional params giống như JS Map Object, chẳng hạn:

Ngoài ra, cách code của Dart cơ bản cũng tương đồng hơn với JavaScript cơ bản, tức là bạn có thể định nghĩa async functions ngay trong một tập tin dart ngang hàng với các sync function khác, mà không cần phải tách class riêng và tự phân Thread như trong Java. Dẫu vậy, để học Dart được nhanh, bạn cũng cần một chút kiến thức cơ bản của Java, sẽ dễ nắm bắt các khái niệm gần với Java hơn, như abstract class và implementation.

Chuỗi bài viết về Dart này không trình bày tất cả về Dart, mà chỉ nói về những điểm cần chú ý, khác biệt so với mặt bằng chung của các ngôn ngữ khác. Để tìm hiểu thêm, bạn cần chịu khó đọc hết các document tại trang chính https://dartlang.org. Ngay cả bản thân tôi, khi viết những dòng này cũng chưa đọc hết các docs đó, tuy nhiên, những kiến thức cơ bản sẽ giúp bạn có thể vào ngay Flutter để code ứng dụng ngay, từ đó tôi và các bạn có thể lấy Flutter để làm nền học Dart.

Trước khi chia tay, tôi muốn trình bày “cảm nhận, tâm tư” của tôi về Dart. Tôi có xem những video hướng dẫn về Flutter tại Google I/O 2017 và lúc đó tôi không hề có thiện cảm với Dart, vì thoạt nhìn thì nó có vẻ rắc rối và “nửa nạc nửa mỡ”. Tuy nhiên, sau khi “nổi cơn hứng chí” muốn nghiên cứu về Flutter vào khoảng 20/6/2018, và dĩ nhiên tôi phải học về Dart, thì tôi lại thích nó hơn Kotlin nhiều, và tôi ước Google chọn Dart thay cho Kotlin làm ngôn ngữ phát triển ứng dụng cho Android thì hơn. Thứ nhất, Dart nhìn có vẻ rắc rối, nhưng thực chất nó vẫn còn đơn giản hơn Kotlin, và thậm chí không có nhiều thứ mang tính thái quá như việc tránh null lại sinh ra nhiều vấn đề như Kotlin lateinit, hay việc nó sử dụng cặp đôi ?: tương tự như C hay Java thay vì phải dùng luôn ifelse như tác phẩm của JetBrain trong inline conditional expression, v.v…

Và như vậy, tôi sẽ kết thúc phần giới thiệu sơ lược về Dart ở đây. Sang bài sau, chúng ta sẽ bắt đầu “làm ăn” với Flutter.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.