⚡️⚡️Flutter Key⚡️⚡️
1️⃣3️⃣ LocalKey
کد های بالا رو با دقت بخونید.
میبینید که یه Stateful به نام ColoredStatefulWidget داریم .
این ویجت قراره یه مربع 150 * 150 با یه رنگی که توی state (initState) به صورت random تعیین میشه نمایش بده و وسط مربع هم یه label نمایش میده که از widget میگیره.
توی HomePage هم یه Column داریم که قراره یه لیست دو تایی از این ویجت رو نمایش بده و وقتی که روی floating زدیم index ویجت ها رو تغییر بده .
✔️تصویر اول اولین خروجی و تصویر دوم خروجی بعد از زدن روی floating هست.
میبینید که label ها جابجا میشن ولی رنگ ها جابجا نمیشن.
این هم متد generateRandomColor که توی عکس ها مشخص نیست :
Color _generateRandomColor() {
var random = Random();
return Color.fromARGB(
255,
random.nextInt(255),
random.nextInt(255),
random.nextInt(255),
);
}
1️⃣3️⃣ LocalKey
کد های بالا رو با دقت بخونید.
میبینید که یه Stateful به نام ColoredStatefulWidget داریم .
این ویجت قراره یه مربع 150 * 150 با یه رنگی که توی state (initState) به صورت random تعیین میشه نمایش بده و وسط مربع هم یه label نمایش میده که از widget میگیره.
توی HomePage هم یه Column داریم که قراره یه لیست دو تایی از این ویجت رو نمایش بده و وقتی که روی floating زدیم index ویجت ها رو تغییر بده .
✔️تصویر اول اولین خروجی و تصویر دوم خروجی بعد از زدن روی floating هست.
میبینید که label ها جابجا میشن ولی رنگ ها جابجا نمیشن.
این هم متد generateRandomColor که توی عکس ها مشخص نیست :
Color _generateRandomColor() {
var random = Random();
return Color.fromARGB(
255,
random.nextInt(255),
random.nextInt(255),
random.nextInt(255),
);
}
⚡️⚡️Flutter Key⚡️⚡️
1️⃣4️⃣ LocalKey
حالا کلاس _HomePageState رو تغییر میدیم.
و موقع ساخت ویجت ها توی initState بهشون key میدیم.
همون طور که خروجی رو در دو حالت میبینید (اول کار و بعدن setState و تغییرindex ها) علاوه بر label ها رنگ ها هم جابجا مین.
1️⃣4️⃣ LocalKey
حالا کلاس _HomePageState رو تغییر میدیم.
و موقع ساخت ویجت ها توی initState بهشون key میدیم.
همون طور که خروجی رو در دو حالت میبینید (اول کار و بعدن setState و تغییرindex ها) علاوه بر label ها رنگ ها هم جابجا مین.
⚡️⚡️Flutter Key⚡️⚡️
1️⃣5️⃣ LocalKey
حالا توی مثال بعدی یه تغییر دیگه میدیم :
ویجت ها رو میگذاریم داخل یه ویجت Builder.
ویجت Builder یه Stateless هست.
در کمال ناباوری میبینیم که با هربار setState رنگهای جدید تولید میشن.(label ها جابجا میشن)
1️⃣5️⃣ LocalKey
حالا توی مثال بعدی یه تغییر دیگه میدیم :
ویجت ها رو میگذاریم داخل یه ویجت Builder.
ویجت Builder یه Stateless هست.
در کمال ناباوری میبینیم که با هربار setState رنگهای جدید تولید میشن.(label ها جابجا میشن)
⚡️⚡️Flutter Key⚡️⚡️
1️⃣6️⃣ LocalKey
✔️این مورد رو اینجوری حل میکنیم.
به جای اینکه key رو به stateful ها اختصاص بدیم به builder ها اختصاص میدیم.
🔥پس key رو باید به فرزند اصلی لیست (اینجا column) بدیم.
1️⃣6️⃣ LocalKey
✔️این مورد رو اینجوری حل میکنیم.
به جای اینکه key رو به stateful ها اختصاص بدیم به builder ها اختصاص میدیم.
🔥پس key رو باید به فرزند اصلی لیست (اینجا column) بدیم.
⚡️⚡️Flutter Key⚡️⚡️
1️⃣7️⃣ LocalKey
🔥پس هر وقت یه لیست از Stateful های هم نوع داشتیم که قرار بود order شون تغییر کنه.
توجه کنید
✔️حتمن stateful باشن (stateful ها یا فرزند اصلی لیست باشن یا مثل مثال بالا از نوادگان لیست باشن)
✔️هم نوع باشن.
در این حالت از LocalKey ها استفاده میکنیم.
🔥🔥و نکته مهم طبق مثال های بالا این هست که key رو باید به فرزندان اصلی لیست بدیم.
این مثال هایی که زدیم مشابهش توی گوگل و یوتیوب هست.
ولی مهم مفهومه و اینکه چرا این اتفاقات میوفته که ان شالله بعدن بهش میپردازیم.
❌فقط توی همین مورد از این key ها استفاده کنید و جای دیگه لازم نیست.
❌فقط و فقط جاهایی که یه ویجت قراره چند تا فرزند بگیره (children) و قراره این اتفاقات بیوفته.
باید فرزندها key بگیرن.
اون هم از نوع Local .
ویجت های تک فرزندی نیاز ندارن که فرزندشون LocalKey داشته باشه به هیچ وجه.
🔥مگر اینکه جایی خود فلاتر برای کار دیگه ای اجبار کنه که به فلان ویجت حتمن key بدید.
#key
#flutter_key
#local_key
#global_key
1️⃣7️⃣ LocalKey
🔥پس هر وقت یه لیست از Stateful های هم نوع داشتیم که قرار بود order شون تغییر کنه.
توجه کنید
✔️حتمن stateful باشن (stateful ها یا فرزند اصلی لیست باشن یا مثل مثال بالا از نوادگان لیست باشن)
✔️هم نوع باشن.
در این حالت از LocalKey ها استفاده میکنیم.
🔥🔥و نکته مهم طبق مثال های بالا این هست که key رو باید به فرزندان اصلی لیست بدیم.
این مثال هایی که زدیم مشابهش توی گوگل و یوتیوب هست.
ولی مهم مفهومه و اینکه چرا این اتفاقات میوفته که ان شالله بعدن بهش میپردازیم.
❌فقط توی همین مورد از این key ها استفاده کنید و جای دیگه لازم نیست.
❌فقط و فقط جاهایی که یه ویجت قراره چند تا فرزند بگیره (children) و قراره این اتفاقات بیوفته.
باید فرزندها key بگیرن.
اون هم از نوع Local .
ویجت های تک فرزندی نیاز ندارن که فرزندشون LocalKey داشته باشه به هیچ وجه.
🔥مگر اینکه جایی خود فلاتر برای کار دیگه ای اجبار کنه که به فلان ویجت حتمن key بدید.
#key
#flutter_key
#local_key
#global_key
#quiz #statefulwidget #state_life_cycle
آیا توی initState یه State class به BuildContext دسترسی داریم؟
آیا توی initState یه State class به BuildContext دسترسی داریم؟
Anonymous Quiz
53%
بله
47%
خیر
Quiz
کوییز(سطح آسان)
وقتی برای اولین بار یه State class ساخته میشه کدوم یک از موارد زیر قبل از همه اجرا میشه؟
کوییز(سطح آسان)
وقتی برای اولین بار یه State class ساخته میشه کدوم یک از موارد زیر قبل از همه اجرا میشه؟
Anonymous Quiz
50%
State constructor
42%
initState
8%
build
Quiz
کوییز(سطح متوسط)
در اولین اجرای یه State class کدوم متد بعد از initState و قبل از build اجرا میشه؟
کوییز(سطح متوسط)
در اولین اجرای یه State class کدوم متد بعد از initState و قبل از build اجرا میشه؟
Anonymous Quiz
29%
didUpdateWidget
47%
didChangeDependencies
24%
activate
Quiz
کوییز (سطح متوسط)
توی یه State class تصمیم دارم یه سری color تعریف و اون رو با استفاده از theme مقدار دهی کنم. توی کدوم یک از متد های زیر Theme.of رو صدا بزنم؟ ( دلیل انتخابت رو کامنت کن)
کوییز (سطح متوسط)
توی یه State class تصمیم دارم یه سری color تعریف و اون رو با استفاده از theme مقدار دهی کنم. توی کدوم یک از متد های زیر Theme.of رو صدا بزنم؟ ( دلیل انتخابت رو کامنت کن)
Anonymous Quiz
32%
initState
26%
didUpdateWidget
35%
didChangeDependencies
8%
activate
Quiz
کوییز (سطح متوسط)
ایا در یه State class همیشه قبل از متد dispose متد deactivate اجرا میشه؟
کوییز (سطح متوسط)
ایا در یه State class همیشه قبل از متد dispose متد deactivate اجرا میشه؟
Anonymous Quiz
41%
بله
59%
خیر
⚡️چرخه حیات State ، مختصر ، کامل و دقیق⚡️
1⃣mount
اولین بار که یک stateful ساخته میشه و توی درخت قرار میگیره متد های زیر از state به ترتیب اجرا میشن :
State Constructor
initState
didChangeDependencies
build
❌توی هر سه متد بالا به context دسترسی داریم و میتونیم با context کار کنیم.
برخلاف تصور و اشتباه رایج خیلی ها که میگن داخل initState به context دسترسی نداریم.
🔥فقط اگه میخاستیم به یه inheritedWidget وابسته بشیم مثلن theme.of رو صدا بزنیم این کار رو باید توی دو متد didChangeDependencies یا build انجام بدیم.
🔥همیچنین توی متد های بالا با استفاده از پروپرتی widget میتونیم به ویجت این State دسترسی داشته باشیم.
2⃣setState
هر بار که توی استیت setState صدا زده بشه متد build یکبار دیگه اجرا میشه.
3⃣update
هر بار که ویجت parent این stateful این ویجت رو با یه کانفیگ جدید اپدیت کنه متدهای زیر اجرا میشن :
didUpdateWidget (Widget oldWidget)
build
ویجت parent این ویجت اپدیت شده و child خودش که همین stateful ما هست رو با یه ویجت جدید از همین type اپدیت کرده (ویجت ها immutable هستن)
در نتیجه didUpdateWidget اجرا میشه که به state اطلاع بده که ویجتت اپدیت شده.
توی ورودی هم ویجت قبلی (stateful قبلی /oldWidet) رو بهش میده.
ویجت جدید هم از طریق پروپرتی widget قابل دسترسیه.
4⃣dependencies changed
اگه این ویجت به یه InheritedWidget وابسته شده باشه مثلن Theme.of رو با context خودش صدا زده باشه.
هر بار که اون InheritedWidget اپدیت بشه و این اپدیت شدن رو به درخت زیر خودش نوتیف بده متد های زیر به ترتیب اجرا میشن :
didChangeDependencies
build
5⃣deactivate
هر بار که ویجت parent این ویجت تصمیم بگیره این نقطه از درخت رو با یه ویجت جدید جایگزین کنه یا کلن این ویجت رو حذف کنه و دیگه این ویجت بدردش نخوره این ویجت رو غیر فعال میکنه و از درخت حذف میکنه و در این مرحله متد زیر اجرا میشه :
deactivate
🔥در این مرحله هنوز متد dispose اجرا نمیشه و فقط deactivate اجرا میشه.
6⃣activate
اگه به این ویجت یه GlobalKey داده باشیم بعد از deactivate شدن ممکنه یه جای دیگه از درخت (با یه parent) دیگه به یه ویجت از این نوع و همین GlobalKey نیاز داشته باشه.
در نتیجه این ویجت activate میشه و توی اون نقطه از درخت مورد استفاده قرار میگیره و parent اش نسبت به قبل تغییر میکنه.(این اتفاق یعنی پیوند زدن به یه جای دیگه درخت حتمن باید توی همین فریم اتفاق بیفته که ویجت deactivate شده)
درنتیجه متد زیر توی state اجرا میشه :
activate
بعد از این متد هم متد
build
اجرا میشه و اگه این ویجت توی اجرای قبلی به یه inheritedWidget وابسته شده باشه قبل build هم متد زیر اجرا میشه :
didChangeDependencies
پس یا :
activate
build
یا
activate
didChangeDependencies
build
بسته به شرایط اجرا میشن.
7⃣unmount
اگه بعد از deactivate شدن و تا پایان این فریم این ویجت به هیچ جای دیگه پیوند نخوره (GlobalKey نداشته باشه یا لازم نشه که پیوند بخوره) متد زیر اجرا میشه :
dispose
و state برای همیشه میره پی کارش و غیر قابل استفاده میشه.
❌پس بلافاصله بعد از متد deactivate متد dispose اجرا نمیشه.
یه فاصله ای بینشون هست.
فاصله خیلی کم و در حد میلی ثانیه هست ولی بین اجرای این دو فاصله هست.
🔥همیشه قبل از dispose متد deactivate اجرا میشه ولی الزامن همیشه بعد از deactivate متد dispose اجرا نمیشه.
پس :
🔥توی initState هم به context دسترسی داریم.
🔥وابسته شدن به InheritedWidget رو حتمن توی didChangeDependencies یا build انجام میدیم.
🔥توی متد های deactivate و dispose کارهایی که مربوط به context میشه رو انجام نمیدیم (چون widget tree اون موقع statble نیست و در واقع این ویجت parent خودش رو از دست داده و parent نداره)
🔥کارهایی مثل dispose کردن کنترلر ها و ... رو توی متد dispose انجام میدیم و نه deactivate چون بعد از deactivate ممکنه دوباره به درخت برگرده و reperent بشه.
🔥در صورتی که ویجت GlobalKey داشته باشه (فقط GlobalKey) ممکنه بعد از deactivate شدن reparent بشه و به یه parent دیگه پیوند بخوره و مجددن activate بشه(که در این صورت state حفظ میشه)
#state_life_cycle
1⃣mount
اولین بار که یک stateful ساخته میشه و توی درخت قرار میگیره متد های زیر از state به ترتیب اجرا میشن :
State Constructor
initState
didChangeDependencies
build
❌توی هر سه متد بالا به context دسترسی داریم و میتونیم با context کار کنیم.
برخلاف تصور و اشتباه رایج خیلی ها که میگن داخل initState به context دسترسی نداریم.
🔥فقط اگه میخاستیم به یه inheritedWidget وابسته بشیم مثلن theme.of رو صدا بزنیم این کار رو باید توی دو متد didChangeDependencies یا build انجام بدیم.
🔥همیچنین توی متد های بالا با استفاده از پروپرتی widget میتونیم به ویجت این State دسترسی داشته باشیم.
2⃣setState
هر بار که توی استیت setState صدا زده بشه متد build یکبار دیگه اجرا میشه.
3⃣update
هر بار که ویجت parent این stateful این ویجت رو با یه کانفیگ جدید اپدیت کنه متدهای زیر اجرا میشن :
didUpdateWidget (Widget oldWidget)
build
ویجت parent این ویجت اپدیت شده و child خودش که همین stateful ما هست رو با یه ویجت جدید از همین type اپدیت کرده (ویجت ها immutable هستن)
در نتیجه didUpdateWidget اجرا میشه که به state اطلاع بده که ویجتت اپدیت شده.
توی ورودی هم ویجت قبلی (stateful قبلی /oldWidet) رو بهش میده.
ویجت جدید هم از طریق پروپرتی widget قابل دسترسیه.
4⃣dependencies changed
اگه این ویجت به یه InheritedWidget وابسته شده باشه مثلن Theme.of رو با context خودش صدا زده باشه.
هر بار که اون InheritedWidget اپدیت بشه و این اپدیت شدن رو به درخت زیر خودش نوتیف بده متد های زیر به ترتیب اجرا میشن :
didChangeDependencies
build
5⃣deactivate
هر بار که ویجت parent این ویجت تصمیم بگیره این نقطه از درخت رو با یه ویجت جدید جایگزین کنه یا کلن این ویجت رو حذف کنه و دیگه این ویجت بدردش نخوره این ویجت رو غیر فعال میکنه و از درخت حذف میکنه و در این مرحله متد زیر اجرا میشه :
deactivate
🔥در این مرحله هنوز متد dispose اجرا نمیشه و فقط deactivate اجرا میشه.
6⃣activate
اگه به این ویجت یه GlobalKey داده باشیم بعد از deactivate شدن ممکنه یه جای دیگه از درخت (با یه parent) دیگه به یه ویجت از این نوع و همین GlobalKey نیاز داشته باشه.
در نتیجه این ویجت activate میشه و توی اون نقطه از درخت مورد استفاده قرار میگیره و parent اش نسبت به قبل تغییر میکنه.(این اتفاق یعنی پیوند زدن به یه جای دیگه درخت حتمن باید توی همین فریم اتفاق بیفته که ویجت deactivate شده)
درنتیجه متد زیر توی state اجرا میشه :
activate
بعد از این متد هم متد
build
اجرا میشه و اگه این ویجت توی اجرای قبلی به یه inheritedWidget وابسته شده باشه قبل build هم متد زیر اجرا میشه :
didChangeDependencies
پس یا :
activate
build
یا
activate
didChangeDependencies
build
بسته به شرایط اجرا میشن.
7⃣unmount
اگه بعد از deactivate شدن و تا پایان این فریم این ویجت به هیچ جای دیگه پیوند نخوره (GlobalKey نداشته باشه یا لازم نشه که پیوند بخوره) متد زیر اجرا میشه :
dispose
و state برای همیشه میره پی کارش و غیر قابل استفاده میشه.
❌پس بلافاصله بعد از متد deactivate متد dispose اجرا نمیشه.
یه فاصله ای بینشون هست.
فاصله خیلی کم و در حد میلی ثانیه هست ولی بین اجرای این دو فاصله هست.
🔥همیشه قبل از dispose متد deactivate اجرا میشه ولی الزامن همیشه بعد از deactivate متد dispose اجرا نمیشه.
پس :
🔥توی initState هم به context دسترسی داریم.
🔥وابسته شدن به InheritedWidget رو حتمن توی didChangeDependencies یا build انجام میدیم.
🔥توی متد های deactivate و dispose کارهایی که مربوط به context میشه رو انجام نمیدیم (چون widget tree اون موقع statble نیست و در واقع این ویجت parent خودش رو از دست داده و parent نداره)
🔥کارهایی مثل dispose کردن کنترلر ها و ... رو توی متد dispose انجام میدیم و نه deactivate چون بعد از deactivate ممکنه دوباره به درخت برگرده و reperent بشه.
🔥در صورتی که ویجت GlobalKey داشته باشه (فقط GlobalKey) ممکنه بعد از deactivate شدن reparent بشه و به یه parent دیگه پیوند بخوره و مجددن activate بشه(که در این صورت state حفظ میشه)
#state_life_cycle
#quiz
#state_life_cycle
توی کد بالا یه کلاس HomePage از نوع استیت فول داریم که از یه اسکفلد تشکیل شده که توی body اون یه استیت فول دیگه به اسم HomePageBody قرار داره و یه floatingActionButton هم داریم که با تپ کردنش setState روی Homepage اعمال میشه....
#state_life_cycle
توی کد بالا یه کلاس HomePage از نوع استیت فول داریم که از یه اسکفلد تشکیل شده که توی body اون یه استیت فول دیگه به اسم HomePageBody قرار داره و یه floatingActionButton هم داریم که با تپ کردنش setState روی Homepage اعمال میشه....
با تپ کردن FloatingActionButton به ترتیب کدوم متد ها از _HomePageBodyState اجرا میشن؟
Anonymous Quiz
11%
build
16%
initState / build
23%
didChangeDependencies / build
20%
initState / didChangeDependencies / build
20%
didUpdateWidget / build
0%
activate / build
11%
activate / didChangeDependencies / build