1. provider들간에 값 연동이 가능하고, 1개 내의 provider파일안에 여러개의 provider를 생성 및 연동시킬 수 있다.
filters_provider부분에 연동해보자.
- filters_provider.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:meals/providers/meals_provider.dart';
enum Filter {
glutenFree,
lactoseFree,
vegetarian,
vegan,
}
class FiltersNotifier extends StateNotifier<Map<Filter, bool>> {
FiltersNotifier()
: super({
Filter.glutenFree: false,
Filter.lactoseFree: false,
Filter.vegetarian: false,
Filter.vegan: false
});
void setFilters(Map<Filter, bool> chosenFilters) {
state = chosenFilters;
}
void setFilter(Filter filter, bool isActive) {
// state[filter] = isActive; // not allowed! => mutating state
state = {
...state,
filter: isActive,
};
}
}
final filtersProvider =
StateNotifierProvider<FiltersNotifier, Map<Filter, bool>>(
(ref) => FiltersNotifier(),
);
final filteredMealsProvider = Provider((ref) {
final meals = ref.watch(mealsProvider);
final activeFilters = ref.watch(filtersProvider);
return meals.where((meal) {
if (activeFilters[Filter.glutenFree]! && !meal.isGlutenFree) {
return false;
}
if (activeFilters[Filter.lactoseFree]! && !meal.isLactoseFree) {
return false;
}
if (activeFilters[Filter.vegetarian]! && !meal.isVegetarian) {
return false;
}
if (activeFilters[Filter.vegan]! && !meal.isVegan) {
return false;
}
return true;
}).toList();
});
1)filteredMealsProvider의 결과 값으 단순 data이기 때문에 Provider((ref) ~~ 를 사용한다.
2) filteredMealsProvider 를 보면, 기존 tabs.dart에서 사용했던 필터된 meals을 가져오는 로직을 구현해놨다.
mealsProvider에서 watch를 통해 값을 가져오고(이것 watch이기 때문에 값이 변동되면 해당 provider의 값 역시 실시간으로 값이 바뀐다 - 의존성) 그리고 같은 파일안에 있는 filtersProvider를 activeFilter로 사용해준다. (필터 상태값)
- tabs.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:meals/screens/categories.dart';
import 'package:meals/screens/filters.dart';
import 'package:meals/screens/meals.dart';
import 'package:meals/widgets/main_drawer.dart';
import 'package:meals/providers/favorites_provider.dart';
import 'package:meals/providers/filters_provider.dart';
const kInitialFilters = {
Filter.glutenFree: false,
Filter.lactoseFree: false,
Filter.vegetarian: false,
Filter.vegan: false
};
class TabsScreen extends ConsumerStatefulWidget {
const TabsScreen({super.key});
@override
ConsumerState<TabsScreen> createState() {
return _TabsScreenState();
}
}
class _TabsScreenState extends ConsumerState<TabsScreen> {
int _selectedPageIndex = 0;
void _selectPage(int index) {
setState(() {
_selectedPageIndex = index;
});
}
void _setScreen(String identifier) async {
Navigator.of(context).pop();
if (identifier == 'filters') {
await Navigator.of(context).push<Map<Filter, bool>>(
MaterialPageRoute(
builder: (ctx) => const FiltersScreen(),
),
);
}
}
@override
Widget build(BuildContext context) {
final availableMeals = ref.watch(filteredMealsProvider);
Widget activePage = CategoriesScreen(
availableMeals: availableMeals,
);
var activePageTitle = 'Categories';
if (_selectedPageIndex == 1) {
final favoriteMeals = ref.watch(favoriteMealsProvider);
activePage = MealsScreen(
meals: favoriteMeals,
);
activePageTitle = 'Your Favorites';
}
return Scaffold(
appBar: AppBar(
title: Text(activePageTitle),
),
drawer: MainDrawer(
onSelectScreen: _setScreen,
),
body: activePage,
bottomNavigationBar: BottomNavigationBar(
onTap: _selectPage,
currentIndex: _selectedPageIndex,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.set_meal),
label: 'Categories',
),
BottomNavigationBarItem(
icon: Icon(Icons.star),
label: 'Favorites',
),
],
),
);
}
}
1) 이제 final availableMeals = ref.watch(filteredMealsProvider); 부분을 통해서 값을 가져온다.
'코딩강의 > meals_app(플러터-유데미)' 카테고리의 다른 글
| ~196. Explicit Animations: Playing the Animation with AnimatedBuilder (0) | 2023.11.06 |
|---|---|
| 190. Swapping The "Favorite Button" Based On Provider State (State부분 마지막 강의) (0) | 2023.11.05 |
| 188. Outsourcing State Into The Provider (0) | 2023.11.05 |
| ~187. Combining Local & Provider-managed State (0) | 2023.11.05 |
| ~185. Triggering a Notifier Method (0) | 2023.11.02 |