{"id":6062,"date":"2022-04-27T19:20:00","date_gmt":"2022-04-27T19:20:00","guid":{"rendered":"https:\/\/cloudsurfers.it\/?p=6062"},"modified":"2022-04-27T19:20:01","modified_gmt":"2022-04-27T19:20:01","slug":"sviluppare-applicazione-flutter-parte-3","status":"publish","type":"post","link":"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-3\/","title":{"rendered":"Sviluppare un\u2019applicazione Flutter \u2013 Parte 3"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"400\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/cover-2.png\" alt=\"\" class=\"wp-image-6063\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/cover-2.png 800w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/cover-2-300x150.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/cover-2-768x384.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure><\/div>\n\n\n\n<p>Terza parte della serie in cui stiamo realizzando un&#8217;applicazione <strong>Flutter <\/strong>multipiattaforma da zero, facendolo passo passo.<\/p>\n\n\n\n<p>Fino ad ora, nelle parti precedenti, abbiamo sviluppato un&#8217;app multilingua, integrata ad uno strato API Web. Potete trovare la <a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-1\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">prima<\/a> e la <a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">seconda <\/a>parte della serie qui sul sito se non le aveste gi\u00e0 lette.<\/p>\n\n\n\n<p>Il codice sorgente, inoltre, \u00e8 disponibile su <a href=\"https:\/\/github.com\/Cloudsurfers-Dev\/flutter_demo_application_pt3\" data-type=\"URL\" data-id=\"https:\/\/github.com\/Cloudsurfers-Dev\/flutter_demo_application_pt3\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a> separato per articoli.<\/p>\n\n\n\n<p>Ora andremo ad aggiungere al nostro applicativo una nuova pagina con al suo interno una lista di elementi simil applicazione <em>To Do list<\/em> ed integreremo il tutto con una base dati locale SQLite per la storicizzazione delle informazioni.<\/p>\n\n\n\n<p>Iniziamo&#8230;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"pagina-elenco\">Pagina Elenco<\/h3>\n\n\n\n<p>Creiamo un nuovo file <code>list.dart<\/code> all&#8217;interno della cartella contenente le pagine <code>pages<\/code> e popoliamolo come segue:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nimport &#039;package:flutter\/material.dart&#039;;\n\nclass ListPage extends StatefulWidget {\n  const ListPage({Key? key}) : super(key: key);\n\n  @override\n  State&lt;ListPage&gt; createState() =&gt; _ListPage();\n}\n\nclass _ListPage extends State&lt;ListPage&gt; {\n  final List&lt;Widget&gt; items = &#x5B;];\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: const Text(&quot;Elenco&quot;),\n      ),\n      body: ListView.builder(\n        itemCount: items.length,\n        itemBuilder: (context, index) {\n          return items&#x5B;index];\n        },\n      ),\n      floatingActionButton: FloatingActionButton(\n        onPressed: () {\n           print(&quot;On add pressed!&quot;);\n        },\n        child: const Icon(Icons.add),\n      ),\n    );\n  }\n}\n<\/pre><\/div>\n\n\n<p>Pi\u00f9 nel dettaglio, il codice sopra, disegna una pagina <a href=\"https:\/\/material.io\/design\" data-type=\"URL\" data-id=\"https:\/\/material.io\/design\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Material<\/em> <\/a>tramite il <em>Widget<\/em> <a href=\"https:\/\/api.flutter.dev\/flutter\/material\/Scaffold-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/material\/Scaffold-class.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Scaffold<\/strong><\/a>, come abbiamo gi\u00e0 visto precedentemente.<\/p>\n\n\n\n<p>All&#8217;interno del corpo della pagina <em>body <\/em>disegna una lista mediante il <em>Widget<\/em> <strong><a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/ListView-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/widgets\/ListView-class.html\" target=\"_blank\" rel=\"noreferrer noopener\">ListView<\/a><\/strong>, lista popolata poi da un <em>array<\/em> vuoto <strong>items<\/strong>, <em>array<\/em> di <em>Widget<\/em> generici al momento.<\/p>\n\n\n\n<p>La pagina contiene anche un <em><a href=\"https:\/\/api.flutter.dev\/flutter\/material\/FloatingActionButton-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/material\/FloatingActionButton-class.html\" target=\"_blank\" rel=\"noreferrer noopener\">FloatingActionButton<\/a><\/em>, il classico pulsantino in stile <a href=\"https:\/\/material.io\/design\" data-type=\"URL\" data-id=\"https:\/\/material.io\/design\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Material<\/em> <\/a>che si trova normalmente nell&#8217;angolo in basso a destra della pagina (pu\u00f2 essere posizionato anche altrove all&#8217;interno della pagina):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-17.png\" alt=\"\" class=\"wp-image-6065\" width=\"284\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-17.png 400w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-17-300x169.png 300w\" sizes=\"(max-width: 400px) 100vw, 400px\" loading=\"lazy\" \/><\/figure><\/div>\n\n\n\n<p>Ora dobbiamo poter navigare all&#8217;interno di questa nuova pagina. Facciamo si che, effettuando l&#8217;accesso mediante la pagina di login, venga mostrata la pagina elenco (nel caso in cui l&#8217;accesso vada a buon fine).<\/p>\n\n\n\n<p>Spostiamoci quindi all&#8217;interno della pagina di autenticazione, file <code>login.dart<\/code>, pi\u00f9 precisamente all&#8217;interno dell&#8217;evento <code>onPressed: () {}<\/code> dell&#8217;<em><a href=\"https:\/\/api.flutter.dev\/flutter\/material\/ElevatedButton-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/material\/ElevatedButton-class.html\" target=\"_blank\" rel=\"noreferrer noopener\">ElevatedButton<\/a><\/em> di accesso.<\/p>\n\n\n\n<p>Commentiamo l&#8217;operazione di autenticazione tramite API vista nell&#8217;<a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">articolo precedente<\/a> (al momento non \u00e8 necessaria per i nostri test):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n\/*AuthRequest request = AuthRequest(\n  email: _email,\n  password: _password,\n);\n\nGetIt.I&lt;ApiProvider&gt;().auth(request).then((response) {\n  print(response?.token);\n\n  if (response != null &amp;&amp; response.token != null) {\n    setState(() {\n      GetIt.I&lt;AuthProvider&gt;().setToken(response.token);\n    });\n  }\n}).onError((error, stackTrace) {\n  print(error);\n});*\/\n<\/pre><\/div>\n\n\n<p>ed aggiungiamo all&#8217;interno dell&#8217;evento:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n...\nprint(_email);\nprint(_password);\n\n...\n\nNavigator.push(\n  context,\n  MaterialPageRoute(\n    builder: (context) =&gt; const ListPage(),\n  ),\n);\n<\/pre><\/div>\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><em>Le due righe inerenti alla stampa di _email e _password erano gi\u00e0 presenti all&#8217;interno del codice, servono solo per dare un&#8217;indicazione di dove viene inserita la chiamata Navigator API.<\/em><\/p><\/blockquote>\n\n\n\n<p>La chiamata <em><a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/Navigator-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/widgets\/Navigator-class.html\" target=\"_blank\" rel=\"noreferrer noopener\">Navigator API<\/a><\/em> <strong>push<\/strong> permette di navigare verso una &#8220;<em>strada<\/em>&#8221; indicata tramite l&#8217;oggetto <em><a href=\"https:\/\/api.flutter.dev\/flutter\/material\/MaterialPageRoute-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/material\/MaterialPageRoute-class.html\" target=\"_blank\" rel=\"noreferrer noopener\">MaterialPageRoute<\/a><\/em>, in questo caso un&#8217;istanza della classe <strong>ListPage()<\/strong> (la pagina elenco creata sopra).<\/p>\n\n\n\n<p>Avviamo l&#8217;applicazione, menu <code>Run<\/code>, <code>Start Debugging<\/code> (<em>F5<\/em> da tastiera) e facciamo un accesso valido (form validato come abbiamo visto nella <a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-1\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">prima parte<\/a> della guida):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-18.png\" alt=\"\" class=\"wp-image-6066\" width=\"284\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-18.png 400w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-18-134x300.png 134w\" sizes=\"(max-width: 400px) 100vw, 400px\" loading=\"lazy\" \/><\/figure><\/div>\n\n\n\n<p>Come potete vedere, effettuato l&#8217;accesso, ci troveremo davanti una pagina vuota chiamata <em>Elenco<\/em> con un pulsante &#8220;+&#8221; in basso a destra.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><em>La pagina vuota in realt\u00e0 \u00e8 un elenco popolato dalla lista <strong>items<\/strong> che per\u00f2 al momento risulta vuoto.<\/em><\/p><\/blockquote>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"794\" height=\"239\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-19.png\" alt=\"\" class=\"wp-image-6067\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-19.png 794w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-19-300x90.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-19-768x231.png 768w\" sizes=\"auto, (max-width: 794px) 100vw, 794px\" \/><\/figure><\/div>\n\n\n\n<p>Premendo il pulsante &#8220;+&#8221; viene stampata all&#8217;interno della console la stringa <code>On add pressed!<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"database-helper\">Database <em>helper<\/em><\/h3>\n\n\n\n<p>Ora andremo ad implementare un database locale SQLite sviluppando quello che di fatto \u00e8 un <em>provider<\/em> (come abbiamo gi\u00e0 visto lo <a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">scorso articolo<\/a>), che chiameremo per\u00f2 <strong>DatabaseHelper<\/strong>, quindi <em>helper<\/em> per convenzione.<\/p>\n\n\n\n<p>Realizzeremo quindi una tabella di questo tipo:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"tabella-persone\">Tabella Persone<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Campo<\/th><th>Tipo<\/th><th>Note<\/th><\/tr><\/thead><tbody><tr><td>Id<\/td><td><em>INTEGER<\/em><\/td><td>PRIMARY KEY AUTOINCREMENT<\/td><\/tr><tr><td>Nome<\/td><td><em>TEXT<\/em><\/td><td>NOT NULL<\/td><\/tr><tr><td>Cognome<\/td><td><em>TEXT<\/em><\/td><td>NOT NULL<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>tradotto in <em>SQL<\/em> (<em>SQLite<\/em>):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nCREATE TABLE Persone (\n    Id INTEGER PRIMARY KEY AUTOINCREMENT,\n    Nome TEXT NOT NULL,\n    Cognome TEXT NOT NULL\n)\n<\/pre><\/div>\n\n\n<p>Successivamente andremo ad aggiungere i metodi per: inserire, eliminare ed ottenere l&#8217;elenco dei record salvati in tabella.<\/p>\n\n\n\n<p>Vediamo come&#8230;<\/p>\n\n\n\n<p>Per prima cosa dobbiamo installare due nuove librerie, <a href=\"https:\/\/pub.dev\/packages\/sqflite\" data-type=\"URL\" data-id=\"https:\/\/pub.dev\/packages\/sqflite\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>sqflite<\/strong> <\/a>per la gestione della base dati e <a href=\"https:\/\/pub.dev\/packages\/path_provider\" data-type=\"URL\" data-id=\"https:\/\/pub.dev\/packages\/path_provider\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>path_provider<\/strong> <\/a>per ottenere percorsi di sistema che possiamo utilizzare (ad esempio per salvare la nostra base dati).<\/p>\n\n\n\n<p>Aggiungiamo quindi al file di progetto <code>pubspec.yaml<\/code> i due nuovi pacchetti:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\nsqflite: ^2.0.0+3\npath_provider: ^2.0.1\n<\/pre><\/div>\n\n\n<p>salviamo per far eseguire automaticamente il comando <code>flutter pub get<\/code> a <em>VSCode<\/em>.<\/p>\n\n\n\n<p>Al termine, creiamo un nuovo file <code>db_helper.dart<\/code> all&#8217;interno della cartella <code>providers<\/code> e compiliamolo come segue:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nimport &#039;dart:io&#039;;\nimport &#039;package:path\/path.dart&#039;;\nimport &#039;package:sqflite\/sqflite.dart&#039;;\nimport &#039;package:path_provider\/path_provider.dart&#039;;\n\nclass DatabaseHelper {\n  final _databaseName = &quot;database.db&quot;;\n  final _databaseVersion = 1;\n\n  Database? _database;\n\n  Future _initDatabase() async {\n    Directory documentsDirectory = await getApplicationDocumentsDirectory();\n    String path = join(documentsDirectory.path, _databaseName);\n    _database = await openDatabase(path,\n        version: _databaseVersion, onCreate: _onCreate);\n  }\n\n  Future _onCreate(Database db, int version) async {\n    await db.execute(&#039;&#039;&#039;\n          CREATE TABLE Persone (\n            Id INTEGER PRIMARY KEY AUTOINCREMENT,\n            Nome TEXT NOT NULL,\n            Cognome TEXT NOT NULL\n          )\n          &#039;&#039;&#039;);\n  }\n}\n<\/pre><\/div>\n\n\n<p>Vediamolo nel dettaglio&#8230;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nfinal _databaseName = &quot;database.db&quot;;\nfinal _databaseVersion = 1;\n<\/pre><\/div>\n\n\n<p>In questo punto vengono dichiarate ed assegnate due variabili fisse: <em>_databaseName<\/em> che indica il nome che avr\u00e0 il file <em>.db<\/em> creato tramite la libreria <em><a href=\"https:\/\/pub.dev\/packages\/sqflite\" data-type=\"URL\" data-id=\"https:\/\/pub.dev\/packages\/sqflite\" target=\"_blank\" rel=\"noreferrer noopener\">sqflite<\/a><\/em>, e <em>_databaseVersion<\/em> che indica la versione della base dati.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><em>Tramite il metodo <strong>_onCreate()<\/strong> che vedremo utilizzato successivamente, \u00e8 possibile identificare la versione del database, cos\u00ec da gestire il versioning nel caso di aggiornamento della base dati a seguito di un rilascio di una versione successiva dell&#8217;applicazione, per esempio.<\/em><\/p><\/blockquote>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nFuture _initDatabase() async {\n    Directory documentsDirectory = await getApplicationDocumentsDirectory();\n    String path = join(documentsDirectory.path, _databaseName);\n    _database = await openDatabase(path,\n        version: _databaseVersion, onCreate: _onCreate);\n}\n<\/pre><\/div>\n\n\n<p>il metodo asincrono <strong>_initDatabase()<\/strong>, genera il percorso finale che avr\u00e0 la base dati (per fare ci\u00f2 utilizza il metodo <em>getApplicationDocumentsDirectory<\/em> della libreria <em><a href=\"https:\/\/pub.dev\/packages\/path_provider\" data-type=\"URL\" data-id=\"https:\/\/pub.dev\/packages\/path_provider\" target=\"_blank\" rel=\"noreferrer noopener\">path_provider<\/a><\/em> installata in precedenza), in questo caso la cartella <em>Documenti<\/em> dell&#8217;applicazione, e apre un&#8217;istanza database assegnandola alla variabile <strong>_database<\/strong>.<\/p>\n\n\n\n<p>Come argomento del metodo <strong>openDatabase<\/strong> che si occupa dell&#8217;apertura\/creazione della base dati, troviamo il metodo <strong>_onCreate<\/strong>, che esegue semplicemente la query di creazione della tabella o delle tabelle nel caso ne avessimo pi\u00f9 di una.<\/p>\n\n\n\n<p>Mancano ora i metodi per l&#8217;interazione con la tabella <em>Persone<\/em> creata. Prima per\u00f2 abbiamo bisogno di creare un nuovo modello che identifica l&#8217;oggetto <em>Persona<\/em>.<\/p>\n\n\n\n<p>Creiamo quindi un nuovo file <code>persona_db.dart<\/code> all&#8217;interno del percorso <code>models<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nclass PersonaDB {\n  int? id;\n  String? nome;\n  String? cognome;\n\n  PersonaDB({\n    this.id,\n    this.nome,\n    this.cognome,\n  });\n}\n<\/pre><\/div>\n\n\n<p>A differenza degli oggetti creati nel <a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">precedente articolo<\/a>, questo oggetto non necessit\u00e0 n&#8217;\u00e8 di generare un file <em>JSON<\/em>, n&#8217;\u00e8 di essere generato da una sorgente <em>JSON<\/em>. I metodi <strong>toJson()<\/strong> e <strong>fromJson()<\/strong> quindi, non sono presenti.<\/p>\n\n\n\n<p>Creata la classe <em>PersonaDB<\/em>, aggiungiamo i metodi di interazione all&#8217;interno della classe <em>DatabaseHelper<\/em> del file <code>db_helper.dart<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nimport &#039;package:demo_application\/models\/persona_db.dart&#039;;\n\n...\n    \nFuture&lt;int&gt; insertPersona(PersonaDB persona) async {\n    if (_database == null) await _initDatabase();\n    return await _database!.insert(\n      &quot;Persone&quot;,\n      {\n        &quot;Nome&quot;: persona.nome,\n        &quot;Cognome&quot;: persona.cognome,\n      },\n      conflictAlgorithm: ConflictAlgorithm.fail,\n    );\n}\n\nFuture&lt;List&lt;PersonaDB&gt;&gt; listPersone() async {\n    if (_database == null) await _initDatabase();\n    List&lt;PersonaDB&gt; result = &#x5B;];\n    List&lt;Map&lt;String, Object?&gt;&gt; rows = await _database!.query(&quot;Persone&quot;);\n    for (var row in rows) {\n      result.add(PersonaDB(\n        id: row&#x5B;&quot;Id&quot;] as int,\n        nome: row&#x5B;&quot;Nome&quot;] as String,\n        cognome: row&#x5B;&quot;Cognome&quot;] as String,\n      ));\n    }\n    return result;\n}\n\nFuture&lt;int&gt; deletePersona(PersonaDB persona) async {\n    if (_database == null) await _initDatabase();\n    return await _database!.delete(\n      &quot;Persone&quot;,\n      where: &quot;Id = ?&quot;,\n      whereArgs: &#x5B;persona.id],\n    );\n}\n<\/pre><\/div>\n\n\n<p>Il codice risulta molto esplicito, all&#8217;inizio di ogni operazione si verifica se \u00e8 presente o meno l&#8217;istanza <em>_database<\/em> e nel caso si inizializza.<\/p>\n\n\n\n<p>Successivamente vengono utilizzati i metodi <strong>insert<\/strong>, <strong>query<\/strong> e <strong>delete<\/strong> messi a disposizione dalla libreria <a href=\"https:\/\/pub.dev\/packages\/sqflite\" data-type=\"URL\" data-id=\"https:\/\/pub.dev\/packages\/sqflite\" target=\"_blank\" rel=\"noreferrer noopener\"><em>sqflite<\/em> <\/a>per eseguire le varie operazioni.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><em>In fase di inserimento di un nuovo record non \u00e8 specificato il campo Id in quanto la chiave ha la propriet\u00e0 <strong>AUTOINCREMENT<\/strong> che ne aumenta automaticamente il progressivo<\/em>.<\/p><\/blockquote>\n\n\n\n<p>Proseguiamo registrando il <em>provider<\/em> all&#8217;interno del file <code>main.dart<\/code> (<a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">seconda parte<\/a> per la funziona di <em>GetIt<\/em>):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n...\nGetIt.I.registerSingleton&amp;lt;DatabaseHelper&gt;(DatabaseHelper());\n...\n<\/pre><\/div>\n\n\n<p>ed associamo il tutto alla nuova pagina <em>Elenco<\/em> creata.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"elenco-interattivo\">Elenco interattivo<\/h3>\n\n\n\n<p>Torniamo a lavorare sul file <code>list.dart<\/code> ed aggiungiamo all&#8217;interno della classe <em>_ListPage<\/em> due <em>array<\/em> fissi <strong>nomi<\/strong> e <strong>cognomi<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n...\nfinal List&lt;String&gt; nomi = &#x5B;\n    &quot;Matteo&quot;,\n    &quot;Marco&quot;,\n    &quot;Nicola&quot;,\n    &quot;Cristian&quot;,\n    &quot;Elena&quot;,\n    &quot;Barbara&quot;,\n];\n\nfinal List&lt;String&gt; cognomi = &#x5B;\n    &quot;Rossi&quot;,\n    &quot;Verdi&quot;,\n    &quot;Gialli&quot;,\n    &quot;Viola&quot;,\n];\n...\n<\/pre><\/div>\n\n\n<p>Queste due liste ci serviranno successivamente per inserire valori <em>randomici<\/em> all&#8217;interno della tabella <em>Persone<\/em>.<\/p>\n\n\n\n<p>Sempre all&#8217;interno della classe <em>_ListPage<\/em> aggiungiamo un nuovo metodo che chiamiamo <strong>loadList()<\/strong> importando i necessari riferimenti:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nimport &#039;package:get_it\/get_it.dart&#039;;\nimport &#039;package:demo_application\/providers\/db_helper.dart&#039;;\n\n...\n\nFuture loadList() async {\n    GetIt.I&lt;DatabaseHelper&gt;().listPersone().then((persone) {\n      setState(() {\n        items.clear();\n        for (var persona in persone) {\n          items.add(\n            ListTile(\n              title: Text(persona.id.toString() +\n                  &#039; - &#039; +\n                  persona.nome! +\n                  &#039; &#039; +\n                  persona.cognome!),\n              onTap: () {\n                GetIt.I&lt;DatabaseHelper&gt;()\n                    .deletePersona(persona)\n                    .then((value) =&gt; loadList());\n              },\n            ),\n          );\n        }\n      });\n    });\n}\n\n_ListPage() {\n    loadList();\n}\n...\n<\/pre><\/div>\n\n\n<p>Il metodo <strong>loadList()<\/strong> viene anche invocato all&#8217;interno del costruttore, cos\u00ec da caricare la lista alla creazione della pagina.<\/p>\n\n\n\n<p>All&#8217;interno del nuovo metodo viene richiamato il metodo <strong>listPersone()<\/strong>, dell&#8217;istanza <em>DatabaseHelper<\/em>, per ottenere l&#8217;elenco dei record presenti all&#8217;interno della tabella <em>Persone<\/em>.<\/p>\n\n\n\n<p>Elenco di record utilizzato poi per ripopolare l&#8217;<em>array<\/em> <strong>items<\/strong>, utilizzato a sua volta per <em>disegnare<\/em> i vari elementi all&#8217;interno del <em>Widget<\/em> <em><a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/ListView-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/widgets\/ListView-class.html\" target=\"_blank\" rel=\"noreferrer noopener\">ListView<\/a><\/em>.<\/p>\n\n\n\n<p>Come \u00e8 possibile vedere, <strong>items<\/strong> \u00e8 un elenco di <em>Widget<\/em> <a href=\"https:\/\/api.flutter.dev\/flutter\/material\/ListTile-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/material\/ListTile-class.html\" target=\"_blank\" rel=\"noreferrer noopener\"><em>ListTile<\/em> <\/a>che presentano un titolo, in questo caso una stringa contenente: id, nome e cognome di ogni record presente in tabella, ed un evento <code>onTap: () {}<\/code> (click sull&#8217;elemento della lista).<\/p>\n\n\n\n<p>In questo esempio, premendo su un elemento della lista, questo, viene eliminato dalla base dati e la lista viene successivamente ricaricata e ridisegnata:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n...\nGetIt.I&amp;lt;DatabaseHelper&gt;()\n    .deletePersona(persona)\n    .then((value) =&gt; loadList());\n...\n<\/pre><\/div>\n\n\n<p>Si pu\u00f2 notare inoltre che le operazioni di modifica dell&#8217;<em>array<\/em> <strong>items<\/strong> vengono fatte all&#8217;interno del metodo <code>setState(() {}<\/code>, questo viene fatto per ridisegnare l&#8217;interfaccia (<a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">seconda parte<\/a> per approfondire).<\/p>\n\n\n\n<p>A questo punto non resta che aggiungere un nuovo elemento <em>randomico <\/em>alla pressione del pulsante &#8220;+&#8221; presente in basso a destra all&#8217;interno della pagina.<\/p>\n\n\n\n<p>Aggiungiamo quindi la seguente operazione all&#8217;interno dell&#8217;evento <code>onPressed: () {}<\/code> del pulsante <em><a href=\"https:\/\/api.flutter.dev\/flutter\/material\/FloatingActionButton-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/material\/FloatingActionButton-class.html\" target=\"_blank\" rel=\"noreferrer noopener\">FloatingActionButton<\/a><\/em>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nimport &#039;dart:math&#039;;\nimport &#039;package:demo_application\/models\/persona_db.dart&#039;;\n\n...\n    \nGetIt.I&lt;DatabaseHelper&gt;()\n    .insertPersona(PersonaDB(\n        nome: nomi&#x5B;random.nextInt(nomi.length)],\n        cognome: cognomi&#x5B;random.nextInt(cognomi.length)],\n    ))\n    .then((value) =&gt; loadList());\n...\n<\/pre><\/div>\n\n\n<p>Il nome ed il cognome vengono selezionati casualmente all&#8217;interno delle rispettive liste.<\/p>\n\n\n\n<p>Eseguiamo l&#8217;applicazione con <em>F5<\/em>, effettuiamo l&#8217;accesso e premiamo il pulsante &#8220;+&#8221;:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-20.png\" alt=\"\" class=\"wp-image-6068\" width=\"284\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-20.png 400w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-20-134x300.png 134w\" sizes=\"(max-width: 400px) 100vw, 400px\" loading=\"lazy\" \/><\/figure><\/div>\n\n\n\n<p>Alla pressione del pulsante apparir\u00e0 a schermo un nuovo elemento. Continuamo a premerlo un&#8217;altro paio di volte per verificarne il comportamento corretto.<\/p>\n\n\n\n<p>Proviamo ora invece a &#8220;<em>tappare<\/em>&#8221; gli elementi della lista:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-21.png\" alt=\"\" class=\"wp-image-6069\" width=\"284\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-21.png 400w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2022\/04\/image-21-134x300.png 134w\" sizes=\"(max-width: 400px) 100vw, 400px\" loading=\"lazy\" \/><\/figure><\/div>\n\n\n\n<p>Come \u00e8 possibile vedere, gli elementi che vengono premuti verranno eliminati.<\/p>\n\n\n\n<p>Per la prova finale terminiamo l&#8217;esecuzione dell&#8217;app con <em>Shift+F5<\/em> e rieseguiamo il tutto con <em>F5<\/em>. Accediamo dalla pagina di login&#8230; ed ecco qua la nostra lista, esattamente nello stato in cui l&#8217;abbiamo lasciata terminando l&#8217;applicazione, ad indicare che il database funziona correttamente.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"prossimamente\">Prossimamente&#8230;<\/h3>\n\n\n\n<p>Il prossimo sar\u00e0 l&#8217;ultimo articolo di questa serie sullo sviluppo di applicazioni Flutter.<\/p>\n\n\n\n<p>Vedremo con gestire la modalit\u00e0 scura e cambiare il tema della nostra app. Inoltre proveremo a compilarla su un ambiente macOS ed eseguirla su un simulatore iOS per verificarne il funzionamento multipiattaforma.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"github\">GitHub<\/h3>\n\n\n\n<p>Il progetto Flutter realizzato in questo articolo \u00e8 disponibile su <a href=\"https:\/\/github.com\/Cloudsurfers-Dev\/flutter_demo_application_pt3\" data-type=\"URL\" data-id=\"https:\/\/github.com\/Cloudsurfers-Dev\/flutter_demo_application_pt3\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fonti\">Fonti<\/h3>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/flutter.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/flutter.dev\/<\/a><\/li><li><a href=\"https:\/\/dart.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/dart.dev\/<\/a><\/li><li><a href=\"https:\/\/material.io\/design\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/material.io\/design\/<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p><!-- wp:paragraph --><\/p>\n<p>Terza parte della serie in cui stiamo realizzando un&#8217;applicazione <strong>Flutter <\/strong>multipiattaforma da zero, facendolo passo passo.<\/p>\n<p><!-- \/wp:paragraph --><\/p>\n<p><!-- wp:paragraph --><\/p>\n<p>Fino ad ora, nelle parti precedenti, abbiamo sviluppato un&#8217;app multilingua, integrata ad uno strato API Web. Potete trovare la <a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-1\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">prima<\/a> e la <a href=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" data-type=\"URL\" data-id=\"https:\/\/cloudsurfers.it\/index.php\/sviluppare-applicazione-flutter-parte-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">seconda <\/a>parte della serie qui sul sito se non le aveste gi\u00e0 lette.<\/p>\n<p><!-- \/wp:paragraph --><\/p>\n<p><!-- wp:paragraph --><\/p>\n<p>Il codice sorgente, inoltre, \u00e8 disponibile su <a href=\"https:\/\/github.com\/Cloudsurfers-Dev\/flutter_demo_application_pt3\" data-type=\"URL\" data-id=\"https:\/\/github.com\/Cloudsurfers-Dev\/flutter_demo_application_pt3\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a> separato per articoli.<\/p>\n<p><!-- \/wp:paragraph --><\/p>\n<p><!-- wp:paragraph --><\/p>\n<p>Ora andremo ad aggiungere al nostro applicativo una nuova pagina con al suo interno una lista di elementi simil applicazione <em>To Do list<\/em> ed integreremo il tutto con una base dati locale SQLite per la storicizzazione delle informazioni.<\/p>\n<p><!-- \/wp:paragraph --><\/p>\n","protected":false},"author":3,"featured_media":6063,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wds_primary_category":0,"footnotes":""},"categories":[185,181,36],"tags":[96,184,182,183,110],"class_list":["post-6062","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dart","category-flutter","category-guide","tag-app","tag-dart","tag-flutter","tag-mobile","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts\/6062","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/comments?post=6062"}],"version-history":[{"count":0,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts\/6062\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/media\/6063"}],"wp:attachment":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/media?parent=6062"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/categories?post=6062"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/tags?post=6062"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}