Привет, ребята, это мой первый урок. Я надеюсь, что могу рассказать вам ясно, так что наслаждайтесь!

Как вы знаете, иногда в нашем приложении нам нужно сохранить наши данные в локальное хранилище. Вот почему мы используем общие настройки. В pub.dev общие настройки имеют простой способ их использования. Кроме того, общие настройки набрали 6 тысяч лайков на pub.dev, и это здорово! Проблема в том, что в общих настройках нет никакого метода, позволяющего нам сохранить значение объекта, вот в чем проблема. Если вы перейдете на pub.dev и выполните поиск Shared Preferences в разделе примеров, Shared Preferences просто позволит нам сохранить наши int, string, bool, double и список строковых данных. Итак, в этой статье я поделюсь с вами, как сохранить наш объект с помощью общих настроек. Итак, продолжайте читать.

Я покажу вам, как сохранить значение нашего объекта с помощью общих настроек. В этом случае я буду получать данные из общедоступного API (reqres.in) с помощью http, а затем сохранять в нашем локальном хранилище с помощью общих настроек. Хорошо, давайте кодировать!

Прежде чем мы начнем, попробуем сохранить наш объект в локальном хранилище. Есть важная вещь, которую вы должны знать. Да, нам нужно установить пакет или плагин, который мы можем использовать в этом случае. Итак, я установил два пакета: первый — Shared Prefrences, а второй — http. Позвольте мне рассказать вам немного о двух пакетах выше. Общие настройки, которые мы можем использовать для сохранения наших данных в локальном хранилище, как указано в заголовке этой статьи выше. И Http я буду использовать для получения данных из Интернета. Довольно просто, правда?

Давайте кодировать!

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        title: const Text(
          'Home Screen',
        ),
        titleTextStyle: const TextStyle(
          fontSize: 16,
          fontWeight: FontWeight.w700,
          color: Colors.white,
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Text(
              'Id is ',
              style: TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.w700,
              ),
            ),
             SizedBox(
              height: 40,
            ),
            Text(
              'Email is ',
              style: TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.w700,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Выше у меня есть простой домашний экран, который я могу использовать для отображения данных позже. Следующий шаг, давайте создадим модель для анализа наших данных из reqres.in в наш объект.

// To parse this JSON data, do
//
//     final userModel = userModelFromJson(jsonString);

import 'dart:convert';

UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));

String userModelToJson(UserModel data) => json.encode(data.toJson());

class UserModel {
  UserModel({
    this.data,
    this.support,
  });

  Data? data;
  Support? support;

  factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
        data: Data.fromJson(json["data"]),
        support: Support.fromJson(json["support"]),
      );

  Map<String, dynamic> toJson() => {
        "data": data!.toJson(),
        "support": support!.toJson(),
      };
}

class Data {
  Data({
    this.id,
    this.email,
    this.firstName,
    this.lastName,
    this.avatar,
  });

  int? id;
  String? email;
  String? firstName;
  String? lastName;
  String? avatar;

  factory Data.fromJson(Map<String, dynamic> json) => Data(
        id: json["id"],
        email: json["email"],
        firstName: json["first_name"],
        lastName: json["last_name"],
        avatar: json["avatar"],
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "email": email,
        "first_name": firstName,
        "last_name": lastName,
        "avatar": avatar,
      };
}

class Support {
  Support({
    this.url,
    this.text,
  });

  String? url;
  String? text;

  factory Support.fromJson(Map<String, dynamic> json) => Support(
        url: json["url"],
        text: json["text"],
      );

  Map<String, dynamic> toJson() => {
        "url": url,
        "text": text,
      };
}Our model is already, i use app.quicktype.io to generate our data from response, to our object that we can use later. 

Во-первых, я буду получать данные из Интернета, используя http. Вы можете следовать моему коду ниже:

import 'dart:convert';
import 'dart:developer';

import 'package:example/model/user_model.dart';
import 'package:http/http.dart' as http;

class HomeScreenController {
  Future<UserModel> fetchUser() async {
    final url = Uri.parse('https://reqres.in/api/users/2');
    http.Response response = await http.get(url);
    UserModel userResponse = UserModel.fromJson(jsonDecode(response.body));
    log(
      'RESPONSE: EMAIL IS ${userResponse.data!.email}\nFIRST NAME ${userResponse.data!.firstName}\nLAST NAME ${userResponse.data!.lastName}',
    );
    return userResponse;
  }
}

Выше у меня есть простой способ получить данные из Интернета. Сначала вы можете создать папку с именем controller, а затем создать файл внутри папки с именем HomeScreenController. На главном экране мы немного изменим, чтобы отобразить данные.

import 'package:example/controller/home_screen_controller.dart';
import 'package:example/model/user_model.dart';
import 'package:flutter/material.dart';

class HomePageScreen extends StatelessWidget {
  HomePageScreen({super.key});

  final HomeScreenController controller = HomeScreenController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        title: const Text(
          'Home Screen',
        ),
        titleTextStyle: const TextStyle(
          fontSize: 16,
          fontWeight: FontWeight.w700,
          color: Colors.white,
        ),
      ),
      body: FutureBuilder<UserModel>(
          future: controller.fetchUser(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Center(
                child: CircularProgressIndicator(),
              );
            }
            if (snapshot.hasData) {
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      'Id is ${snapshot.data!.data!.id!}',
                      style: const TextStyle(
                        fontSize: 24,
                        fontWeight: FontWeight.w700,
                      ),
                    ),
                    const SizedBox(
                      height: 40,
                    ),
                    Text(
                      'Email is ${snapshot.data!.data!.email!}',
                      style: const TextStyle(
                        fontSize: 24,
                        fontWeight: FontWeight.w700,
                      ),
                    ),
                  ],
                ),
              );
            }
            return const Center(
              child: Text('Oopps.... Something Wrong'),
            );
          }),
    );
  }
}

Как видите, я использую FutureBuilder для отображения данных из HomeController. Итак, результат будет примерно таким:

Но мы еще не сохраняем наши данные в локальном хранилище. Как мы сохраняем в наше локальное хранилище? Это достаточно просто.

import 'dart:convert';
import 'dart:developer';

import 'package:example/model/user_model.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

class HomeScreenController {
  Future<UserModel> fetchUser() async {
    try {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      final url = Uri.parse('https://reqres.in/api/users/2');
      http.Response response = await http.get(url);
      UserModel userResponse = UserModel.fromJson(jsonDecode(response.body));

      // SAVE TO OUR LOCAL STORAGE
      Map<String, dynamic> dataUser = jsonDecode(userModelToJson(userResponse));
      final userEncode = jsonEncode(dataUser);
      /*
      CODE ABOVE WILL RETURN STRING
      SO, WE CAN USE OUR SHARED PREFERENCES TO SAVE OUR OBJECT
      */
      prefs.setString('user', userEncode);
      // LET'S SEE OUR DATA THAT WE SAVE TO LOCAL STORAGE
      String getPrefs = prefs.getString('user')!;
      log('SAVE TO LOCAL $getPrefs');
      return userResponse;
    } catch (e) {
      log(e.toString());
      throw e.toString();
    }
  }
}

Как видите, я изменил свой HomeScreenController. Сначала вы можете следовать моему коду. Тогда я постараюсь объяснить вам это. Сначала мы получаем данные из Интернета и вставляем их в нашу модель, используя метод from json. Мы не можем использовать userResponse напрямую к нашему значению Shared Preferences, потому что его тип не совпадает. Итак, мы можем использовать jsonDecode и метод json для преобразования нашей модели. jsonResponse вернет Map‹String, dynamic›. Затем мы можем закодировать наш объект (jsonResponse). Зачем нам нужно кодировать наш объект? Как я объясню сначала, общие настройки не имеют никакого метода, позволяющего нам сохранять наши данные в локальном хранилище. Вот почему нам нужно преобразовать наш объект в строку, используя метод кодирования. Итак, наш объект уже является строкой, мы можем использовать Shared Preferences для сохранения в локальном хранилище. Достаточно просто, не так ли?

Надеюсь, вы понимаете, о чем я говорю выше. Таким образом, вы можете уменьшить свой запрос к серверу, если ваши данные уже есть. Надеюсь, я рассказал вам ясно, спасибо за чтение моего первого урока. Если у вас есть какие-либо вопросы, пожалуйста, прокомментируйте ниже. Хорошего дня! Удачного кодирования!