लक्षित रीबिल्ड के लिए watch, read और select में महारत हासिल करते हुए ChangeNotifier और Provider के साथ एप्लिकेशन स्टेट साझा करें।
इस पाठ को Kodokon में खोलेंजब तक स्टेट किसी एक स्क्रीन के साथ जीता और मरता है, तब तक setState काफ़ी है। जैसे ही डेटा साझा होता है - कार्ट, सेशन, प्राथमिकताएँ - उसे कंस्ट्रक्टर से कंस्ट्रक्टर तक नीचे पास करना अप्रबंधनीय हो जाता है। ChangeNotifier SDK का न्यूनतम ऑब्ज़र्वेबल प्रदान करता है; provider उसे ट्री में इंजेक्ट करता है और केवल सब्सक्राइब किए गए विजेट को रीबिल्ड करता है। Riverpod या Bloc की तुलना में, यह जोड़ी ऑडिट करने में सबसे आसान बनी रहती है: थोड़ा जादू, एक अकेली डिपेंडेंसी, एक ऐसा तंत्र जिसे आप एक वाक्य में समझा सकते हैं।
flutter pub add providerएक अच्छी तरह से डिज़ाइन किया गया नोटिफायर एनकैप्सुलेट करता है: निजी फ़ील्ड, केवल-पठन गेटर, केवल उन मेथड के ज़रिए बदलाव जो notifyListeners() के साथ समाप्त होते हैं। यही अनुबंध इस बात की गारंटी देता है कि कोई भी स्टेट परिवर्तन UI से बच न पाए।
import 'package:flutter/foundation.dart';
class CartModel extends ChangeNotifier {
final List<String> _items = [];
List<String> get items => List.unmodifiable(_items);
int get count => _items.length;
void add(String item) {
_items.add(item);
notifyListeners();
}
void remove(String item) {
_items.remove(item);
notifyListeners();
}
}तीन प्रवेश बिंदु, तीन उपयोग। context.watch<T>() विजेट को सब्सक्राइब करता है: यह हर notifyListeners पर रीबिल्ड होता है। context.read<T>() बिना सब्सक्राइब किए पढ़ता है: यह onPressed जैसे कॉलबैक के लिए उपकरण है। context.select<T, R>() केवल एक प्रोजेक्शन को सब्सक्राइब करता है: विजेट केवल तभी रीबिल्ड होता है जब वह सटीक वैल्यू बदलती है। सुनहरा नियम: watch और select केवल build में, read हैंडलर में - कभी उल्टा नहीं।
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CounterModel extends ChangeNotifier {
int _value = 0;
int get value => _value;
void increment() {
_value++;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => CounterModel(),
child: const CounterApp(),
),
);
}
class CounterApp extends StatelessWidget {
const CounterApp({super.key});
@override
Widget build(BuildContext context) {
final value = context.watch<CounterModel>().value;
return MaterialApp(
home: Scaffold(
body: Center(child: Text('Count: $value')),
floatingActionButton: FloatingActionButton(
onPressed: () =>
context.read<CounterModel>().increment(),
child: const Icon(Icons.add),
),
),
);
}
}import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CartModel extends ChangeNotifier {
final List<String> _items = [];
int get count => _items.length;
}
class CartBadge extends StatelessWidget {
const CartBadge({super.key});
@override
Widget build(BuildContext context) {
final count = context.select(
(CartModel cart) => cart.count,
);
return Badge(
label: Text('$count'),
child: const Icon(Icons.shopping_cart),
);
}
}
onPressed के भीतर, बिना किसी अनावश्यक सब्सक्रिप्शन के आप cart.add(...) को कैसे ट्रिगर करते हैं?context.watch<CartModel>().add(...)context.read<CartModel>().add(...)context.select((CartModel c) => c.add(...))notifyListeners() वास्तव में क्या ट्रिगर करता है?_items को सीधे प्रकट करने के बजाय List.unmodifiable(_items) क्यों प्रकट करें?notifyListeners के बिना, और इसलिए बिना रीबिल्ड के, स्टेट बदल देता।