Programmare applicazioni mobili con flutter

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Sì infatti li ho messi fuori qualsiasi blocco di codice.
In php mi basta dichiarare un'array associativo tipo questo:
PHP:
<?php
$vettore = array();
$vettore['inizio'] = 'Benvenuto';
$vettore['saluto'] = $vettore['inizio'].' ospite';
# eccetera   
    
?>
Li ho sempre messi fuori qualsiasi blocco di codice e non ho mai avuto problemi. Ora mi serve fare la stessa cosa in dart, sempre fuori da ogni blocco di codice, in quanto sono variabili che mi servono in tutta l'applicazione.

Come posso fare?

Grazie
 

pabloski

Utente Èlite
2,868
916
Ma questo è Dart, non PHP. Le istruzioni si mettono all'interno delle funzioni o altri blocchi di codice, che iniziano e finiscono con { }.

Se quel codice che hai postato, lo metti in una funzione, funziona perfettamente. E' una questione di sintassi.
 

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Ho capito che è la sintassi e che in php è diverso.

Ma non posso dichiarare un oggetto Map fuori dai blocchi di codice? C'è un'alternativa per farlo?

Grazie
 

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Ho risolto così. variabili.dart
JavaScript:
Map<String, dynamic> applicazione = Map();

void dichiarazioniIniziali() {
  applicazione['nome'] = 'App Provo';
  // e tante altre
}
main.dart
JavaScript:
void main() {
  dichiarazioniIniziali();
  runApp(ApplicazioneMia());
}
E ora tutto funziona come voglio io. Se hai un modo migliore, ben venga.

Ora però devo fare un passo indietro, ancor prima delle notifiche. Mi serve avere le variabili salvate sul dispositivo prima di avviare l'app. Il codice che esegue questa funzionalità nella mia app è questo, variabili.dart:
JavaScript:
SharedPreferences impostazioniSalvate;

void caricaImpostazioni() async {
  impostazioniSalvate = await SharedPreferences.getInstance();
}
Ho provato a mettere la chiamata alla funzione caricaImpostazioni() subito dopo dichiarazioniIniziali() in main e prima di runApp(), ma ricevo errori del tipo "non ancora inizializzata la libreria SharedPreferences".

Quindi devo andare con lo splash screen. Nelle prime righe della pagina di documentazione, di cui mi hai postato il collegamento, si legge che lo splash screen è obbligatorio per ios, e invece android ne ha due tipi. Non so quale dei due va meglio per me, e non ho capito bene se si può mettere solo un'immagine o qualsiasi altra cosa.

Magari se possibile, potresti mostrarmi un po' di esempio riguardante l'inserimento dello splash screen?

Grazie
 

pabloski

Utente Èlite
2,868
916
Il problema lì è che fai un uso abnorme di variabili globali, che è il male assoluto nei software medio/grandi.

Venendo dal Javascript, sei stato abituato così. Ed è questo tipo di abitudini che viene bacchettato riguardo Javascript. E' per questo che si dice che è un linguaggio "da schifo".

Il perchè ti dà quell'errore riguardo SharedPreferences, è dovuto al fatto che esse sono legate al contesto. Ma il contesto viene creato, dopo l'esecuzione di runApp.

Inoltre, se guardi qui, noterai che risolve l'errore e il problema di avere una variabile globale per SharedPreferences https://pub.dev/packages/shared_preferences

semplicemente richiedendo, ad ogni uso, l'istanza di SharedPreferences allocata. Ed è quello il modo corretto.
 

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Ho seguito il tuo consiglio, e ora non ho più errori. Metto anche l'oggetto CircularProgressIndicator nel frattempo che SharedPreferences legge le variabili salvate.
Purtroppo sono abituato a js e php, e nei siti che ho costruito, ho sempre usato solo variabili globali, tranne per variabili temporanee all'interno di funzioni. Sto tentando di ridurre al minimo l'uso delle variabili globali, perché so che consumano cpu e ram sia nei server (php) sia nei dispositivi degli utenti (js).

Però c'è un problema: appena carico la pagina iniziale faccio visualizzare la variabile salvata nel dispositivo (per ora solo un numero intero) e funziona. Ma poi ho creato una route chiamata impostazioni dove questo numero intero viene incrementato, e nella route stessa, tramite setstate(), il numero viene aggiornato. Ma ritornando alla pagina iniziale, mi ritrovo con il numero vecchio.

Come posso risolvere?

Grazie
 

pabloski

Utente Èlite
2,868
916
Purtroppo sono abituato a js e php, e nei siti che ho costruito, ho sempre usato solo variabili globali, tranne per variabili temporanee all'interno di funzioni.

Sono linguaggi che insegnano tante brutte pratiche. Per questo dicevo di avere flessibilità e fermarsi un attimo a studiare la teoria che ci sta dietro Dart ( che poi è semplicemente la collezione di buone pratiche maturate in 30 anni, nei linguaggi C-like ).

Però c'è un problema: appena carico la pagina iniziale faccio visualizzare la variabile salvata nel dispositivo (per ora solo un numero intero) e funziona. Ma poi ho creato una route chiamata impostazioni dove questo numero intero viene incrementato, e nella route stessa, tramite setstate(), il numero viene aggiornato. Ma ritornando alla pagina iniziale, mi ritrovo con il numero vecchio.

Non ho capito bene dove si trova la variabile e che succede.
 

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Non ho capito bene dove si trova la variabile e che succede.
iniziale.dart
JavaScript:
class PagIniziale extends StatefulWidget {
  @override
  _PagInizialeState createState() => _PagInizialeState();
}

class _PagInizialeState extends State<PagIniziale> {
  Future<SharedPreferences> _impoSalvate = SharedPreferences.getInstance();
  Future<int> _voltePremuto;

  @override
  void initState() {
    super.initState();
    _voltePremuto = _impoSalvate.then((SharedPreferences v) {
      return v.getInt('voltepremuto');
    });
  }

  @override
  Widget build(BuildContext context) {
    return
      // da qualche parte nello scaffold
      FutureBuilder<int>(
                    future: _voltePremuto,
                    builder: (context, snapshot) {
                      switch (snapshot.connectionState) {
                        case ConnectionState.waiting:
                          return CircularProgressIndicator();
                        default:
                          if (snapshot.hasError) {
                            return Text('Errore: ${snapshot.error}');
                          } else {
                            return Text(
                              'Premuto ${(snapshot.data ?? 0)} volte',
                              style: TextStyle(fontSize: 36.0),
                            );
                          }
                      }
                    });
  }
}
impostazioni.dart
JavaScript:
class PagImpostazioni extends StatefulWidget {
  @override
  _PagImpostazioniState createState() => _PagImpostazioniState();
}

class _PagImpostazioniState extends State<PagImpostazioni> {
  Future<SharedPreferences> _impoSalvate = SharedPreferences.getInstance();
  Future<int> _volte;

  Future<void> _spingi() async {
    final SharedPreferences v = await _impoSalvate;
    final int _quante = (v.getInt('voltepremuto') ?? 0) + 1;
    setState(() {
      _volte = v.setInt('voltepremuto', _quante).then((bool fatto) => _quante);
    });
  }

  @override
  void initState() {
    super.initState();
    _volte = _impoSalvate.then((SharedPreferences v) {
      return v.getInt('voltepremuto') ?? 0;
    });
  }

  @override
  Widget build(BuildContext context) {
    return
    // da qualche parte anche qui
    FutureBuilder<int>(
            future: _volte,
            builder: (context, snapshot) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  ListTile(
                    title: Text('Premi qui per incrementare'),
                    subtitle: Text('Spingi ${snapshot.data} volte'),
                    trailing: Icon(Icons.keyboard_arrow_right),
                    onTap: _spingi,
                  ),
                  // e tanto altro
                ],
              );
            });
  }
}
Apro l'app, mi dice che ho premuto 20 volte, vado nella route impostazioni, faccio incrementare il numero premendo su listtile portando il numero a 25 (esempio).
Nella pagina impostazioni il numero si aggiorna ogni volta che premo, quando ritorno indietro alla pagina iniziale, mi dice ancora 20 volte.

Mi serve aggiornare anche la pagina iniziale.
 

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Manco io c'ho capito un granché, se è future, perché viene costruito prima di build? :look:

Ma la cosa che vorrei fare è ricostruire gli oggetto futurebuilder ogni volta che la route viene visualizzata, anche ritornando alla pagina iniziale con navigator.pop().

Come posso fare?

Grazie
 

pabloski

Utente Èlite
2,868
916
Lo stato. Devi recuperare lo stato.

Comincia da qui https://flutter.dev/docs/development/data-and-backend/state-mgmt

E poi da un'occhiata qui


Devi prima capire come Flutter funziona sotto il cofano, altrimenti ti ritroverai a fare copia-incolla di codice che, alla lunga, non funzionerà.
 

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Prima di leggere i documenti che mi hai postato, voglio sapere se posso fare questa cosa di recuperare lo stato anche per aggiungere elementi alle route nel caso viene comunicato di farlo (es. via firebase o xhr).

Grazie
 

pabloski

Utente Èlite
2,868
916
Naturale che si può fare. Esistono pattern che consentono di far rimbalzare lo stato da una route all'altra.
 

hddsfortuna

Utente Attivo
869
39
Net
FTTH 1000/300
OS
Ubuntu 22.04
Leggendo questa pagina nella guida che mi hai postato -> sezione consumer, sarà l'inglese o altro, ma non ho capito a cosa serve di questo codice:
JavaScript:
return Consumer<CartModel>(
  builder: (context, cart, child) => Stack(
        children: [
          // Use SomeExpensiveWidget here, without rebuilding every time.
          child,
          Text("Total price: ${cart.totalPrice}"),
        ],
      ),
  // Build the expensive widget here.
  child: SomeExpensiveWidget(),
);
Se io devo usare l'elemento consumer solo dove necessario modificare l'albero dei widget, a cosa serve il terzo parametro child di builder?

Grazie
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!