<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های ramin bagherian</title>
        <link>https://virgool.io/feed/@ramin.bagheriian</link>
        <description>برنامه نویس اندروید ( جاوا یِ سابق, فلاتر الان )</description>
        <language>fa</language>
        <pubDate>2026-07-08 00:41:01</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1273598/avatar/2hllS6.jpeg?height=120&amp;width=120</url>
            <title>ramin bagherian</title>
            <link>https://virgool.io/@ramin.bagheriian</link>
        </image>

                    <item>
                <title>Multi Type Return Functions (record) در دارت 3</title>
                <link>https://virgool.io/@ramin.bagheriian/multi-type-return-functions-record-%D8%AF%D8%B1-%D8%AF%D8%A7%D8%B1%D8%AA-3-drmuya6tqwro</link>
                <description>امروز میخوایم در مورد record ها که در دارت 3 معرفی شد صحبت کنیم و ببینیم که اصلا چی هستن !   رکوردها شبیه به list ها هستن و میشه آرایه ای از داده هارو داخلشون ذخیره کرد و در جاهای مختلف استفاده کرد, البته با این تفاوت که دیتا تایپ و تعداد متغییر ها باید مشخص بشه !چجوری ؟ جلوتر میبینیم !تعریفشون مثل پارامتر های وردی متدها هستش و تفاوتی با اونا نداره که هم به صورت named parameter و هم به صورت معمول که هممون استفاده میکنیم تعریف مشن. شاید زیاد کاربردی به نظر نیاد و نشه همه جا ازش استفاده کرد, به نظر من بیشتر واسه کم کردن تعداد خط کدا خوبه ولی خب یادگیریش خالی از لطف نیست و ممکن یه جایی به درد بخوره !حالا بریم یه مثال بزنیم که کامل جا بیفته ! اول سناریو تعریف میکنیم بعد کد میزنیم ....نکته : مثالی که میزنم خیلی ساده طرح شده و صرفا واسه درک مطلب هستش و از نظر مهندسی نرم افزار درست نیستتصور کنین ما قراره از کاربر دو تا عدد بگیریم و 3 تا عملیات مختلف رو با 3 تا متد مختلف رو اون اعداد انجام بدیم که عبارتند از تقسیم اعداد, زوج بودن حاصل تقسیم و کانکت کردن عدد با یک رشته, که مقادیر بازگشتی هر متد برای قسمت خاصی از برنامه درنظر گرفته شده !پس تا اینجا شد 3 تا متد که مقادیر بازگشتی bool , String و double دارن و به شکل زیر نوشته میشن !خب متد ها آمادس و میشه ازشون استفاده کرد . این حالت عادیه که هممون بلدیم ! حالا اگه بخوایم همین کارو با record ها انجام بدیم چی ؟! خیلی ساده یه متد مینویسیم و به جایه یه مقدار بازگشتی, مقادیری که انتظار داریم برگرده رو در اول متد با پارانتز مشخص میکنیم به شکل زیر :نکته : من اینجا از named pramatere استفاده کردم, شما میتونی فقط دیتا تایپ مشخص کنی .... خب اینجا ما 3 تا متد رو به یک متد تبدیل کردیم, به یک متدی که 3 تا نوع داده مختلف برگشت میده.حالا داخل بدنه متد هر 3 عملیاتی که بالا تعریف کرده بودیم رو میتونیم پیاده سازی کنیم که میشه مثل کد پایین : همونطور که میبینین من اول عملیات تقسیم رو تو یه متغییر لوکال ذخیره کردم و بعد از return پارانتز باز کردم و نام پرامتر بازگشتی رو صدا زدم تا مقدار داخلش ست کنم !حالا چطور میشه از این متد استفاده کرد ؟! از این متد به دو روش میشه استفاده کرد, یا باید یه record دقیقا به همین شکلی که متد تعریف کردیم, تعریف کنیم و یا مستقیما متد رو صدا بزنیم و با دات مقدار مورد نظر رو فراخوانی کنیم,که الان به هر دو روش اینکارو انجام میدیم !روش اول ساخت record : ساخت رکورد دقیقا مثل تعریف متغییر هستش, با این تفاوت که اینبار به جای یه دیتا تایپ چندتا دیتا تایپ رو داخل پارانتز مشخص میکنیم ! به شکل زیر :همونطور که میبینین تو خط کد 33 من یه record رو به صورت late تعریف کردم که همون دیتا تایپ های بازگشتی متد myInfo رو داره و بعد داخل initState متد رو صدا زدم و record رو مقدار دهی کردم نکته : حتما حواستون باشه که اگه از named parameter ها استفاده میکنید, نام پارامتر های record با نام پارامتر های متد یکی باشه و اگه از named parameter استفاده نمیکنید حواستون به ترتیب تعریف دیتا تایپ ها باشه ! حالا هرجا که لازم باشه میتونیم record رو صدا بزنیم و به مقادیر داخلش دسترسی داشته باشیم مثل record.message یا record.isEven ... این از روش اول .روش دوم : صدا زدن خود متد myInfo هستش که زیاد کار منطقی به نظرم نمیاد ولی خوب میشه از این روش هم استفاده کرد مثلا :myInfo(12, 13).isEven; //return bool myInfo(12, 14).divition; // return double و در آخر این روش تو برنامه های بزرگ ممکنه مفهوم سالید رو زیره سوال ببره و اپ از حالت استاندارد خارج بشه چون همونطور که میدونین هر متد و هر کلاسی باید یه کار مشخص انجام بده نه چند کار پس حواستون به این موضوع هم باشه .خیلی ممنونم بخاطر وقتی که گذاشتین و این مقاله رو مطالع کردین امیدوارم که مفید بوده باشه موفق باشید .</description>
                <category>ramin bagherian</category>
                <author>ramin bagherian</author>
                <pubDate>Tue, 20 Jun 2023 17:27:34 +0330</pubDate>
            </item>
                    <item>
                <title>توضیحاتی کوتاه در مورد isolate و multi thread در فلاتر</title>
                <link>https://virgool.io/flutter-community/%D8%AA%D9%88%D8%B6%DB%8C%D8%AD%D8%A7%D8%AA%DB%8C-%DA%A9%D9%88%D8%AA%D8%A7%D9%87-%D8%AF%D8%B1-%D9%85%D9%88%D8%B1%D8%AF-isolate-%D9%88-multi-thread-%D8%AF%D8%B1-%D9%81%D9%84%D8%A7%D8%AA%D8%B1-orrzxmyf6ykb</link>
                <description>شاید برای شما این اتفاق افتاده باشه که تو یک بخشی از پروژه مجبور به انجام یک کار سنگین بشید مثلا تبدیل یه فایل با حجم بالا, به آرایه ای از Byte یا دانلود یه فایل با حجم بالا و یا انجام یک سری محاسبات پیچیده که ممکنه منابع زیادی رو اشغال کنه !خوب همه ما میدونیم که کل اپ ما تو یک thread ( حالا فارسیش میشه نخ  ولی در طول این مقاله از کلمه رشته برای اشاره به Thread استفاده میکنیم ) داره عمل میکنه که اصطلاحا بهش Main-Thread میگن و میشه گفت که اکثریت اتفاقات بر روی این رشته میفته از جمله رندر کردن UI و اگه وقفه ای تو این  عمل پیش بیاد ممکنه که به UX یا همان تجربه کاربری ما صدمه بزنه و حس خوبی به کاربر نده ...این دقیقا مشکلی بود که من تو یکی از پروژه هام باهاش روبرو شدم و بعد از خوندن چندتا مقاله و آزمون خطا بهرین راه رو ( حداقل از نظر خودم ) انتخاب کردم که همون isolate هستش !بریم یه سناریو طراحی کنیم تا تو عمل بهتر متوجه مشکل و راه حلش بشیم .تو سایت StackOverflow مثال واقعی تری در مورد isolate پیاده کردم که ممکنه تو درک بهتره این موضوع کمکتون کنهتصور کنین یه حلقه for داریم که میخوایم از ۰ تا ۴۰۰۰ رو برامون طی کنه !خب از اونجایی که این عمل تقریبا سنگین هستش, پس احتمال اینکه چند ثانیه وقفه تو اجرای برنامه داشته باشیم زیاده و اصطاحا یه Freeze کوتاه داشته باشیم ! کلاس Home خودمون رو می سازیم به ساده ترین شکل ممکن که شامل یک CircularProgressIndicator برای نشون دادن وقفه و یک دکمه برای اجرای حلقه.به این شکلو یه متد خیلی ساده برای حلقه for و متصل کردنش به onPressed دکمه خب ! پارامتر stop متد بالا رو روی ۴۰۰۰ تنظیم میکنیم بعد به دکمه وصلش میکنیم که بعد از کیلک با همچین صحنه ای روبرو میشم .. همون طور که تو gif بالا میبینید پروگرس برای چند ثانیه فریز شد و اون دقیقا لحظه کلیک روی دکمه بود .خب بریم سراغ راه حل برای حل این مشکل راه های زیادی وجود داره ولی ما از isolate استفاده میکنیم تا به هدفمون که یه نگاه کلی به isolate هستش رو برسیم. طبقه گفته خود فلاتر isolate ها مموری خودشون رو دارن و جدای از مموری اختصاص داده شده به اپ عمل میکنن و این باعث میشه که Main-Thread به مشکل نخوره ...تو این مقاله از Isolate.spawn استفاده میکنیم که ساده ترین و پایه ای ترین روش هستش بریم سراغ کد :اول کد هارو مینویسم بعد توضیح میدم !اول متد isolate رو ایجاد میکنیم به شکل زیرتو این متد ما یه نمونه از کلاس ReceiverPort میسازیم تا بتونیم به مقدار بازگشتی متدی که داخل isolate درحال اجراس دسترسی داشته باشیم !( من مثال رو یکم تغییر دادم که این حالت رو هم بتونیم بررسی کنیم و زیاد ساده نباشه )کلاس isolate یه متد static به اسم spawn داره که نوع بازگشتی isolate هستش و به صورت Asynchronous نوشته شده (Future)همون طور که تو خط کد های بالا میبینید متد for یا همون expensiveCalculate رو به عنوان پارامتر اول به spawn پاس دادیم و پارانتزی جلوش قرار ندادیم که یعنی این متد زمانی که خود isolate فراخوانی بشه اجرا میشه حتما حواستون به این باشه !و پارامتر دوم لیستی از نوع داده dynamic هستش خب حالا چرا لیست ؟ تو این روش ما نمیتونیم برای متد for بیشتر از یک پارامتر در نظر بگیریم و این در حالیه که ما علاوه بر مقدار stop  sendPort هم باید پاس بدیم این برای زمانی که مقدار بازگشتیه متد برامون مهم باشه در غیره این صورت میتونیم فقط مقدار stop حلقه رو که int هستش پاس بدیم !ولی اینجا ما میخوایم وقتی حلقه تموم شد یه مقدار String برامون برگرده پس حتما باید از port پراپرتی sendPort که یه getter از نوع کلاس SendPort هست و این getter در داخل کلاس ReciverPort در دسترس هستش و ما قبلا تعریفش کردیم رو به عنوان پارامتر پاس بدیم و همچنین مقدار stop حلقه رو... چی گفتم !؟ (((((: پس برای همین از لیست استفاده میکنیم . نکته : پارامتر دوم spawn از نوع Object که یعنی میتونیم کلاس یا مدل هم بهش پاس بدیم و کد تمیز تری بنویسیم نکته بعدی مقدار جنریک spawn هستش که اگه به قطعه کد پایین نگاه کنین دقیقا مشابه با پارامتر ورودی متد for هستش و بایدم باشه و در آخر قرار دادن نمونه گرفته شده از کلاس ReciverPort در حالت listen هستش که بتونیم مقدار نهایی رو از متد for بگیریم . این از کد بالا چیز دیگه ای برای توضیح نداره :)حالا کد های داخل متد for :داخل متد for مقادیر  stop و sendPort رو میگیریم و داخل یه متغیر ذخیره میکنیم !و در نهایت نتیجه متد رو که تو مثال ما مقدار done بود رو با sendPort به listener برمیگردونیم !نکته : حتما در آخر بعد از اینکه کارتون با isolate و port تموم شد هردو رو close کنین . نکته بعدی اینکه این متد دیگه نیاید داخل اسکپ هیچ کلاسی باشه و به اصطلاح Global-Function یا همون High-Level باید باشه با این روش دیگه عملیات های سنگین تاثیری تو UI و UX برنامتون نمیزاره و وقفه تو روند اجرای برنامه ایجاد نیمشه . خب امیدوارم که تونسته باشم حق مطلب رو درست ادا کنم و براتون مفید بوده باشه !و در نهایت ممنون از وقتی که گذاشتید برای مطالعه این مقالهموفق باشید . :) </description>
                <category>ramin bagherian</category>
                <author>ramin bagherian</author>
                <pubDate>Sat, 11 Feb 2023 23:00:07 +0330</pubDate>
            </item>
                    <item>
                <title>توضیحاتی در مورد microframework GetX در فلاتر</title>
                <link>https://virgool.io/@ramin.bagheriian/%D8%AA%D9%88%D8%B6%DB%8C%D8%AD%D8%A7%D8%AA%DB%8C-%D8%AF%D8%B1-%D9%85%D9%88%D8%B1%D8%AF-microframework-getx-%D8%AF%D8%B1-%D9%81%D9%84%D8%A7%D8%AA%D8%B1-hzyezjywhzgx</link>
                <description>نوشته شخصی &quot; این اولین پست من تو سایت ویرگول هستش و همچنین اولین مقالم امیدوارم که بتونم حق مطلب رو درست ادا کنم &quot;خب بریم سراغ بحث ...بیاین ببینیم اصلا GetX چی هست کلا ؟ یا اگه بخوایم ریزتر بشیم state چی هست ؟با یه مثال شروع کنیم : چه اتفاقی می افته وقتی کلید چراغ خونتون یا اتاقتون رو فشار میدین ؟خب از دید برنامه نویسی کلید و چراغ UI ما هستن ! و جریان برق logic سناریوی ما هستش و فشار دادن کلید event وقتی شما کلید رو فشار میدید در واقع وضعیت (state) اون کلید رو از خاموش به روشن و یا برعکس تغییر دادین و این باعث تغییری تو logic شده و state چراغ رو از خاموش به روشن یا برعکس عوض کرده پس تغییر وضعیت کلید باعث تغییر وضعیت چراغ شده .تو فلاتر تمام ویجت ها حول محور state میچرخه و هر تغییری که UI به خودش میگیره درواقع state اون UI یا Widget تغییر کرده مدیریت state یکی از مسائل مهم و البته پیچیده فلاتر به حساب میاد ساده ترین روش برای مدیریت استفاده از متد setState هستش که خب مشکلات خاص خودش رو داره مثل پرفورمنس پایین و فراخوانی متد build ولی کتابخونه های خوبی برای راحتی کار هستن که از این پیچیدگی تا حد زیادی کم کنن !مثلا : Proveider , Flutter BloC , Get it , Mobx و GetX .....کتابخونه یا همون microframework GetX یکی از معروفترین و ساده ترین های فلاتر هستش ( از نظر من )که امکانات زیادی داره و فقط state management نیست سه ستون اصلی GetX :1 . state management مدیریت وضعیت : در حالت کلی از دو روش برای مدیریت وضعیت استفاده میکنه اولی متد GetBuilder هستش که ساده ترینش هست و دومی استفاده از وضعیت واکنشی (reactive state) با استفاده از Getx یا Obx هستش که تو این مقاله درمورد هر دو روش صحبت میکنیم .2 . Route Management مدیریت مسیر :با GetX میشه بین صحفه های مختلف جابجا شد, SnackBar  , Dialog  , BottomSheet نمایش داد , و همه این کار هارو بدون نیاز به context انجام داد ( جالب شد نه ؟ D:) البته این مقاله فقط در مورد مدیریت وضعیت با GetX هستش ولی سعی میکنم یه مثال کوچیک در مورد این موارد هم بزنم و اگه این مقاله براتون مفید باشه مقالات بیشتری در این باره بنویسم.3 . Dependency Management مدیریت وابستگی :یکی از ساده ترین و قدرتمد ترین راه های مدیریت وابستگی استفاده از controller های GetX هستش که کلا با یک خط کد هندل میشه, و اجازه دسترسی به View رو بدون نیاز به Inherited Widget یا context رو میده, به زبان ساده GetX جلوی تکرار کد رو تا حد قابل قبولی میگیره. خب حالا بریم یه مثال با کد بزنیم ببینم این گفته ها تو عمل چه شکلی هستش :قدم اول ساخت یه پروژه خالی هستش که دیگه توضیح نمیدم چجوری اینو همه بلدیم ....قدم دوم اضافه کردن GetX به پروژه داخل فایل pubspec.yaml هستش از سایت pub.dev آخرین نسخه GetX رو به شکل زیر به پروژه اضافه کنین ( قندشکن لازم دارین این قسمت)dependencies:
    flutter:
         sdk: flutter
    get: ^4.6.1(درحال حاضر که من این مطلب رو مینویسم آخرین نسخه از این کتابخونه 4.6.1 هستش)حالا یا دستور flutter pub getرو تو ترمینال بنویسید یا فایل pubspec.yaml رو ( ctrl + s ) ذخیره کنین تا دانلود انجام بشه.قدم سوم عوض کردن ویجت MaterilApp به GetMaterialApp داخل کلاس main.dart هستش که بعد از اضافه کردن کتابخونه به پروژه در دسترس هست الان نتونستم با کد باکس خود ویرگول کنار بیام ....خب تا اینجا یه سری کار های اولیه و ابتدایی بود.اینجا ما یه ویجت تکس داریم و یک فلوتینگ باتن که قراره با هربار فشار دادن ( همون سناریوی چراغ و کلید که اول گفتم ) مقدار تکس ما رو تغییر بده یا همون state ویجت تکس ما تغییر کنه ! میدونیم که setState هم این کارو برامون انجام میده ولی اضافه بار داره, یعنی تمام ویجت هارو دوباره build میکنه در حالی که ما فقط نیاز داریم که ویجت تکس ما تغییر وضعیت بشه و دوباره ساخته بشه..خب اول از GetBuilder شروع میکنیم بعد میریم سراغ Obx :قدم چهارم ساخت یه کلاس کنترولر هستش که از GetxController ارثبری کرده باشه و مقادیری که قراره تغییر کنه رو داخلش تعریف میکنیمخوب ما اینجا کلاس MyController رو داریم که از کلاس GetxController ارثبری کرده و الان به متد های این کلاس دسترسی داره یه متغییر از نوع int داریم که مقدار مارو داخل خودش داره و قراره که با هربار کلیک روی دکمه مقدارش تغییر کنه و در نهایت یه getter تعریف کردیم که مقدار رو از این متغییر و کلاس بگیریم ( اجباری برای تعریف getter نیست من از رو عادت این کارو کردم میشه مستقیم مقدار counter رو بگیرین البته دیگه نباید private تعریف بشه تو این حالت )خب قدم پنجم : تعریف یک تابع هستش که عملیات افزایش رو برامون انجام بده و به ما notify کنه این موضوع رو یا به اصطلاح خبر بده به ویجت های مرتبطش واسه تغییر وضعیت متد incrementCounter یه متد خیلی سادس که فقط مقدار رو افزایش میده و در آخر هم update رو صدا میزنه. حالا این update چیکار میکنه رو اینجا نمیشه گفت چون واسه توضیحش لازمه کدهای کلاس main کامل بشه بعد ! پس این متد update رو یادتون نگه دارین تا بعدا برسیم بهش...قدم ششم : میریم سراغ کلاس main و ادامه کد ما گفتیم که میخوایم فقط ویجت Text ما تغییر وضعیت داده بشه و بقیه ویجت ها ثابت بمونن, واسه این کار کافیه ویجت Text رو داخل ویجت GetBuilder  قرار بدیم و کلاس MyController رو بهش تعریف میکنیم.GetBuilder داخل خودش متدی داره به نام builder builder درواقع از ما یه کنترولر میگیره و یه ویجت برمیگردونه که ما کنترولر رو به شکل زیر بهش معرفی کردیم GetBuilder&lt;MyController&gt; {
          builder: (_clr){
                  return Text(&#039; counter ${_clr.getCounter.toString()} &#039; );
         }
}درواقع clr_ نمونه ای از همون کلاس کنترولری هست که ما تعریف کردیم و الان به واسطه اون به مقادیر دسترسی داریم  و هر بار که متد update داخل اون کلاس صدازده میشه ویجت یا ویجت های داخل builder باز سازی میشه ولی با مقادیر جدید .پس حالا فهمیدیم که اون متد update تو کلاس MyController به چه دردی میخوره :)خب تا اینجا که همه چی اوکی شد .میریم سراغ دکمه که قرار کار افزایش رو برامون انجام بده  قدم هفتم : برای این کار لازمه که از کنترولر نمونه سازی انجام بدیم ولی به روشی که خود GetX گفته یعنی به شکل زیر :final _controller = Get.put(MyController());نمونه گیری تو GetX حالت های مختلفی داره که همرو نمشه تو یه مقاله گفت سعی میکنم بعدا درموردش توضیح بدم حالا ما یه نمونه از کلاس MyController با نام controller_ داریم و مسلما به متد ها هم دسترسی داریم شاید سوال بشه که چرا مقدار Text رو با همین نمونه که ساختیم عوض نکنیم ! جوابش سادس چون اگه این کار انجام بدیم دیگه state عوض نمیشه و فقط مقدار عوض میشه .. یعنی عملا تو UI چیزی تغییر نمیکنه !این GetBuilder هستش که state رو تغییر میده .اگه یادتون باشه ما یه متدی داشتیم به اسم incrementCounter حالا خیلی راحت داخل پراپرتی onPressed دکمه متد رو صدا میزنیمonPressed: (){
       _controller.incrementCounter();
}خب تبریک میگم شما الان یه state management هر چند خیلی ساده رو پیاده کردید ! :)خوب بریم سراغ Obx:روش Obx تقریبا مشابه روش بالاس با یه سری تفاوت های کوچیک ....بریم سراغش تو روش Obx ما همون کلاس MyController رو داریم ولی با یه تفاوت تو نوع متغییر ها متغییر هایی که تو این حالت تعریف میشن از نوع observable هستند و میشه گفت یه حالت استریم دارن ! یعنی دیگه نیازی به متد update نداریم . میریم سراغ کنترولر و تعریف متغییر کلمه کلیدی این متغییر ها با Rx شروع میشه و تقریبا همه Data type هارو شامل میشه !ما اینجا از RxInt استفاده میکنیم چون نوع دادمون عدد صحیح و بعد از مقدار دهی obs که مخفف observable هستش رو به آخر مقدار اضافه میکنیم !  و بعد داخل updateValue عملیات افزایش داده رو انجام میدمیم ! کل کنترولر شد 3 خط جذاب نیست؟ :)خب بریم سراغ کلاس main :داخل این کلاس اگه یادتون باشه ما یه ویجت GetBuilder داشتیم دقیقا همون ویجت رو یه Obx تغییر میدیم و builder رو هم حذف میکنیم ! خییییلی جمع و جور ساده :)Obx ( () Text( &amp;quot counter : ${_controller.counter.value} &amp;quot ) )کل اون GetBuilder شد این یک خط ولی فراموش نکینن که هنوزم به اون نمونه که از کلاس MyController ساختیم نیاز داریم و باید باشه .و نکته مهم بعدی اینکه واسه گرفتن مقدار از متغییر های نوع Rx یا observable حتما باید بعد از نام متغییر به value اشاره کنین تا مقدار گرفته بشه ..._controller.counter.value;این کلاس main که بجای GetBuilder از Obx استفاده شده . حالا بیاین با همین روش یه SnackBar نمایش بدیم به کاربر, ببینیم چطور بدون context میشه این کار کرد ؟  سناریو میخوایم وقتی مقدار counter به 3 رسید یه SnackBar نشون بدیم به کاربر و حالا یه متنی آزمایشی هم داشته باشه بریم سراغ کنترولر و متد update که به شکل لامبدا نوشتیم.کلاس Get به صورت پیشفرض متد هایی مثل Get.snackbar( title , description ) که برای ما یه snackBar بدون نیاز به context رو میده و همچنین امکان شخصی سازی هم داره و در کل میتونم بگم که از snackBar که از سمت scaffold میاد خییلی بهتره D: کلاس کنترولر رو به شکل زیر تغییر میدیم !همون طور که میبینین داخل متد updateValue با دستور if مقدار counter رو چک میکنیم که اگه به مقدار 3 یا بیشتر رسیده باشه snackBar نمایش داده بشه ...مقادیر ورودی snackBar که اجباری هستن title و decription هستش و به صورت پیشفرض از سمت بالا ظاهر میشه ولی قابل شخصی سازی هستش و تقریبا میتونین همه قسمت هارو تغییر بدین ...خب امیدوارم که از این مطلب لذت برده باشید و براتون مفید بوده باشه ! اگه استقبالی بشه سعی میکنم GetX رو به صورت کامل در حد اطلاعاتم توضیح بدم که دوستان علاقه مند بتونن استفاده کنن ...ممنون از وقتی که گذاشتین برای مطالعه این مقاله موفق باشید .</description>
                <category>ramin bagherian</category>
                <author>ramin bagherian</author>
                <pubDate>Fri, 18 Mar 2022 18:10:45 +0330</pubDate>
            </item>
            </channel>
</rss>