Bom dia a todos! Após os três primeiros artigos, espero que este seja igualmente útil.
Hoje vou tentar explicar o padrão MVC em uma linguagem simples.
E claro que vou mostrar tudo na prática!
Vai!
Nosso plano
Parte 1 - introdução ao desenvolvimento, primeiro apêndice, conceito de estado;
Parte 2 - arquivo pubspec.yaml e usando flutter na linha de comando;
Parte 3 - BottomNavigationBar e Navigator;
Parte 4 (artigo atual) - MVC. Usaremos esse padrão específico como um dos mais simples;
Parte 5 - pacote http. Criação da classe Repositório, primeiras solicitações, listagem de postagens;
Parte 6 - Trabalhar com imagens, exibir imagens em forma de grade, receber imagens da rede, adicionar as suas ao aplicativo;
Parte 7 - Criando seu próprio tema, adicionando fontes personalizadas e animações;
Parte 8 - Um pouco sobre testes;
Por que MVC e outros princípios arquitetônicos?
Talvez, a princípio, seja completamente incompreensível para iniciantes com que propósito usar os princípios arquitetônicos, porque sem eles é bom.
Por que complicar as coisas?
Os motivos mais convincentes:
Complexidade do código - quando você tem um pequeno aplicativo com uma ou duas telas, seja Flutter ou um aplicativo Android / iOS nativo, provavelmente você pode passar sem entender os princípios da arquitetura. Outra coisa é quando o projeto tem um tamanho decente, você não pode prescindir de regras e princípios uniformes.
A complexidade da tarefa - por exemplo: você precisa implementar a alternância entre 3, 5 ou até 10 tópicos (talvez a tarefa não seja comum). Sem um entendimento claro da arquitetura, isso não é tão fácil de fazer.
Complexidade de suporte - se você está desenvolvendo um grande projeto comercial, diga: Um portal de uma cidade, combinado com vários serviços (mapa, hotéis, etc.), você deve ter pelo menos uma equipe. Cada membro da equipe deve agir de forma coordenada. E para agir harmoniosamente, você precisa entender o código de outra pessoa. Sem uma abordagem única para todos, sua equipe estará no caos e o sistema entrará em colapso.
Esses são os motivos mais comuns em minha opinião.
Além disso, uma boa arquitetura de aplicativo coloca as coisas em ordem na cabeça do programador :)
Qual é a essência do 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 .
.
! .
: