Provider 강의 (www.youtube.com/watch?v=ikV-Ub9XgO4&list=PLwUg6hFuXV86arSYNF9x_5Vm_lKdIBpf9&index=4)
Base code (www.youtube.com/watch?v=2iWJRAcEsaQ&list=PLwUg6hFuXV86arSYNF9x_5Vm_lKdIBpf9&index=53)
Provider 강의 소스와 Base code 가 다릅니다.
Base code 영상의 최종소스를 기반으로 Provider 강의 설명을 바탕으로 setState ==> provider 로 변경.
<신규> saved_notifier.dart 코드 - 데이터 상태관리
import 'package:english_words/english_words.dart';
import 'package:flutter/foundation.dart';
class SavedNotifier extends ChangeNotifier{
final Set<WordPair> _saved = Set<WordPair>();
void toggleSaved(WordPair newSaved) {
final bool alreadySaved = _saved.contains(newSaved);
if (alreadySaved)
_saved.remove(newSaved);
else
_saved.add(newSaved);
notifyListeners(); // 변경시 알람을 전송하는 역할
}
bool alreadyContain(WordPair pair){
return _saved.contains(pair);
}
Set<WordPair> get saved => _saved;
}
<수정> main.dart 코드
import 'package:bloc_stream/src/random_list.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'src/saved_notifier.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<SavedNotifier>( // 4.0 이후부터 create 사용.
create: (context) => SavedNotifier(),
child: MaterialApp(
home: RandomList(),
),
);
}
}
<수정> random_list.dart 코드
import 'package:bloc_stream/src/saved.dart';
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
import 'package:provider/provider.dart';
import 'saved_notifier.dart';
class RandomList extends StatefulWidget {
@override
_RandomListState createState() => _RandomListState();
}
class _RandomListState extends State<RandomList> {
final List<WordPair> _suggestions = <WordPair>[];
// final Set<WordPair> _saved = Set<WordPair>(); // provider 로 처리
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Naming App'),
actions: <Widget>[
IconButton(icon: Icon(Icons.list), onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SavedList())
).then((value) {
//저장화면에서 돌아오면 변경사항을 다시 그리기
// Future/async/await 처리 안해도 됨.
// 리턴시 처리 필요없음 return Future.value(true);
// setState(() {
// print('리턴시 setState');
// });
});
})],
),
body: _buildList(),
);
}
Widget _buildList() {
return ListView.builder(itemBuilder: (context, index) {
// 0,2,4,6,8 is real items
// 1,3,5,7,9 is dividers
if (index.isOdd) {
return Divider();
}
// 몫을 구하는 방법, 파이썬은 // 2개로처리.
var realIndex = index ~/ 2;
if (realIndex >= _suggestions.length) {
// 화면에 표시할 내용이 단어 개수보다 많으면(같거나) 단어를 10 추가 생성할것.
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[realIndex]);
});
}
Widget _buildRow(WordPair pair) {
// 해당 단어가 저장되어 있는지 확인
// final bool alreadySaved = _saved.contains(pair); // 아래로 이동.
return Consumer<SavedNotifier>( // Consumer 로 ListTile 감싸기
builder: (context, SavedNotifier, child){
bool alreadySaved = SavedNotifier.saved.contains(pair); // 이걸로 해도 되고,
// bool alreadySaved = SavedNotifier.alreadyContain(pair) // 이걸로 해도 됨
return ListTile(
title: Text(
pair.asPascalCase,
textScaleFactor: 1.5,
),
trailing: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.pinkAccent : null,
),
onTap: () {
SavedNotifier.toggleSaved(pair);
// setState(() { // SavedNotifier.toggleSaved(pair) 로 대체함
// if (alreadySaved)
// SavedNotifier.saved.remove(pair);
// else
// SavedNotifier.saved.add(pair);
// print(SavedNotifier.saved.toString());
// });
},
);
},
// child: , // ListTile() 부분은 builder 내부로 이동
);
}
}
<수정> saved.dart
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'saved_notifier.dart';
class SavedList extends StatefulWidget {
// 'saved' 리스트는 레퍼런스로 가져오기 때문에 여기서 삭제 가능
// final Set<WordPair> saved;
// SavedList({@required this.saved});
@override
_SavedListState createState() => _SavedListState();
}
class _SavedListState extends State<SavedList> {
@override
Widget build(BuildContext context) {
final savedNotifier = context.watch<SavedNotifier>(); // 상위 위젯에서 데이터 찾기
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Saved'),
),
body: _buildList(savedNotifier.saved),
);
}
Widget _buildList(Set<WordPair> saved) {
return ListView.builder(
itemCount: saved.length * 2,
itemBuilder: (context, index) {
if (index.isOdd) return Divider();
var realIndex = index ~/ 2;
return _buildRow(saved.toList()[realIndex], saved);
});
}
Widget _buildRow(WordPair pair, Set<WordPair> saved) {
return ListTile(
title: Text(
pair.asPascalCase,
textScaleFactor: 1.5,
),
onTap: () {
Provider.of<SavedNotifier>(context, listen: false).toggleSaved(pair);
// setState(() { // Provider.of 로 대체
// // 'saved' 리스트는 레퍼런스로 가져오기 때문에 여기서 삭제 가능
// saved.remove(pair);
// });
},
);
}
}
'Flutter > 00 Legacy' 카테고리의 다른 글
[Flutter] Getx with state management(reactive version) (0) | 2021.06.04 |
---|---|
[Flutter] Getx with state management(update version) (0) | 2021.06.04 |
[Flutter] Provider with Flutter sample - ChangeNotifierProvider (0) | 2021.05.04 |
[Flutter] Bloc, Stream - setState 을 Bloc, Stream 으로 변경 (0) | 2021.05.03 |
[Flutter] Bloc, Stream - setState 로 구현 (0) | 2021.05.03 |