Theory
Doubt के दो Seconds
Book tap कीजिए, और FestConnect Flutter server में save करने में 2 seconds लेता है। दो seconds जिनमें एक unresponsive screen हर student को फिर tap कराती है: double bookings, support queue, chaos।
Unit 1 ने इसे Android पर ProgressBar और visibility juggling से solve किया। Flutter का version leaner है: 2 indicator widgets एक single parameter से split, और: क्योंकि यहाँ सब कुछ composition है: professional loading overlay, एक widget से बना जिसे आप पहले से जानते हैं: Stack, इस topic का दूसरा नाम।
Theory
2 Indicators, 1 Deciding Parameter
- LinearProgressIndicator: एक horizontal bar
- CircularProgressIndicator: spinner
दोनों एक switch obey करते हैं, value: parameter:
- value: null (या simply omitted): indeterminate: हमेशा के लिए animate होता है, सिर्फ़ "working" promise करता है: unknowable durations (network saves) के लिए सही
- value: 0.0 से 1.0: determinate: वह fraction display करता है: 5 में से 3 pass photos uploaded होने पर value: 0.6
Scale नोटिस कीजिए: 0 से 1 एक double की तरह, Android के setMax(100)/setProgress(60) की तरह नहीं: अलग units वाला Unit 1 twin, और एक favourite compare question।
Practical
Loading Overlay: Stack + Indicator + एक Bool
class _BookingState extends State<BookingScreen> {
bool saving = false;
void book() {
setState(() { saving = true; }); // show the overlay
saveToServer().then((_) {
setState(() { saving = false; }); // hide in the completion path
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
bookingForm(), // the page itself
if (saving) ...[ // conditional children
Positioned.fill( // translucent blanket
child: Container(color: Colors.black54),
),
const Center( // the spinner on top
child: CircularProgressIndicator(), // value: null = spins
),
],
],
);
}
}
// Determinate cousin, for the 5-photo upload:
// LinearProgressIndicator(value: uploaded / 5) // 3 of 5 -> 0.6
Theory
Stack, Deeper Pass
Invisible-widgets lesson ने Stack को FrameLayout के twin की तरह introduce किया; overlay इसके 2 power tools इस्तेमाल करता है:
- Positioned.fill: एक child को पूरे stack के ऊपर stretch करता है: translucent Container पूरे form को blanket करता है, stray taps absorb करते हुए
- non-positioned children stack के alignment obey करते हैं (या एक Center wrapper, जैसे यहाँ): spinner mid-screen float करता है
और children list के अंदर conditional if (saving) ...[ ] उन widgets के लिए Flutter का idiom है जो सिर्फ़ कभी-कभी exist करते हैं: bool decide करता है, setState इसे flip करता है, rebuild overlay add या remove करता है: state STRUCTURE decide कर रहा है, सिर्फ़ values नहीं।
Quiz
CircularProgressIndicator() और CircularProgressIndicator(value: 0.6) के बीच क्या फ़र्क है?
- कोई नहीं: value सिर्फ़ size बदलता है
- पहला हमेशा spin करता है (indeterminate); दूसरा fixed 60% arc दिखाता है (determinate)
- पहला invisible है जब तक value supply न हो
- value: 0.6 इसे 60% speed पर spin कराता है
Show the answer
पहला हमेशा spin करता है (indeterminate); दूसरा fixed 60% arc दिखाता है (determinate)
एक parameter पूरा semantic split carry करता है: null/omitted मतलब है "working, duration unknown": eternal animation: जबकि 0-to-1 double मतलब है "यह exact fraction done है": 60% पर एक still arc। इनके बीच choose करना आप जो जानते हैं उसके बारे में honesty है: एक network save indeterminate है, एक 5-photo upload measurably determinate है (uploaded / 5)। Options C और D behaviours invent करते हैं: indicator built होते ही हमेशा visible है, और value कभी speed modulate नहीं करता। और Android veterans के लिए scale trap याद रखिए: 0.6, कभी 60 नहीं।
Think first
Overlay का Life Cycle Audit कीजिए
Listing के book() flow को walk कीजिए: कब क्या appear होता है, black54 Container dimming के अलावा actually क्या contribute करता है, और: Unit 1 के Android ProgressBar rule को याद करते हुए: यह simplified code अभी कौन सा failure path handle नहीं कर रहा?
Show the answer
Tap: setState(saving = true): rebuild blanket + spinner add करता है: save इनके पीछे चलता है: .then false setState करता है: rebuild दोनों remove करता है। Container की दूसरी job armour है: Positioned.fill मतलब यह हर tap INTERCEPT करता है, तो double-booking double-tap blanket पर मर जाता है। Missing path: failure: अगर saveToServer error देता है, .then कभी नहीं चलता और overlay हमेशा के लिए spin करता है: Unit 1 का rule (हर outcome path में hide कीजिए) एक .catchError माँगता है जो saving = false भी setState करे: eternal-spinner bug, Flutter edition।
Watch out
Indicator और Overlay Slips
value: 60: 0-to-1 scale का मतलब है 60 clamped nonsense है; fractions, percentages नहीं।
बिना Blanket के Overlay: एक live form के ऊपर एक naked spinner फिर भी taps through जाने देता है: Positioned.fill Container tap shield है।
सिर्फ़ Success पर Hide करना: reveal का eternal spinner: हर path (success, error) को flag lower करनी चाहिए।
Measurable Work के लिए Indeterminate: एक mystery spinner वाला 5-photo upload वह information waste करता है जो user को पसंद आती।
Theory
Composition Flutter का Answer है
नोटिस कीजिए Flutter ने आपको क्या NAHI दिया: एक LoadingOverlay widget। इसने आपको दिया Stack, Positioned.fill, एक Container, एक indicator और एक bool: और overlay इनकी COMPOSITION है, 10 honest lines। यही framework का philosophy एक exhibit में है: कम primitives, infinite assemblies: Unit 1 के hand-composed ImageSlider जैसा वही lesson। अगला: fest की event list एक आख़िरी बार लौटती है: Flutter की Lists, जहाँ ListView.builder उस adapter story को complete करता है जो इस subject के बिल्कुल पहले lesson में शुरू हुई थी।
Summary
Key takeaways
- LinearProgressIndicator = bar, CircularProgressIndicator = spinner; एक widget family, 2 shapes।
- value: null/omitted = indeterminate (हमेशा spin करता है); value: 0.0-1.0 = determinate fraction: 0-to-1, कभी 0-to-100 नहीं।
- Unknowable waits (network) के लिए indeterminate, measurable ones (5 में से n uploads) के लिए determinate।
- Loading overlay = Stack + Positioned.fill translucent Container (tap shield) + centered spinner + एक saving bool।
- एक children list में if (cond) ...[ ]: state structure decide कर रहा है।
- Overlay को हर completion path में hide कीजिए वरना यह हमेशा के लिए spin करता है।
- Memory hook: null spins, fractions fill, blanket stray taps खाता है।