Good day everyone! After the first three articles, I hope you find this one just as useful.
Today I will try to explain the MVC pattern in simple language.
And of course I will show everything in practice!
Go!
Our plan
Part 1 - introduction to development, first appendix, concept of state;
Part 2 - pubspec.yaml file and using flutter on the command line;
Part 3 - BottomNavigationBar and Navigator;
Part 4 (current article) - MVC. We will use this particular pattern as one of the simplest;
Part 5 - http package. Creation of the Repository class, first requests, listing of posts;
Part 6 - Working with pictures, displaying pictures in the form of a grid, receiving pictures from the network, adding your own to the application;
Part 7 - Creating your own theme, adding custom fonts and animations;
Part 8 - A little about testing;
Why MVC and other architectural principles?
Perhaps at first it is completely incomprehensible to beginners for what purpose to use architectural principles, because without them it is good.
Why complicate things?
The most compelling reasons:
Complexity of the code - when you have a small application with one or two screens, be it Flutter or a native Android / iOS application, you can probably do without understanding the principles of architecture. Another thing is when the project has a decent size, you cannot do without uniform rules and principles.
The complexity of the task - for example: you need to implement switching between 3, 5 or even 10 topics (perhaps the task is not common). Without a clear understanding of the architecture, this is not so easy to do.
Complexity of support - if you are developing a huge commercial project, say: A portal of a city, combined with various services (map, hotels, etc.), you should at least have a team. Each team member must act in a coordinated manner. And in order to act harmoniously, you need to understand someone else's code. Without some kind of unified approach, your team will be chaos and the system will collapse.
These are the most common reasons in my opinion.
Also, a good application architecture puts things in order in the programmer's head :)
What is the essence of MVC?
MVC (Model - View - Controller) :
(Model) , . . : . , . , ( ). ( , , ). , - Dart, : Pony
(View), Flutter (, , ), . View . ( , ..). , , . , - : Text, Scaffold, AppBar, ListView .
(Controller) ( ) . - . . , , , : HomeController
MVC
.
Flutter pub-, II pubspec.yaml
:
# dependencies: flutter: sdk: flutter # pub- # # flutter_staggered_grid_view: ^0.4.0 # # MVC # Flutter mvc_pattern: ^7.0.0 # , # http # http: ^0.13.3
pub get
:
flutter pub get
Android Studio ( Flutter commands):
MVC.
:
:
, (View) , .
)
controllers
home_controller.dart
:
import 'package:flutter/material.dart';
import 'package:mvc_pattern/mvc_pattern.dart';
import '../models/tab.dart';
// mvc_pattern
// ControllerMVC,
// setState
class HomeController extends ControllerMVC {
//
static HomeController _this;
static HomeController get controller => _this;
// factory
// HomeController
//
// Singleton
//
// HomeController
factory HomeController() {
if (_this == null) _this = HomeController._();
return _this;
}
HomeController._();
// GlobalKey ,
//
// ,
// NavigatorState - Navigator
// _ ,
// private ,
// _navigatorKeys
final _navigatorKeys = {
TabItem.POSTS: GlobalKey<NavigatorState>(),
TabItem.ALBUMS: GlobalKey<NavigatorState>(),
TabItem.TODOS: GlobalKey<NavigatorState>(),
};
// get getter
// _navigatorKeys,
//
// ( )
Map<TabItem, GlobalKey> get navigatorKeys => _navigatorKeys;
//
var _currentTab = TabItem.POSTS;
//
TabItem get currentTab => _currentTab;
//
// selectTab
// HomePage
// , mvc_pattern
// setState
// ,
void selectTab(TabItem tabItem) {
setState(() => _currentTab = tabItem);
}
}
HomePage.dart
:
import 'package:flutter/material.dart';
import 'package:mvc_pattern/mvc_pattern.dart';
import '../../models/tab.dart';
import '../../controllers/home_controller.dart';
import 'bottom_navigation.dart';
import 'tab_navigator.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
//
// StateMVC mvc_pattern
class _HomePageState extends StateMVC {
//
HomeController _con;
// super StateMVC
//
_HomePageState() : super(HomeController()) {
//
_con = HomeController.controller;
}
//
// currentTab selectTab
//
@override
Widget build(BuildContext context) {
// WillPopScope
// Back
return WillPopScope(
// back
// :
// ()
// Back,
//
// : c , ,
//
onWillPop: () async {
if (_con.currentTab != TabItem.POSTS) {
if (_con.currentTab == TabItem.TODOS) {
_con.selectTab(TabItem.ALBUMS);
} else {
_con.selectTab(TabItem.POSTS);
}
return false;
} else {
return true;
}
},
child: Scaffold(
// Stack
// ,
// ,
body: Stack(children: <Widget>[
_buildOffstageNavigator(TabItem.POSTS),
_buildOffstageNavigator(TabItem.ALBUMS),
_buildOffstageNavigator(TabItem.TODOS),
]),
// MyBottomNavigation
bottomNavigationBar: MyBottomNavigation(
currentTab: _con.currentTab,
onSelectTab: _con.selectTab,
),
),);
}
// - ,
Widget _buildOffstageNavigator(TabItem tabItem) {
return Offstage(
// Offstage :
//
// ,
offstage: _con.currentTab != tabItem,
// TabNavigator
child: TabNavigator(
navigatorKey: _con.navigatorKeys[tabItem],
tabItem: tabItem,
),
);
}
}
, HomePage HomeController
.
! .
Flutter
Flutter Flutter StatefulWidget
'.
.
.
, MVC .
.
! .
: