Bonne journée tout le monde! Après les trois premiers articles, j'espère que celui-ci vous sera tout aussi utile.
Aujourd'hui, je vais essayer d'expliquer le modèle MVC dans un langage simple.
Et bien sûr, je vais tout montrer en pratique!
Va!
Notre plan
Partie 1 - introduction au développement, première annexe, notion d'état ;
Partie 2 - fichier pubspec.yaml et utilisation de flutter sur la ligne de commande ;
Partie 3 - BottomNavigationBar et Navigator ;
Partie 4 (article actuel) - MVC. Nous utiliserons ce modèle particulier comme l'un des plus simples ;
Partie 5 - paquet http. Création de la classe Repository, premières demandes, listing des posts ;
Partie 6 - Travailler avec des images, afficher des images sous forme de grille, recevoir des images du réseau, ajouter les vôtres à l'application ;
Partie 7 - Création de votre propre thème, ajout de polices et d'animations personnalisées ;
Partie 8 - Un peu sur les tests ;
Pourquoi MVC et d'autres principes architecturaux ?
Peut-être, au début, est-il complètement incompréhensible pour les débutants dans quel but utiliser les principes architecturaux, car sans eux, c'est bien.
Pourquoi compliquer les choses ?
Les raisons les plus convaincantes :
Complexité du code - lorsque vous avez une petite application avec un ou deux écrans, que ce soit Flutter ou une application native Android / iOS, vous pouvez probablement vous passer de comprendre les principes de l'architecture. Une autre chose est que lorsque le projet a une taille décente, vous ne pouvez pas vous passer de règles et de principes uniformes.
La complexité de la tâche - par exemple : vous devez implémenter la commutation entre 3, 5 ou même 10 sujets (peut-être que la tâche n'est pas courante). Sans une compréhension claire de l'architecture, ce n'est pas si facile à faire.
Complexité du support - si vous développez un énorme projet commercial, disons : Un portail d'une ville, combiné à divers services (plan, hôtels, etc.), vous devriez au moins avoir une équipe. Chaque membre de l'équipe doit agir de manière coordonnée. Et pour agir harmonieusement, il faut comprendre le code de quelqu'un d'autre. Sans approche unique, votre équipe sera dans le chaos et le système s'effondrera.
Ce sont les raisons les plus courantes à mon avis.
Aussi, une bonne architecture applicative met les choses en ordre dans la tête du programmeur :)
Quelle est l'essence du 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 .
.
! .
: