Shared Preferences Flutter Tutorial: shared_preferences Flutter Guide

Haris Bin Nasir Avatar

·

·

In this tutorial, we’ll dive into implementing shared preferences in a Flutter app to persist user data across sessions. Shared preferences are essential for storing small amounts of data like user settings, login information, and other preferences that need to be retained between app launches. In this guide, we’ll walk you through creating a BMI (Body Mass Index) calculator that remembers the last entered height and weight, as well as keeps a history of calculated BMIs.

If you prefer watching a video tutorial here is a link to that.

Setting Up Your Flutter Project

Before diving into the code, ensure you have a Flutter environment set up. Begin by creating a new Flutter project and setting up the basic structure.

flutter create flutter_shared_preferences_tutorial

Adding Required Dependencies

First, add the necessary dependencies to your pubspec.yaml file:

shared_preferences:

The shared_preferences package allows Flutter developers to store simple data types like strings, integers, and booleans locally on a device. This is ideal for saving user preferences and settings that persist across app sessions. To get the dependency click here.

input_quantity:

The input_quantity package provides a user-friendly widget for inputting numerical values, complete with increment and decrement buttons. It’s perfect for applications that require precise control over quantity inputs, such as a BMI calculator. To get the dependency click here.

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.3.2
  input_quantity: ^2.4.0

These libraries will help manage shared preferences and provide user-friendly input fields.

Creating the Main Application Structure

Start by creating the entry point of your Flutter application in main.dart:

import 'package:flutter/material.dart';
import 'package:flutter_shared_prefrences_tutorial/pages/home_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: HomePage(),
    );
  }
}

Creating the Home Page

The heart of our application lies in the HomePage. This widget is stateful, allowing us to manage user input and display results dynamically.

Setting Up Shared Preferences

Shared Preferences allow us to persist data. Initialize them in the initState() method:

class _HomePageState extends State<HomePage> {
  SharedPreferences? _prefs;
  num _height = 0, _weight = 0, _bmi = 0;
  List<String> _bmiHistory = <String>[];

  @override
  void initState() {
    super.initState();
    SharedPreferences.getInstance().then((value) {
      setState(() {
        _prefs = value;
        _bmiHistory = _prefs!.getStringList("bmi_history") ?? [];
        _height = _prefs!.getDouble("last_input_height")?.toDouble() ?? 0;
        _weight = _prefs!.getDouble("last_input_weight")?.toDouble() ?? 0;
      });
    });
  }
}

Building the User Interface

Next, construct the user interface by combining several widgets:

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _buildUI(),
  );
}

Widget _buildUI() {
  if (_prefs == null) {
    return Center(child: CircularProgressIndicator());
  }
  return SafeArea(
    child: Column(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Container(
          width: MediaQuery.sizeOf(context).width,
          height: MediaQuery.sizeOf(context).height * 0.05,
          child: Center(
            child: Text(
              "${_bmiHistory.lastOrNull ?? 0.00} BMI",
              style: TextStyle(fontSize: 25),
            ),
          ),
        ),
        Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            _weightInput(),
            _heightInput(),
          ],
        ),
        _calculateBMIButton(),
        _bmiHistoryList(),
      ],
    ),
  );
}

Handling User Input: Weight and Height

We use InputQty widgets for collecting height and weight data from the user. These inputs are automatically saved to shared preferences when changed.

Weight Input

Widget _weightInput() {
  return Column(
    children: [
      const Text("Weight"),
      InputQty(
        maxVal: double.infinity,
        initVal: _weight,
        minVal: 0,
        steps: 1,
        onQtyChanged: (value) {
          setState(() {
            _weight = value;
            _prefs!.setDouble("last_input_weight", _weight.toDouble());
          });
        },
      )
    ],
  );
}

Height Input

Widget _heightInput() {
  return Column(
    children: [
      const Text("Height"),
      InputQty(
        maxVal: double.infinity,
        initVal: _height,
        minVal: 0,
        steps: 1,
        onQtyChanged: (value) {
          setState(() {
            _height = value;
            _prefs!.setDouble("last_input_height", _height.toDouble());
          });
        },
      )
    ],
  );
}

Calculating and Displaying BMI

After collecting the user’s height and weight, the BMI is calculated and displayed along with a history of previous results.

Widget _calculateBMIButton() {
  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 15),
    child: MaterialButton(
      onPressed: () {
        double calculatedBmi = _weight / pow(_height, 2);
        setState(() {
          _bmiHistory.add(calculatedBmi.toStringAsFixed(2));
          _prefs!.setStringList("bmi_history", _bmiHistory);
        });
      },
      color: Colors.purple,
      child: const Text("Calculate", style: TextStyle(color: Colors.white)),
    ),
  );
}

Displaying BMI History

Finally, display a list of the calculated BMIs so users can keep track of their progress.

Widget _bmiHistoryList() {
  return Expanded(
    child: ListView.builder(
      itemCount: _bmiHistory.length,
      itemBuilder: (context, index) {
        return ListTile(
          leading: Text(index.toString(), style: const TextStyle(fontSize: 15)),
          title: Text(_bmiHistory[index]),
          onLongPress: () {
            setState(() {
              _bmiHistory.removeAt(index);
              _prefs!.setStringList("bmi_history", _bmiHistory);
            });
          },
        );
      },
    ),
  );
}

Get Source Code for free:

Conclusion

By following this tutorial, you have successfully implemented a Flutter app that uses shared preferences to store and retrieve user input data. This approach ensures that your app retains user preferences across sessions, enhancing the user experience. Shared preferences are a powerful tool for managing user-specific settings and small amounts of data in Flutter applications.

Happy Coding…!!!

Leave a Reply

Your email address will not be published. Required fields are marked *