- vừa được xem lúc

MVVM trong Flutter

0 0 122

Người đăng: Tran Van Tan

Theo Viblo Asia

Flutter là một cross-platform framework cho phép bạn viết các ứng dụng iOS và Android bằng một codebase duy nhất.

Mặc định, các ứng dụng Flutter không sử dụng bất kỳ design pattern cụ thể nào. Điều này có nghĩa là chúng ta cần chịu trách nhiệm lựa chọn và triển khai một design pattern phù hợp với nhu cầu của mình. Trong bài viết này chúng ta sẽ đi vào triển khai mô hình MVVM trong một ứng dụng Flutter.

MVVM là gì?

Nhìn vào định nghĩa của MVVM, nó là chữ viết tắt của ba từ là Model, View và View Model. Ý tưởng cơ bản của MVVM là xây dựng một View model có thể cung cấp dữ liệu cho View.

Nhìn vào sở đồ trên bạn có thể thấy ViewModel chiếm vị trí trung tâm. Nó sẽ gửi và nhận dữ liệu từ model và gửi cho view, đông thời cũng quan sát sự thay đổi của dữ liệu xảy ra ở View và phản hồi với model tương ứng. Chúng ta sẽ xem xét từng thành phần riêng lẻ để hiểu rõ hơn về chúng

Model

Đây là thành phần quản lý toàn bộ các cơ sở dữ liệu (database) của ứng dụng. Đồng thời Model cũng chứa các lớp mô tả business logic và định nghĩa business rules cho dữ liệu (cách mà dữ liệu sẽ được thay đổi và sử dụng).

ViewModel

ViewModel là trung gian giữa View và Model, nó nhận các sự kiện của người dùng và gửi yêu cầu đó đến Model để lấy data. Khi Model có data và trả lại cho ViewModel, ViewModel sẽ thông báo data đó đến View. ViewModel có thể được sử dụng bởi View, hay một ViewModel có thể cung cấp dữ liệu cho nhiều View khác nhau.

View

View là nơi người dùng tương tác với các widget được hiển thị trên màn hình. Các sự kiện người dùng này sẽ tạo ra một số action chuyển đến ViewModel để xử lý. Khi Viewmodel xử lý xong action nó sẽ cập nhật lại View.

Ví dụ

Chúng ta sẽ tạo một ứng ứng dụng đơn giản dựa trên các nguyên tắc của mô hình MVVM kết hợp với provider để mọi người có cái nhìn trực quan hơn. Ứng dụng sẽ tình kiếm tất cảc các bộ phim liên quan với từ khóa đã nhập vào.

Triển khai web service

Sử dụng API của OMDb để tìm phim. Hãy đăng ký một tài khoản trên đó để có api_key của riêng mình. Tạo 1 calss Webservice để call api và parse dữ liệu (trong ví dụ này dụng package http để call api)

import 'package:movies_app/models/movie.dart';
import 'package:http/http.dart' as http; class Webservice { Future<List<Movie>> fetchMovies(String keyword) async { final url = "http://www.omdbapi.com/?s=$keyword&apikey=YOURAPIKEYHERE"; final response = await http.get(url); if(response.statusCode == 200) { final body = jsonDecode(response.body); final Iterable json = body["Search"]; return json.map((movie) => Movie.fromJson(movie)).toList(); } else { throw Exception("Unable to perform request!"); } }
}

Model Movie như sau:

class Movie { final String title; final String poster; Movie({this.title, this.poster}); factory Movie.fromJson(Map<String, dynamic> json) { return Movie( title: json["Title"], poster: json["Poster"] ); } }

Movie chỉ đơn giản bao gồm một title và một poster. Nó cũng cung cấp 1 hàm fromJson, cho phép chúng ta tạo đối tượng Movie từ JSON response.

Chúng ta đã sử đụng thuật ngữ model để define Movie object.

Chúng ta đã có dữ liệu, việc cần làm tiếp theo là hiển thị dữ liệu này lên màn hình. Trước khi chuyển sang việc tạo UI, ta cần tạo ViewModel, nó sẽ chịu trách nghiệm cung cấp data cho View.

Triển khai class ViewModels

Có 2 ViewModel sẽ được implement.

  • MoviesListViewModel, sẽ đại diện cho toàn bộ màn hình kết quả tim kiếm.
  • MovieViewModel, sẽ đại diện cho một bộ phim riêng lẻ.
class MovieListViewModel extends ChangeNotifier { List<MovieViewModel> movies = List<MovieViewModel>(); Future<void> fetchMovies(String keyword) async { final results = await Webservice().fetchMovies(keyword); this.movies = results.map((item) => MovieViewModel(movie: item)).toList(); notifyListeners(); } } class MovieViewModel { final Movie movie; MovieViewModel({this.movie}); String get title { return this.movie.title; } String get poster { return this.movie.poster; } }

MovieListViewModel kế thừa từ ChangeNotifier. ChangeNotifier cho phép chúng ta thông báo đến View rằng data có sự thay đổi để View update lại UI của nó

Hiển thị movies

class MovieListPage extends StatefulWidget {  _MovieListPageState createState() => _MovieListPageState(); } class _MovieListPageState extends State<MovieListPage> { final TextEditingController _controller = TextEditingController();  Widget build(BuildContext context) { final vm = Provider.of<MovieListViewModel>(context); return Scaffold( appBar: AppBar( title: Text("Movies") ), body: Container( padding: EdgeInsets.all(10), width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: Column(children: <Widget>[ Container( padding: EdgeInsets.only(left: 10), decoration: BoxDecoration( color: Colors.grey, borderRadius: BorderRadius.circular(10) ), child: TextField( controller: _controller, onSubmitted: (value) { if(value.isNotEmpty) { vm.fetchMovies(value); _controller.clear(); } }, style: TextStyle(color: Colors.white), decoration: InputDecoration( hintText: "Search", hintStyle: TextStyle(color: Colors.white), border: InputBorder.none ), ), ), Expanded( child: MovieList(movies: vm.movies)) ]) ) ); }
}

Mỗi khi nhấn submit fetchMovies sẽ tìm tất cả các movies theo từ khóa vào kích hoạt notifyListeners. notifyListeners vs final vm = Provider.of<MovieListViewModel>(context); sẽ khiến hàm build được gọi lại, dữ liệu mới sẽ được hiển thị trên view.

Bạn có thể xem full code ở đây


Nguồn tham khảo: Medium

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 281

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

0 0 207

- vừa được xem lúc

Flutter Animation: Creating medium’s clap animation in flutte Part II

Trong phần 1 mình đã giới thiệu với các bạn cơ bản về Animation trong Flutter. Score Widget Size Animation.

0 0 64

- vừa được xem lúc

Flutter - GetX - Using GetConnect to handle API request (Part 4)

Giới thiệu. Xin chào các bạn, lại là mình với series về GetX và Flutter.

0 0 351

- vừa được xem lúc

StatefulWidget và StatelessWidget trong Flutter

I. Mở đầu. Khi các bạn build một ứng dụng với Flutter thì Widgets là thứ không thể thiếu đúng không ạ. Và 2 loại Widget không thể thiếu đó là StatefullWidget và StatelessWidget.

0 0 143

- vừa được xem lúc

Tìm hiểu về Riverpod - Provider nhưng không hắn :v

Trong Flutter có rất nhiều các quản lý state: Provider, Bloc, GetX, Redux,... khó mà nói cái nào tốt hơn cái nào. Tuy nhiên nếu bạn đã làm quen với Provider thì không ngại để tìm hiểu thêm về Riverpod. Một bản nâng cấp của Provider. Nếu bạn để ý thì cái tên "Riverpod" là các chữ cái của "Provider" đ

0 0 67