質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

1回答

2981閲覧

Flutterでshared_preferencesを利用したローカルでのfavoriteリスト保存方法

namihana

総合スコア23

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

1グッド

0クリップ

投稿2020/03/03 17:25

現在作成しているアプリで、お気に入り機能をつけるところまでは来たのですが、それをshared_preferencesを利用してデータを保持する方法がなかなか掴めません。
具体的にはアプリを終了してもデータを保持したいと考えております。
(現状ですとアプリを再起動すると、お気に入りリストがリセットされてしまいますので、、)

ちなみに、providerを用いて、リストにお気に入り項目をリスト表示するところまではできているのですが、、

どなたか解決できる方はいらっしゃいませんでしょうか。
こちらで試したshared_preferencesの箇所はコメントアウトしております。

まだまだ初心者で初歩的なところかもしれませんが、どなたかわかる方がいらっしゃいましたら教えていただけると幸いです。

以下GitのURL
https://github.com/nannantown/flutter_lang

import 'dart:collection'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; enum EventLoadingStatus { NotLoaded, Loading, Loaded } class Course with ChangeNotifier { var id; var title; var type; var color; bool isFavorite; var name = []; final List<Course> _favorite = []; // final SharedPreferences prefs = await SharedPreferences.getInstance(); // prefs.setStringList(favoriteCourse, List<Course> _favorite); EventLoadingStatus _eventLoadingStatus = EventLoadingStatus.Loading; UnmodifiableListView<Course> get favorite => UnmodifiableListView(_favorite.where((course) => course.isFavorite)); UnmodifiableListView<Course> get beginnerList => UnmodifiableListView( _favorite.where((course) => course.type == "BEGINNER")); UnmodifiableListView<Course> get intermediateList => UnmodifiableListView( _favorite.where((course) => course.type == "INTERMEDIATE")); UnmodifiableListView<Course> get advanceList => UnmodifiableListView( _favorite.where((course) => course.type == "ADVANCED")); UnmodifiableListView<Course> get packsList => UnmodifiableListView(_favorite.where((course) => course.type == "PACKS")); numOfFavorite() => _favorite.length; // final SharedPreferences prefs = await SharedPreferences.getInstance(); // prefs.getStringList('my_favorite_list') ?? []; Course({ this.name, }) { addData(this.name); } addData(name) async { if (name != null) { for (final item in name) { Course course = Course(); course.id = item.id; course.title = item.title; course.type = item.type; course.isFavorite = false; _favorite.add(course); } } notifyListeners(); } void favoriteToggle() { isFavorite = !isFavorite; notifyListeners(); } void toggleFavorite(Course course) { final taskIndex = _favorite.indexOf(course); print("------------- course.isFavorite $taskIndex"); print(_favorite[taskIndex].id); _favorite[taskIndex].favoriteToggle(); notifyListeners(); } void favoriteToggleWithId(String id) { for (final item in _favorite) { if (item.id == id) { item.isFavorite = false; } } notifyListeners(); } // // Future<Void> addDataCourse(Course course) async { // _eventLoadingStatus = EventLoadingStatus.Loading; // notifyListeners(); // _favorite.add(course); // _eventLoadingStatus = EventLoadingStatus.Loaded; // notifyListeners(); // } // void addData(Course course) { // _favorite.add(course); // notifyListeners(); // } } class Contents { final String course; final String title; final String speakerJA; final String speakerJB; final String speakerEA; final String speakerEB; final String soundNameA; final String soundNameB; const Contents({ @required this.course, this.title, @required this.speakerJA, @required this.speakerJB, @required this.speakerEA, @required this.speakerEB, @required this.soundNameA, @required this.soundNameB, }); }
popobot👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

GitHubのコードを少し読んでみました。

やりたいことはFlutterのCartサンプルに似ている気がしました。

Courseモデルとは別に、お気に入りのリストを管理するFavoriteListモデルをChangeNotifierを継承して作成する。起動直後にChangeNotifierProviderで初期化して、そのときにshared_preferencesから取得する。
後は必要な箇所でProvider.ofConsumerFavoriteListにアクセスすればいい気がします。お気に入りを変更する場合は、FavoriteListの状態を変更しつつ、内部でshared_preferencesの内容も更新する感じですかね


GitHubのコードを修正して実験したコードを載せておきます。
なお、以下のコードだと、SharedPreferencesのロードが非同期なので、一瞬だけお気に入りが消えた状態でリストが表示されてしまいます。必要ならロードが終わるまでリストを非表示にするなど対応した方がいいかもしれません。

models/favolit_list.dart

import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class FavoriteList with ChangeNotifier { List<String> _favoriteIds = []; FavoriteList() { load(); } void load() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); _favoriteIds = prefs.getStringList('my_favorite_list') ?? []; notifyListeners(); } void save() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setStringList('my_favorite_list', _favoriteIds); } bool isFavorite(String id) { return _favoriteIds.contains(id); } void toggle(String id) { if (_favoriteIds.contains(id)) { _favoriteIds.remove(id); } else { _favoriteIds.add(id); } save(); notifyListeners(); } }

main.dart (一部抜粋)

void main() => runApp(MultiProvider( providers: [ ChangeNotifierProvider<FavoriteList>( create: (_) => FavoriteList(), ), ChangeNotifierProvider<TextVisibility>( create: (_) => TextVisibility(), ), ChangeNotifierProvider<Course>( create: (_) => Course(), ), ], child: MyApp(), ));

widgets/list_cards.dart (一部抜粋)

trailing: Material( color: Colors.transparent, child: Consumer<FavoriteList>( builder: (context, favoriteList, _) => IconButton( icon: Icon(favoriteList.isFavorite(name.id) ? Icons.favorite : Icons.favorite_border), iconSize: 40, autofocus: true, highlightColor: Colors.pinkAccent, hoverColor: Colors.pink, onPressed: () { favoriteList.toggle(name.id); }, ), ), ),

追加質問に対する回答 2020-3-6

FavoriteScreenでFavoriteListWidgetに渡すリストをお気に入りのコースリストにすればいいと思います。やり方は色々あると思いますが、Courseクラスにコースリストの情報があるので、Courseにお気に入りに登録されているIDを渡してCourseクラスでお気に入りのコースリストを生成するようにしてみました。

以下、変更したコードを載せておきます。

FavoriteScreenでお気に入りのコースを作る処理を呼び出すcourse.favoriteList(favoriteList.ids)

class FavoriteScreen extends StatelessWidget { static const routeName = '/favorite-screen'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('favorite'), centerTitle: true, flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, colors: <Color>[Colors.lightBlue, Colors.lightBlueAccent], ), ), ), ), body: Material( color: Colors.yellow, child: Consumer2<Course, FavoriteList>( builder: (context, course, favoriteList, child) => FavoriteListWidget( list: course.favoriteList(favoriteList.ids), ), ), ), ); } }

FavoriteListにidsを返すプロパティを追加 (一部抜粋)

class FavoriteList with ChangeNotifier { // 省略 List<String> get ids => _favoriteIds; }

Courseでお気に入りのコースリストを作る (一部抜粋)

class Course with ChangeNotifier { // 省略 UnmodifiableListView<Course> favoriteList(List<String> ids) => UnmodifiableListView( _favorite.where((course) => ids.contains(course.id))); }

投稿2020/03/04 08:09

編集2020/03/06 13:21
popobot

総合スコア6586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

namihana

2020/03/05 22:38

とてもわかりやすい回答ありがとうございました! 上記のコードを組み込んでみたところアプリを終了してもお気に入り機能が保持させることができました。 ただ一点わからないところがあり、お気に入りページにこのお気に入りリストを表示させるためにはどうすれば良いか教えていただけないでしょうか。。 色々試してみたのですが、course.dartとfavorite_list.dartを分離したことによりfavorite_screen.dartにどうやってお気に入りリストを渡すことがなかなかうまく行っておりません、、 Gitに最新版をプッシュしておりますのでもし可能であればみていただけると幸いです。 m(__)m
popobot

2020/03/06 04:41 編集

たぶん、以下の問題に該当していると思います。回答にあるようにProvider.value()を使って、遷移先の画面にデータを渡す必要があるのではないかと https://stackoverflow.com/questions/57960738/how-to-scope-a-changenotifier-to-some-routes-using-provider MaterialPageRouteでも同じような問題があり、以下の記事が参考になると思います。 https://qiita.com/kabochapo/items/a90d8438243c27e2f6d9#%E9%81%B7%E7%A7%BB%E5%85%88%E3%81%AE%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%A7%E5%80%A4%E3%82%92%E5%BE%97%E3%82%89%E3%82%8C%E3%81%AA%E3%81%84
popobot

2020/03/06 11:03 編集

すみません。試してみたら、Provider.value()をしなくても、favorite_screen.dartでConsumer<FavoriteList>で取得できました... 追加の質問としては、FavoriteListとCourseをどう組み合わせて、どうお気に入りリストを作ればいいかってことですかね。時間があるときに、もうちょっとコード読んで、試してみます。
popobot

2020/03/06 13:22

追加の質問について、回答欄にサンプルコードを書いてみましたので、参考にしてみてください
namihana

2020/03/07 13:34

サンプルコードを試してみたところ正常に動作いたしました! 解説もこの上なくわかりやすかったので感謝感激です!m(__)m 1ヶ月以上悩んでいたところだったので、とても助かりました! ありがとうございました!! m(__)m
popobot

2020/03/07 20:28

うまくいってよかったです。 余談ですが、全体的に不要になったコードがあったり、変数名がおかしなところがあったので、整理してみると見直しにもなっていいと思いました。
namihana

2020/03/10 20:01

そうですね!一度見直してみたいと思います!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問