joaopaulofcc

[CC] [DBAPI] main.dart

Nov 25th, 2020
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Dart 27.45 KB | None | 0 0
  1. // Importa bibliotecas.
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/widgets.dart';
  4. import 'controls/apiClient.dart';
  5. import 'controls/databaseClient.dart';
  6. import 'models/dog.dart';
  7.  
  8. void main() => runApp(MyApp());
  9.  
  10. class MyApp extends StatelessWidget {
  11.   @override
  12.   Widget build(BuildContext context) {
  13.     return MaterialApp(
  14.       theme: ThemeData(
  15.         primarySwatch: Colors.cyan,
  16.       ),
  17.       home: DogPage(),
  18.     );
  19.   }
  20. }
  21.  
  22. class DogPage extends StatefulWidget {
  23.   @override
  24.   _DogPageState createState() => _DogPageState();
  25. }
  26.  
  27. class _DogPageState extends State<DogPage> {
  28.   // Isso identificará de forma exclusiva o formulário com o qual estamos
  29.   // trabalhando e nos permitirá validar o formulário posteriormente
  30.   final GlobalKey<FormState> _formStateKey = GlobalKey<FormState>();
  31.  
  32.   // Utilizado para armazenar o context e assim utilizarmos os snackbars
  33.   // em qualquer lugar da aplicação.
  34.   final _scaffoldKey = GlobalKey<ScaffoldState>();
  35.  
  36.   // Armazenará a lista de cachorros lidos do banco.
  37.   Future<List<Dog>> dogs;
  38.  
  39.   // Lista auxiliares que serão utilizadas para armazenar dados da API e do BD.
  40.   List<Dog> dogsFromApi;
  41.   List<Dog> dogsFromDb;
  42.  
  43.   // Armazenarão os dados de um objeto que será manipulado no app (ao criar ou atualizar).
  44.   String _dogId;
  45.   String _dogName;
  46.   int _dogAge;
  47.  
  48.   // Indica se a operação é de update (true) ou insert (false).
  49.   bool isUpdate = false;
  50.  
  51.   // Armazena o id do cachorro que será atualizado em uma operação de update.
  52.   String dogIdForUpdate;
  53.  
  54.   // Armazena objeto para manipular o banco.
  55.   DatabaseClient db;
  56.  
  57.   // Armazena objeto para manipular a API.
  58.   ApiClient api;
  59.  
  60.   // Controladores que vão manipular os textos dos TextEdits.
  61.   final _dogIdController = TextEditingController();
  62.   final _dogNameController = TextEditingController();
  63.   final _dogAgeController = TextEditingController();
  64.  
  65.   // Executada ao inicializar o aplicativo.
  66.   @override
  67.   void initState() {
  68.     super.initState();
  69.     // Instancia objeto da classe DatabaseClient.
  70.     db = DatabaseClient();
  71.     // Instancia objeto da classe ApiClient.
  72.     api = ApiClient();
  73.     // Chama método para abrir o banco.
  74.     openDatabase();
  75.   }
  76.  
  77.   // Método que chama a função open da classe "databaseClient"
  78.   openDatabase() async {
  79.     await db.open();
  80.     // Chama método para atualizar a listagem de cachorros já cadastrados no banco.
  81.     await refreshDogList();
  82.   }
  83.  
  84.   // Método que atualiza a listagem de cachorros já cadastrados no banco.
  85.   refreshDogList() {
  86.     setState(() {
  87.       dogs = db.getDogs();
  88.     });
  89.   }
  90.  
  91.   // Método responsável por comandar o envio de um objeto Dog para a API.
  92.   Future<Dog> uploadOnApi(dog) async {
  93.     // Tenta fazer a operação.
  94.     try {
  95.       Dog newDog = await api.insertDog(dog);
  96.  
  97.       // Mostra snackbar de sucesso.
  98.       final snackBar = SnackBar(
  99.         content: Text('Dados enviados com sucesso para a API!'),
  100.         duration: Duration(milliseconds: 500),
  101.         backgroundColor: Colors.green,
  102.       );
  103.  
  104.       _scaffoldKey.currentState.showSnackBar(snackBar);
  105.  
  106.       // Ao receber o dado, a API retorna o objeto que foi salvo nela,
  107.       // incluindo o id que ela utilizou (auto incremento), assim poderemos pegar
  108.       // este objeto e salvar posteriormente no BD.
  109.       return newDog;
  110.     }
  111.     // Caso tenha erro ao realizar a operação.
  112.     catch (error) {
  113.       // Mostra snackbar de erro.
  114.       final snackBar = SnackBar(
  115.         content: Text('Erro ao enviar dado para a API!'),
  116.         duration: Duration(milliseconds: 500),
  117.         backgroundColor: Colors.red,
  118.       );
  119.       _scaffoldKey.currentState.showSnackBar(snackBar);
  120.  
  121.       return null;
  122.     }
  123.   }
  124.  
  125.   // Método responsável por comandar o envio de um objeto Dog para o BD.
  126.   uploadOnDb(dog) async {
  127.     // Tenta fazer a operação.
  128.     try {
  129.       await db.insertDog(dog);
  130.       final snackBar = SnackBar(
  131.         content: Text('Dados enviados com sucesso para a BD!'),
  132.         duration: Duration(milliseconds: 500),
  133.         backgroundColor: Colors.green,
  134.       );
  135.       _scaffoldKey.currentState.showSnackBar(snackBar);
  136.     }
  137.     // Caso tenha erro ao realizar a operação.
  138.     catch (error) {
  139.       // Mostra snackbar de erro.
  140.       final snackBar = SnackBar(
  141.         content: Text('Erro ao enviar dado para o BD!'),
  142.         duration: Duration(milliseconds: 500),
  143.         backgroundColor: Colors.red,
  144.       );
  145.       _scaffoldKey.currentState.showSnackBar(snackBar);
  146.     }
  147.   }
  148.  
  149.   // Método responsável por comandar a remoção de um objeto Dog na API.
  150.   deleteOnApi(Dog dog) async {
  151.     // Tenta fazer a operação.
  152.     try {
  153.       await api.deleteDog(dog.id);
  154.       final snackBar = SnackBar(
  155.         content: Text('Dado removido com sucesso da API!'),
  156.         duration: Duration(milliseconds: 500),
  157.         backgroundColor: Colors.green,
  158.       );
  159.       _scaffoldKey.currentState.showSnackBar(snackBar);
  160.     }
  161.     // Caso tenha erro ao realizar a operação.
  162.     catch (error) {
  163.       // Mostra snackbar de erro.
  164.       final snackBar = SnackBar(
  165.         content: Text('Erro ao remover dado da API!'),
  166.         duration: Duration(milliseconds: 500),
  167.         backgroundColor: Colors.red,
  168.       );
  169.       _scaffoldKey.currentState.showSnackBar(snackBar);
  170.     }
  171.   }
  172.  
  173.   // Método responsável por comandar a remoção de um objeto Dog no BD.
  174.   deleteOnDb(Dog dog) async {
  175.     // Tenta fazer a operação.
  176.     try {
  177.       await db.deleteDog(dog.id);
  178.       final snackBar = SnackBar(
  179.         content: Text('Dado removido com sucesso do BD!'),
  180.         duration: Duration(milliseconds: 500),
  181.         backgroundColor: Colors.green,
  182.       );
  183.       _scaffoldKey.currentState.showSnackBar(snackBar);
  184.     }
  185.     // Caso tenha erro ao realizar a operação.
  186.     catch (error) {
  187.       // Mostra snackbar de erro.
  188.       final snackBar = SnackBar(
  189.         content: Text('Erro ao remover dado do BD!'),
  190.         duration: Duration(milliseconds: 500),
  191.         backgroundColor: Colors.red,
  192.       );
  193.       _scaffoldKey.currentState.showSnackBar(snackBar);
  194.     }
  195.   }
  196.  
  197.   // Método responsável por comandar a atualização de um objeto Dog na API.
  198.   Future<Dog> updateOnApi(Dog dog) async {
  199.     // Tenta fazer a operação.
  200.     try {
  201.       Dog newDog = await api.updateDog(dog);
  202.  
  203.       // Mostra snackbar de sucesso.
  204.       final snackBar = SnackBar(
  205.         content: Text('Dado atualizado com sucesso da API!'),
  206.         duration: Duration(milliseconds: 500),
  207.         backgroundColor: Colors.green,
  208.       );
  209.       _scaffoldKey.currentState.showSnackBar(snackBar);
  210.  
  211.       // Ao receber o dado, a API retorna o objeto que foi atualizado nela,
  212.       // incluindo o id que ela utilizou (auto incremento), assim poderemos pegar
  213.       // este objeto e atualizar posteriormente também no BD.
  214.       return newDog;
  215.     }
  216.     // Caso tenha erro ao realizar a operação.
  217.     catch (error) {
  218.       // Mostra snackbar de erro.
  219.       final snackBar = SnackBar(
  220.         content: Text('Erro ao atualizar dado na API!'),
  221.         duration: Duration(milliseconds: 500),
  222.         backgroundColor: Colors.red,
  223.       );
  224.       _scaffoldKey.currentState.showSnackBar(snackBar);
  225.  
  226.       return null;
  227.     }
  228.   }
  229.  
  230.   // Método responsável por comandar a atualização de um objeto Dog no BD.
  231.   updateOnDb(Dog dog) async {
  232.     // Tenta fazer a operação.
  233.     try {
  234.       await db.updateDog(dog);
  235.       final snackBar = SnackBar(
  236.         content: Text('Dado atualizado com sucesso do BD!'),
  237.         duration: Duration(milliseconds: 500),
  238.         backgroundColor: Colors.green,
  239.       );
  240.       _scaffoldKey.currentState.showSnackBar(snackBar);
  241.     }
  242.     // Caso tenha erro ao realizar a operação.
  243.     catch (error) {
  244.       // Mostra snackbar de erro.
  245.       final snackBar = SnackBar(
  246.         content: Text('Erro ao atualizar dado no BD!'),
  247.         duration: Duration(milliseconds: 500),
  248.         backgroundColor: Colors.red,
  249.       );
  250.       _scaffoldKey.currentState.showSnackBar(snackBar);
  251.     }
  252.   }
  253.  
  254.   // Método responsável por solicitar o download de todos os dados da API e então
  255.   // atualizar a base de dados local.
  256.   downloadFromApi() async {
  257.     // Variável utilizada para indicar se ocorreu erros nesta operação.
  258.     var errorDownload = false;
  259.  
  260.     // Tenta fazer a leitura dos dados da API.
  261.     try {
  262.       dogsFromApi = await api.getDogs();
  263.  
  264.       // Mostra snackbar de sucesso.
  265.       final snackBar = SnackBar(
  266.         content: Text('Dados lidos com sucesso na API!'),
  267.         duration: Duration(milliseconds: 500),
  268.         backgroundColor: Colors.green,
  269.       );
  270.       _scaffoldKey.currentState.showSnackBar(snackBar);
  271.     }
  272.     // Caso dê erro (ex: url incorreta ou sem internet)
  273.     catch (erro) {
  274.       // Indica que ocorreu um erro na variável.
  275.       errorDownload = true;
  276.  
  277.       // Mostra snackbar de erro.
  278.       final snackBar = SnackBar(
  279.         content: Text('Erro ao comunicar com a API!'),
  280.         duration: Duration(milliseconds: 500),
  281.         backgroundColor: Colors.red,
  282.       );
  283.       _scaffoldKey.currentState.showSnackBar(snackBar);
  284.     }
  285.  
  286.     // Se a operação de busca de todos os dados da API foi feita sem erros.
  287.     if (errorDownload == false) {
  288.       // Solicita remoção de todos os dados do BD.
  289.       await db.deleteAllDogs();
  290.       // Solicita escrita de todos os dados lidos na API no BD.
  291.       await db.insertDogs(dogsFromApi);
  292.       // Atualiza lista Dogs para exibição no grid.
  293.       refreshDogList();
  294.  
  295.       // Mostra snackbar de sucesso.
  296.       final snackBar = SnackBar(
  297.         content: Text('Dados armazenados com sucesso no BD!'),
  298.         duration: Duration(milliseconds: 500),
  299.         backgroundColor: Colors.green,
  300.       );
  301.       _scaffoldKey.currentState.showSnackBar(snackBar);
  302.     }
  303.   }
  304.  
  305.   // Método que vai construir a interface do app.
  306.   @override
  307.   Widget build(BuildContext context) {
  308.     return Scaffold(
  309.       key: _scaffoldKey,
  310.       // Cria AppBar
  311.       appBar: AppBar(title: Text('App Dog'), actions: <Widget>[
  312.         // Adiciona botão para download dos dados da API.
  313.         Padding(
  314.             padding: EdgeInsets.only(right: 20.0),
  315.             child: GestureDetector(
  316.               onTap: () {
  317.                 // Ao clicar chama método para obtenção de todos os dados da API.
  318.                 downloadFromApi();
  319.               },
  320.               child: Icon(Icons.cloud_download),
  321.             )),
  322.       ]),
  323.  
  324.       // Corpo do app.
  325.       body: Column(
  326.         children: <Widget>[
  327.           // Cria um formulário.
  328.           Form(
  329.             // Atribui a chave para identificar este formulário.
  330.             key: _formStateKey,
  331.             // Indica que a validação dos campos deve ser verificada automaticamente.
  332.             autovalidate: true,
  333.             // Adiciona Padding
  334.             child: Column(
  335.               children: <Widget>[
  336.                 Padding(
  337.                   padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
  338.                   // Adiciona TextForm para inserir o Id do cachorro.
  339.                   child: TextFormField(
  340.                     enabled: false,
  341.                     // Quando o formulário for enviado, salva o valor preenchido em _dogId.
  342.                     onSaved: (value) {
  343.                       _dogId = value;
  344.                     },
  345.                     // Indica quem é o controlador deste TextForm.
  346.                     controller: _dogIdController,
  347.                     // Indica que o teclado padrão deve ser numérico.
  348.                     keyboardType: TextInputType.number,
  349.                     // Personaliza o TextForm
  350.                     decoration: InputDecoration(
  351.                         disabledBorder: new UnderlineInputBorder(
  352.                             borderSide: new BorderSide(
  353.                                 color: Colors.grey,
  354.                                 width: 2,
  355.                                 style: BorderStyle.solid)),
  356.                         // Rótulo do TextForm
  357.                         labelText: "Id do cachorro",
  358.                         // Ícone que será exibido ao lado do TextForm
  359.                         icon: Icon(
  360.                           Icons.vpn_key,
  361.                           color: Colors.grey,
  362.                         ),
  363.                         // Cor de fundo do TextForm
  364.                         fillColor: Colors.white,
  365.                         // Altera a cor da fonte do rótulo
  366.                         labelStyle: TextStyle(
  367.                           color: Colors.grey,
  368.                         )),
  369.                   ),
  370.                 ),
  371.  
  372.                 // Repete passos anteriores, porém agora, para o TextForm do nome.
  373.                 Padding(
  374.                   padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
  375.                   child: TextFormField(
  376.                     validator: (value) {
  377.                       if (value.isEmpty) {
  378.                         return 'Por favor insira o nome do cachorro';
  379.                       }
  380.                       if (value.trim() == "")
  381.                         return "Somente espaço não é válido!";
  382.                       return null;
  383.                     },
  384.                     onSaved: (value) {
  385.                       _dogName = value;
  386.                     },
  387.                     controller: _dogNameController,
  388.                     decoration: InputDecoration(
  389.                         focusedBorder: new UnderlineInputBorder(
  390.                             borderSide: new BorderSide(
  391.                                 color: Colors.cyan,
  392.                                 width: 2,
  393.                                 style: BorderStyle.solid)),
  394.                         labelText: "Nome do cachorro",
  395.                         icon: Icon(
  396.                           Icons.pets,
  397.                           color: Colors.cyan,
  398.                         ),
  399.                         fillColor: Colors.white,
  400.                         labelStyle: TextStyle(
  401.                           color: Colors.cyan,
  402.                         )),
  403.                   ),
  404.                 ),
  405.  
  406.                 // Repete passos anteriores, porém agora, para o TextForm da idade.
  407.                 Padding(
  408.                   padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
  409.                   child: TextFormField(
  410.                     validator: (value) {
  411.                       if (value.isEmpty) {
  412.                         return 'Por favor insira a idade do cachorro';
  413.                       }
  414.                       if (value.trim() == "")
  415.                         return "Somente espaço não é válido!";
  416.                       return null;
  417.                     },
  418.                     onSaved: (value) {
  419.                       _dogAge = int.parse(value);
  420.                     },
  421.                     controller: _dogAgeController,
  422.                     keyboardType: TextInputType.number,
  423.                     decoration: InputDecoration(
  424.                         focusedBorder: new UnderlineInputBorder(
  425.                             borderSide: new BorderSide(
  426.                                 color: Colors.cyan,
  427.                                 width: 2,
  428.                                 style: BorderStyle.solid)),
  429.                         labelText: "Idade do cachorro",
  430.                         icon: Icon(
  431.                           Icons.calendar_today,
  432.                           color: Colors.cyan,
  433.                         ),
  434.                         fillColor: Colors.white,
  435.                         labelStyle: TextStyle(
  436.                           color: Colors.cyan,
  437.                         )),
  438.                   ),
  439.                 ),
  440.               ],
  441.             ),
  442.           ),
  443.  
  444.           // Após o fórmulário, organiza na horizontal os botões de ação.
  445.           Row(
  446.             // Centraliza os botões.
  447.             mainAxisAlignment: MainAxisAlignment.center,
  448.             // Adiciona botões.
  449.             children: <Widget>[
  450.               // Botão de dupla função (Atualizar ou Adicionar).
  451.               RaisedButton(
  452.                 color: Colors.cyan,
  453.                 // Se a operação for de atualização mostra "ATUALIZAR", caso
  454.                 // contrário, mostra "ADICIONAR".
  455.                 child: Text(
  456.                   (isUpdate ? 'ATUALIZAR' : 'ADICIONAR'),
  457.                   style: TextStyle(color: Colors.white),
  458.                 ),
  459.                 // Programa função do clique no botão
  460.                 onPressed: () async {
  461.                   FocusScope.of(context).requestFocus(new FocusNode());
  462.  
  463.                   // Se a operação for de atualização
  464.                   if (isUpdate) {
  465.                     // Verifica se os dados dos TextForms estão válidos.
  466.                     if (_formStateKey.currentState.validate()) {
  467.                       // Se sim, salva os dados nas variáveis.
  468.                       _formStateKey.currentState.save();
  469.                       // Tenta fazer atualização dos dados.
  470.                       try {
  471.                         // Cria objeto Dog com os dados dos campos de formulário.
  472.                         Dog dog = Dog(
  473.                             id: dogIdForUpdate, name: _dogName, age: _dogAge);
  474.  
  475.                         // Solicita primeiro a atualização na API, ela então retornará
  476.                         // um objeto com os dados atualizados nela, em seguida
  477.                         // chama método para atualizar este objeto no banco
  478.                         await updateOnDb(await updateOnApi(dog));
  479.                         // Solicita que a lista Dogs seja atualizada (para o grid).
  480.                         refreshDogList();
  481.                         // Indica que a atualização acabou (assim os botões voltam ao estado de adicionar).
  482.                         setState(() {
  483.                           isUpdate = false;
  484.                         });
  485.                       }
  486.                       // Caso encontre algum erro nas funções acima.
  487.                       catch (error) {
  488.                         print(error);
  489.                         final snackBar = SnackBar(
  490.                           content: Text('Erro ao comunicar com a API!'),
  491.                           duration: Duration(milliseconds: 500),
  492.                           backgroundColor: Colors.red,
  493.                         );
  494.                         _scaffoldKey.currentState.showSnackBar(snackBar);
  495.                       }
  496.                     }
  497.                   }
  498.                   // Caso a operação a ser executada seja a de inserção de um novo dado.
  499.                   else {
  500.                     // Verifica se os dados dos TextForms estão válidos.
  501.                     if (_formStateKey.currentState.validate()) {
  502.                       // Se sim, salva os dados nas variáveis.
  503.                       _formStateKey.currentState.save();
  504.                       // Tenta fazer inserção dos dados.
  505.                       try {
  506.                         // Cria objeto Dog com os dados dos campos de formulário.
  507.                         Dog dog = Dog(id: _dogId, name: _dogName, age: _dogAge);
  508.                         // Solicita primeiro a inserção na API, ela então retornará
  509.                         // um objeto com os dados inseridos nela, em seguida
  510.                         // chama método para inserir este objeto no banco.
  511.                         // Isso é necessário visto que o id é auto_increment na API,
  512.                         // desta maneira o objeto retornado pela API já tem o id correto.
  513.                         await uploadOnDb(await uploadOnApi(dog));
  514.  
  515.                         // Solicita que a lista Dogs seja atualizada (para o grid).
  516.                         refreshDogList();
  517.                       }
  518.                       // Caso encontre algum erro nas funções acima.
  519.                       catch (error) {
  520.                         final snackBar = SnackBar(
  521.                           content: Text('Erro ao comunicar com a API!'),
  522.                           duration: Duration(milliseconds: 500),
  523.                           backgroundColor: Colors.red,
  524.                         );
  525.                         _scaffoldKey.currentState.showSnackBar(snackBar);
  526.                       }
  527.                     }
  528.                   }
  529.                   // Após a atualização ou inserção, limpa os textos dos TextForms
  530.                   _dogIdController.text = '';
  531.                   _dogNameController.text = '';
  532.                   _dogAgeController.text = '';
  533.                 },
  534.               ),
  535.               Padding(
  536.                 padding: EdgeInsets.all(10),
  537.               ),
  538.               // Botão com dupla função: cancelar a atualização ou limpar os campos
  539.               RaisedButton(
  540.                 color: Colors.red,
  541.                 // Se a operação for de atualização mostra "CANCELAR ATUALIZAÇÃO",
  542.                 // caso contrário, mostra "CANCELAR".
  543.                 child: Text(
  544.                   (isUpdate ? 'CANCELAR ATUALIZAÇÃO' : 'LIMPAR'),
  545.                   style: TextStyle(color: Colors.white),
  546.                 ),
  547.                 // Programa o que ocorrerá quando o botão for clicado
  548.                 onPressed: () {
  549.                   // Em ambas as situações limpa os dados dos TextForms
  550.                   _dogIdController.text = '';
  551.                   _dogNameController.text = '';
  552.                   _dogAgeController.text = '';
  553.  
  554.                   setState(() {
  555.                     // Indica que não está ocorrendo mais uma atualização
  556.                     isUpdate = false;
  557.                     // Limpa a variável que armazenaria o id a ser atualizado
  558.                     dogIdForUpdate = null;
  559.                   });
  560.                 },
  561.               ),
  562.             ],
  563.           ),
  564.           const Divider(
  565.             height: 20.0,
  566.           ),
  567.           // Componente que exibirá a listagem com os cachorros cadastrados.
  568.           Expanded(
  569.             // Para saber +: https://tinyurl.com/y44rl6ce
  570.             child: FutureBuilder(
  571.               future: dogs,
  572.               builder: (context, snapshot) {
  573.                 print(snapshot.connectionState);
  574.                 // Caso não exista dados a serem exibidos, mostra uma mensagem
  575.                 if (snapshot.data == null || snapshot.data.length == 0) {
  576.                   return Text('Sem dados para exibir');
  577.                 }
  578.                 // Se o banco tiver retornado dados para exibir, ou seja, dados
  579.                 // cadastrados, chama método para gerar a lista de cachorros e
  580.                 // e posteriormente exibir tal lista na tela.
  581.                 else if (snapshot.hasData) {
  582.                   return generateList(snapshot.data);
  583.                 }
  584.                 // Retorna um widget circular que será apresentado enquanto a
  585.                 // operação de recuperação de dados estiver sendo processada.
  586.                 return CircularProgressIndicator();
  587.               },
  588.             ),
  589.           ),
  590.         ],
  591.       ),
  592.     );
  593.   }
  594.  
  595.   // Método que retorna um widget com a lista de cachorros cadastrados no banco.
  596.   SingleChildScrollView generateList(List<Dog> dogs) {
  597.     return SingleChildScrollView(
  598.       scrollDirection: Axis.vertical,
  599.       child: SingleChildScrollView(
  600.         scrollDirection: Axis.horizontal,
  601.         child: DataTable(
  602.           columns: [
  603.             DataColumn(
  604.               label: Text('ID', style: TextStyle(fontStyle: FontStyle.italic)),
  605.             ),
  606.             DataColumn(
  607.               label:
  608.                   Text('NOME', style: TextStyle(fontStyle: FontStyle.italic)),
  609.             ),
  610.             DataColumn(
  611.               label:
  612.                   Text('IDADE', style: TextStyle(fontStyle: FontStyle.italic)),
  613.             ),
  614.             DataColumn(
  615.               label: Text('DELETAR',
  616.                   style: TextStyle(fontStyle: FontStyle.italic)),
  617.             )
  618.           ],
  619.           // Monta linhas
  620.           rows: dogs
  621.               .map(
  622.                 (dog) => DataRow(
  623.                   cells: [
  624.                     // Célula que exibirá o id do cachorro.
  625.                     DataCell(
  626.                       Text(dog.id.toString()),
  627.                       // Quando o usuário clicar nesta célula ativa a operação
  628.                       // de atualização.
  629.                       onTap: () {
  630.                         setState(() {
  631.                           // Indica que a operação de atualização está ativada
  632.                           isUpdate = true;
  633.                           // Salva o id do objeto apresentado na linha selecionada
  634.                           dogIdForUpdate = dog.id;
  635.                         });
  636.                         // Preenche, com os dados do cachorro selecionado, os TextForms
  637.                         _dogIdController.text = dog.id.toString();
  638.                         _dogNameController.text = dog.name;
  639.                         _dogAgeController.text = dog.age.toString();
  640.                       },
  641.                     ),
  642.                     // Célula que exibirá o nome do cachorro.
  643.                     DataCell(
  644.                       Text(dog.name),
  645.                       onTap: () {
  646.                         setState(() {
  647.                           isUpdate = true;
  648.                           dogIdForUpdate = dog.id;
  649.                         });
  650.                         _dogIdController.text = dog.id.toString();
  651.                         _dogNameController.text = dog.name;
  652.                         _dogAgeController.text = dog.age.toString();
  653.                       },
  654.                     ),
  655.                     // Célula que exibirá a idade do cachorro.
  656.                     DataCell(
  657.                       Text(dog.age.toString()),
  658.                       onTap: () {
  659.                         setState(() {
  660.                           isUpdate = true;
  661.                           dogIdForUpdate = dog.id;
  662.                         });
  663.                         _dogIdController.text = dog.id.toString();
  664.                         _dogNameController.text = dog.name;
  665.                         _dogAgeController.text = dog.age.toString();
  666.                       },
  667.                     ),
  668.                     // Célula que exibirá o botão para deletar uma linha do banco
  669.                     DataCell(
  670.                       IconButton(
  671.                         icon: Icon(Icons.delete),
  672.                         // Coordena a remoção de um dado do grid, API e BD.
  673.                         onPressed: () {
  674.                           // Tenta fazer deleção dos dados.
  675.                           try {
  676.                             // Solicita que o objeto seja removido da API.
  677.                             deleteOnApi(dog);
  678.                             // Solicita que o objeto seja removido do BD.
  679.                             deleteOnDb(dog);
  680.                             // Solicita que a lista Dogs seja atualizada (para o grid).
  681.                             refreshDogList();
  682.                           }
  683.                           // Caso encontre algum erro nas funções acima.
  684.                           catch (error) {
  685.                             final snackBar = SnackBar(
  686.                               content: Text('Erro ao comunicar com a API!'),
  687.                               duration: Duration(milliseconds: 500),
  688.                               backgroundColor: Colors.red,
  689.                             );
  690.                             _scaffoldKey.currentState.showSnackBar(snackBar);
  691.                           }
  692.                         },
  693.                       ),
  694.                     ),
  695.                   ],
  696.                 ),
  697.               )
  698.               .toList(),
  699.         ),
  700.       ),
  701.     );
  702.   }
  703. }
  704.  
Add Comment
Please, Sign In to add comment