Android

Tạo ứng dụng Flutter đơn giản: Gửi request và hiển thị response lên ListView

Flutter_LIstView_getDataFromInternet

Như bạn đã từng nghe tôi nói, khi đã viết ứng dụng có gửi Request và nhận Response thì thường là sẽ hiển thị Response lên ListView vì bản thân Response hay một phần tử nào đó của Response là dạng Array hoặc Map. Thông thường nhất là các ứng dụng về email, chat hoặc bán hàng, hay đơn giản hơn nữa là ghi chú. Bài này sẽ đưa ra ví dụ hướng dẫn các bạn gửi Request lên server, lấy Response về dưới dạng List và hiển thị lên ListView, dĩ nhiên là sử dụng Flutter. Screenshot trong hình là một thiết bị Android nhưng nó cũng cho kết quả “sao y bản chính” với iPhone. Và trước khi đọc tiếp, mời bạn bật Android Studio lên và tạo project mới, và ta sẽ tận dụng luôn code có sẵn đó, đúng hơn là chỉ thay đổi code của _MyHomePageState.

1. Endpoint và mỗi phần tử của response:

Endpoint mà tôi dùng là “http://jsonplaceholder.typicode.com/posts” với method GET. Bạn có thể cóp pát địa chỉ trên vào trình duyệt để xem mặt mũi của Response trả về tròn méo ra sao. Dưới đây là phần tử đầu tiên:

2. Hướng tư duy:

Như tôi luôn nhắc đi nhắc lại, chúng ta phải thực hiện tư duy theo hướng State, hay nói đúng hơn là setState. Mọi Widgets đều được cập nhật qua State dưới dạng setState. Do đó, bạn không thể dùng cách tư duy kiểu dùng Adapter với ArrayList nguồn rồi add phần tử vào và gọi hàm thần thánh Adapter.notifyDataSetChanged. Lần này, bạn cũng đặt một List, nhưng tốt nhất bạn nên đặt nó trong State<StatefulWidget> class thay vì đặt trực tiếp trong StatefulWidget, để dễ bề quản lí hơn. Chúng ta sẽ tiến hành cập nhật nó trong setState. ListView của bạn sẽ lấy dữ liệu trực tiếp từ nó, nên ListView sẽ tự cập nhật luôn cho bạn.

Ngoài ra, trong phiên bản mới của dart:convert, thì json.decode với JSON nguồn là một JSONArray sẽ trả về List<_InternalLinkedHashMap> và tên _InternalLinkedHashMap không extends Map, dù chúng cũng được tổ chức theo hướng <K,V> và lấy V theo K như nhau. Do class _InternalLinkedHashMap có tên bắt đầu bằng dấu _ nên bạn không trực tiếp gọi tên nó được, vì vậy, bạn chỉ cần cast phần response.body về List<dynamic>, chí ít là hiện tại khi bạn thực hiện theo hướng làm của tôi cho dễ dàng. Cuối bài tôi sẽ nói sơ lược về hướng đi bài bản.

3. Thêm thư viện:

Có một điều khá phiền phức khi viết app cho Flutter là việc dùng http lại cần dùng thư viện ngoài. Nếu bạn đã đọc về bài viết trước của tôi, bạn biết là cần thêm thư viện http vào tập tin pubspec.yaml và cho get dependencies (tương tự như gradle sync trong Android):

4. Điều chỉnh giao diện:

Đầu tiên, chúng ta sẽ tạo một biến List<dynamic> data là một field member trong _MyHomePageState và sau đó sẽ tận dụng body của Scaffold trong phần Widget build(BuildContext). Ngoài ra, tôi đặt thêm một biến kUrl chính là endpoint của chúng ta cho dễ thao tác:

Tôi chỉ giải thích code là mỗi row của ListView sẽ gồm 2 Text. Text đầu tiên chứa title (tương ứng “sunt aut facere repellat provident occaecati excepturi optio reprehenderit” của phần tử đầu tiên), và Text thứ hai chứa body (tương ứng “quia et suscipit\nsuscipit recusandae consequuntur expedita et cum” của phần tử đầu tiên). Tôi có thêm một số style để bạn dễ phân biệt chúng.

5. Gửi request và xử lí response:

Bạn cần import thư viện http vào, và tôi tạm đặt “thừa số chung” cho cả cái bộ thư viện dart trên là http. Như trong bài trước, tôi có hướng dẫn các bạn dùng http.get(String url) để gửi request. Dart Future<T> sẽ return chính T khi đi kèm với await, hoặc T sẽ nằm trong .then nếu không dùng await, vì vậy bạn có thể dùng await nếu thích. Ở đây tôi dùng .then:

Vậy, câu hỏi được đặt ra là gọi block trên ở đâu? Bạn có thể gọi ngay trước build(BuildContext)#return. Tuy nhiên, bạn cần lưu ý là hàm build(BuildContext) này sẽ được chạy trong vòng lặp, sẽ lặp suốt quá trình mà bạn nhìn thấy MyHomePage. Do đó, nó sẽ liên tục gửi request lên endpoint trên. Vì vậy, bạn chỉ cần và nên gửi request khi data trong trạng thái null mà thôi, tức là:

6. Tổng hợp:

Dưới đây là phần code của _MyHomePageState. Các phần khác trong main.dart đều được giữ nguyên hiện trạng vì chúng ta đã thay đổi những gì cần thay đổi rồi.

Và như vậy, chúng ta đã hoàn thành một ứng dụng nho nhỏ nhưng có võ, cho kết quả tương tự như ảnh bên dưới. Thực sự, tôi cho rằng phần code này nhẹ nhàng hơn so với Android và iOS Sdk. Vì vậy, nếu bạn không sử dụng nhiều native platform APIs, Flutter là một lựa chọn đáng cân nhắc.

Flutter_LIstView_getDataFromInternet

7. Cách “bài bản”

Cách này dành cho những “đồng chí” nào nặng lòng về OOP. Bạn có thể đặt một class Post với nội dung như sau:

Và theo hướng tư duy đó, biến data sẽ thuộc về class List<Post>. Đối với cách làm này, bạn chỉ cần thay đổi phần code trong setState như sau:

Hoặc nếu bạn muốn “nhồi nhét” vào cùng một dòng với hàm List#map

Kết quả sẽ cho ra tương tự. Chúc các bạn vui vẻ và thành công.

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.