سلام.
امروز میخوام در مورد یکی از عادت هام در برنامه نویسی صحبت کنم و اونم اینه که سعی میکنم تا حدی سورس کد فریم ورکی که ازش استفاده میکنم رو بخونم. و اومدم که این کار رو به شما هم توصیه کنم چون این کار باعث میشه دید بهتری نسبت به فریمورک تون داشته باشید و بتونید کد بهینه تری بنویسید و عملکرد برنامه رو توی حالت های خاص بهتر پیشبینی کنید و در کنار اینها ممکنه از نویسندگان فریمورک یه چیزایی یاد بگیرید و ایده های جدید بیاد توی ذهنتون. چند وقت پیش هم یکم از فلاتر رو خوندم و به نظرم رسید که میتونم با نوشتن فرایندی که طی کردم هم به فلاتر کار ها یه نکته در مورد فلاتر بگم هم بقیه برنامه نویس هایی که این عادت رو ندارن با نحوه ی کار آشنا کنم که شاید به دردتون بخوره.
توی فلاتر برای بخش هایی از UI که با عوض شدن دیتا آپدیت میشن یه تابع داریم به اسم setState که یه high order function هست و یک تابع رو به عنوان ورودی از ما میگیره. حالا ما توی اون تابعی که بهش پاس میدیم میایم بخشی از دیتایی که widget داره ازش استفاده میکنه رو آپدیت میکنیم و بعد از تموم شدن اجرا تابع در اولین فرصت (فریم بعدی که میخواد رندر بشه) widget ماهم آپدیت میشه و دیتای جدید و نشون میده.
این موضوع خیلی جادویی به نظر میرسه.
فلاتر از کجا میفهمه که من چه بخشی از دیتا رو توی اون call back تغییر دادم که بره و اون رو آپدیت کنه.
برای پیدا کردن جواب از قابلیت jump to definition استفاده میکنیم. این قابلیت شما رو به جایی که یک تابع تعریف شده میبره. بسته به IDE یا Text editor ی که استفاده میکنید ممکنه short key های مختلفی برای این کار باشه (اگه نمیدونید چجوریه احتمالا با ctrl + click به نتیجه میرسید).
حالا میایم jump to definition رو روی تابع setState اجرا میکنیم که ببینیم توش چه خبره:
یسری assert هست که کاری باهاش نداریم. و در نهایت:
اولش که تابع مارو صدا میزنه.
بعدش داره تابع markNeedsBuild رو صدا میزنه.
پس بریم ببینیم چه خبره مهم تر از بادی تابع اون کامنت های بالاشه دقت کنید که چی نوشته:
میگه: این ویجت رو به لیست ویجت هایی که توی فریم بعدی میخوایم rebuild کنیم اضافه میکنه.
یه نکته بامزه هم هست اونم اینه کن توضیح داده که چرا اینجوری نوشتنش:
میگه: میخوایم جلوگیری کنیم از اینکه یه ویو دو بار بیلد بشه در یک بار رندر کردن فریم.
این موضوع خودش دوتا درس داره:
یک: اینکه اگه کار مشابهی خواستیم بکنیم از این روش استفاده کنیم.
دو: همیشه توضیح بدیم که چرا این کارو کردیم که بعدا خودمون یا همکارامون بفهمن چرا این کد این شکلیه و حذف اش نکنن?
حالا کامنت بالای خود تابع setState رو بخونیم:
میگه: به فریمورک خبر میده که وضعیت این آبجکت تغییر کرده.
دقت کنید که نمیگه کجاش تغییر کرده. فقط میگه تغییر کرده.
پس جواب سوالی که فلاتر چطوری جادویی میفهمه که کدوم بخش هارو باید آپدیت کنه اینه که فلاتر اصلا نمیفهمه که کدوم بخش هارو باید آپدیت کنه و کل widget ای که توش تابع setState صدا زده شده رو از اول میسازه و جایگزین میکنه.
دومین نتیجه گیری هم اینه که از اینکه چند بار بدون فاصله و پشت سر هم setState صدا کنیم نگران نباشیم چون این باعث نمیشه که چند بار build اتفاق بیوفته.
پس طبق چیزایی که فهمیدیم اگر ما به جای این:
بیایم از این استفاده کنیم:
هیچ فرقی نباید بکنه.
که واقعا هم هیچ فرقی نمیکنه و این فرضیه ی مارو اثبات میکنه.
پس در نهایت میتونیم تابع setState با پارامتری با بدنه خالی رو مثل تابع rebuild در نظر بگیریم و هرجا که نیاز به اپدیت داریم صداش بزنیم.
پ ن: حتی میتویم یه extention function براش بنویسیم و تابع rebuild رو به State اضافه کنیم.
پس ما هر چی بیایم widget های جزئی تر و کوچکتر بنویسیم پرفورمنس برنامه ما بهتر میشه چون اگر یه بخش UI نیاز به build شدن داشته باشه دیگه فقط همون بخش build میشه و بقیه بخش ها دیگه الکی build نمیشن.
در بدترین حالت اگه شما کل برنامه رو اگر توی یه widget بنویسید فلاتر برای آپدیت کردن هر بخش کوچیک از UI مجبوره کللل برنامه رو از اول بسازه و محاسبات مربوط به render و… رو انجام بده که این خیلی خیلی بده.
این پست رو دیگه همینجا تموم میکنم.
امیدوارم مفید بوده باشه.
پایدار باشید.