扑腾书籍 扑腾学徒

10
共享偏好 由凯文摩尔撰写

图片:您:您正在浏览食谱并找到一个您喜欢的食谱。你赶时间,想用稍后将它写下来检查它。你能建立一个浮动应用程序吗?你肯定可以!阅读,了解如何。

在本章中,您的目标是学习如何使用 共享偏好 将重要信息保存到您的设备。

您将从一个新项目开始,在屏幕底部显示三个不同视图的标签:食谱,书签和杂货。

第一个屏幕是您在哪里搜索要准备的食谱。一旦您找到了您喜欢的配方,只需将其添加到书签页面以及应用程序将添加到您的书签页面,并添加您需要的所有成分。您将使用Web API来搜索食谱并将您在本地数据库中的书签存储的API。

已完成的应用程序看起来像:

这将显示“回谱”选项卡以及搜索“意大利面”时获得的结果。它在搜索文本字段中键入并按下搜索图标。该应用程序将您的搜索词历史存储在文本字段右侧的组合框中。

当您点击一张卡时,您会看到类似的东西:

要保存配方,只需点击 书签 按钮。当你导航到 书签 选项卡,您会看到配方已保存:

如果您不再想要配方,请左转或向右滑动,您会看到一个删除按钮,允许您从书签食谱列表中删除它。

杂货 选项卡显示您所需的成分来制作您已添加的食谱。

您将在接下来的几章中构建此应用程序。在本章中,您将使用 共享偏好 要保存像所选选项卡的简单数据,也可以缓存搜索物品 食谱 tab.

到本章末尾,您会知道:

  • 什么共享的偏好是。
  • 如何使用 shared_preferences. 要保存和检索对象的插件。

现在你知道你的目标是什么,是时候跳进去了!

入门

打开 起动机 project for this chapter in Android Studio, run flutter pub get if necessary, then run the app.

请注意底部的三个选项卡 - 当您点击它时,每个选项卡将显示一个不同的屏幕。只有 食谱 屏幕目前有任何UI显示。它看起来像这样:

app库

Starter项目包括以下图书馆 pubspec.yml.:

dependencies:
  ...
  cached_network_image: ^2.3.2+1
  flutter_slidable: ^0.5.7
  flutter_svg: ^0.19.0
  flutter_statusbarcolor: ^0.2.3

保存数据

将数据保存到设备有三种主要方法:

为什么节省小的数据?

节省小型数据有很多原因。例如,您可以在用户登录时保存用户ID - 或者用户完全登录。您还可以保存用户已添加书签以稍后查阅的船上状态或数据。

SharedPreeferences.

shared_preferences. 是一个扑振插件,允许您以键值格式保存数据,以便您可以轻松地检索它。在幕后,它使用恰如其名字 SharedPreeferences. 在Android和类似的 userdefaults. on iOS.

  shared_preferences: ">=0.5.8 <2.0.0"

flutter pub get

保存UI状态

你会使用 shared_preferences. 在本节中保存已保存的搜索列表。稍后,您还将保存用户已选择的选项卡,以便应用程序始终打开该选项卡。

添加到搜索列表的条目

首先,您将更改UI,以便当用户按下搜索图标时,该应用程序将将搜索条目添加到搜索列表。

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class _RecipeListState extends State<RecipeList> {
  static const String prefSearchKey = "previousSearches";
bool inErrorState = false;
List<String> previousSearches = List<String>();

在后台运行代码

要了解接下来,您将添加的代码,您需要了解背景中的运行代码。

保存以前的搜索

既然你已经奠定了一些基础,你已经准备好实施了保存搜索。

void savePreviousSearches() async {
  // 1
  SharedPreferences prefs = await SharedPreferences.getInstance();
  // 2
  prefs.setStringList(prefSearchKey, previousSearches);
}
void getPreviousSearches() async {
  // 1
  SharedPreferences prefs = await SharedPreferences.getInstance();
  // 2
  if (prefs.containsKey(prefSearchKey)) {
    // 3
    previousSearches = prefs.getStringList(prefSearchKey);
    // 4
    if (previousSearches == null) {
      previousSearches = List<String>();
    }
  }
}
getPreviousSearches();

添加按钮以保存搜索

接下来,您将为用户提供通过添加保存按钮来保存搜索的权力。

IconButton(
  icon: Icon(Icons.search),
  // 1
  onPressed: () {
    // 2
    startSearch(searchTextController.text);
  },
),
Expanded(
  // 3
  child: TextField(
    decoration: InputDecoration(
      border: InputBorder.none, hintText: 'Search'),
    autofocus: false,
    // 4
    textInputAction: TextInputAction.done,
    // 5
    onSubmitted: (value) {
      if (!previousSearches.contains(value)) {
        previousSearches.add(value);
        savePreviousSearches();
      }
    },
    controller: searchTextController,
  )),
// 6
PopupMenuButton<String>(
  icon: const Icon(Icons.arrow_drop_down),
  // 7
  onSelected: (String value) {
    searchTextController.text = value;
    startSearch(searchTextController.text);
  },
  itemBuilder: (BuildContext context) {
    // 8
    return previousSearches
      .map<CustomDropdownMenuItem<String>>((String value) {
        return CustomDropdownMenuItem<String>(
          text: value,
          value: value,
           callback: () {
              setState(() {
                // 9
                previousSearches.remove(value);
                Navigator.pop(context);
              });
            },
        );
      }).toList();
      },
    ),

添加搜索功能

Finally, you need to make the search work. Do this by adding the startSearch() method after the _buildSearchCard() method:

void startSearch(String value) {
  // 1
  setState(() {
    // 2
    currentSearchList.clear();
    currentCount = 0;
    currentEndPosition = pageCount;
    currentStartPosition = 0;
    hasMore = true;
    // 3
    if (!previousSearches.contains(value)) {
      // 4
      previousSearches.add(value);
      // 5
      savePreviousSearches();
    }
  });
}

测试应用程序

现在是时候测试这个应用程序了。因为您添加了新的依赖项,因此退出运行实例并再次运行(请注意,您并不总是在添加依赖项时不需要重新启动)。你会看到这样的东西:

保存所选选项卡

在本节中,您将使用saved_preferences保存用户已导航到的当前UI选项卡。

import 'package:shared_preferences/shared_preferences.dart';
List<Widget> pageList = List<Widget>();
static const String prefSelectedIndexKey = "selectedIndex";
void saveCurrentIndex() async {
  // 1
  SharedPreferences prefs = await SharedPreferences.getInstance();
  // 2
  prefs.setInt(prefSelectedIndexKey, _selectedIndex);
}
void getCurrentIndex() async {
  // 1
  SharedPreferences prefs = await SharedPreferences.getInstance();
  // 2
  if (prefs.containsKey(prefSelectedIndexKey)) {
    // 3
    setState(() {
      _selectedIndex = prefs.getInt(prefSelectedIndexKey);
    });
  }
}
getCurrentIndex();
saveCurrentIndex();

关键点

  • 有多种方法可以在应用程序中保存数据:在共享首选项和SQLite数据库中的文件中。
  • 共享首选项最适合存储像字符串,数字和布尔的原始类型的简单,键值对。
  • 共享首选项的示例使用是保存用户正在查看的当前选定的选项卡,以便下次用户启动应用程序时,它们会带到同一个选项卡。
  • async/await keyword pair let you run asynchronous code off the main UI thread and then wait for the response. An example is getting an instance of the SharedPreeferences. class.
  • shared_preferences. 插件不应用于保持敏感数据。相反,考虑使用 flutter_secure_storage plugin.

然后去哪儿?

在本章中,您学习了如何使用Shared_preferences插件持续应用程序中的简单数据类型。如果您想了解有关Android SharedPreferences的更多信息,请转至 //developer.android.com/reference/kotlin/android/content/SharedPreferences?hl=en。对于ios,去 //developer.apple.com/documentation/foundation/userdefaults.

有一个技术问题?想报告一个错误吗? 您可以向官方书籍论坛中的书籍作者提出问题和报告错误 这里 .

有反馈分享在线阅读体验吗? 如果您有关于UI,UX,突出显示或我们在线阅读器的其他功能的反馈,您可以将其发送到设计团队,其中表格如下所示:

© 2021 Razeware LLC

您可以免费读取,本章的部分显示为 混淆了 文本。解锁这本书,以及我们整个书籍和视频目录,带有Raywenderlich.com的专业订阅。

现在解锁

要突出或记笔记,您需要在订阅中拥有这本书或自行购买。