<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمد صادق مهرافزون</title>
        <link>https://virgool.io/feed/@mohaammaadsadeq</link>
        <description>Android developer</description>
        <language>fa</language>
        <pubDate>2026-07-06 11:03:53</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/472315/avatar/6UMRbe.jpg?height=120&amp;width=120</url>
            <title>محمد صادق مهرافزون</title>
            <link>https://virgool.io/@mohaammaadsadeq</link>
        </image>

                    <item>
                <title>کتابخانه‌ی Compose DatePicker Persian</title>
                <link>https://virgool.io/@mohaammaadsadeq/%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%DB%8C-compose-datepicker-persian-bk7lsjzppozp</link>
                <description>سلام دوستانخوشحالم کتابخونه جدیدم رو باهاتون به اشتراک میزارم:کتابخونه ای که نوشتم یک DatePicker BottomSheet شمسی برای Jetpack Compose هست که تجربه‌ای روان، ساده و حرفه‌ای برای انتخاب تاریخ در اپلیکیشن‌های فارسی فراهم می‌کنه.✨ ویژگی‌ها✅ تقویم شمسی کامل و قابل استفاده در Jetpack Compose🌐 پشتیبانی کامل از زبان فارسی (روزها، ماه‌ها، اعداد)📅 خروجی‌های تاریخ با فرمت شمسی و میلادی🖋️ فونت فارسی سفارشی با چند وزن متفاوت⚙️ ساختار بهینه و قابل استفاده در پروژه‌های Compose📆 پشتیبانی از حالت انتخاب ماه و سال بدون نمایش انتخاب روز (برای زمانی که نیاز به انتخاب روز نیست)🎨 امکان شخصی‌سازی کامل ظاهر، رنگ‌ها، فونت، اندازه‌ها و نحوه نمایش 📆 قابلیت تعیین تاریخ پیش فرض اولیه برای انتخاب خودکار هنگام باز شدن تقویم شمسی مناسب برای مواقعی که کاربر قبلاً تاریخی انتخاب کرده و اکنون میخواهد آن را ویرایش کند.خوشحال می‌شم اگر استفاده کردید، بازخورد و ستاره بدید اگر هم فکر می‌کنید این ابزار می‌تونه به کار بقیه هم بیاد براشون بفرستید. 🙌🙏✌ (:برای اطلاعات بیشتر و استفاده از این کتابخونه روی لینک زیر کلیک کنید:https://github.com/MohammadSadeghMehrafzoon/ComposeDatePickerپ.ن: داکیومنتش هم براتون نوشتم که بتونید راحت ازش استفاده کنید.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Tue, 01 Jul 2025 21:41:22 +0330</pubDate>
            </item>
                    <item>
                <title>‏Strictmode در برنامه نویسی اندروید چیست و چه کاربردی دارد؟</title>
                <link>https://virgool.io/@mohaammaadsadeq/strictmode-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%DA%86%DB%8C%D8%B3%D8%AA-%D9%88-%DA%86%D9%87-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%AF%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AF-xo2ykqpw8boq</link>
                <description>‏StrictMode یکی از ابزارهای مهم در اندروید برای شناسایی مشکلات عملکردی (performance issues) و قوانین استفاده‌ی نادرست از منابع در اپلیکیشن است. این ابزار عمدتاً برای بررسی عملیات سنگین یا نادرست در ترد اصلی (Main Thread) و همچنین نشت منابع (resource leaks) استفاده می‌شود.هدف StrictMode چیست؟‏StrictMode به شما کمک می‌کند: از انجام عملیات سنگین مثل دسترسی به دیسک یا شبکه در ترد اصلی جلوگیری کنید. نشت منابع مثل  Cursor یا Closeableهایی که بسته نشده‌اند را شناسایی کنید. استفاده‌های نادرست از حافظه، تردها و فایل‌ها را پیدا کنید.انواع Policy ها در StrictMode1.نوع ThreadPolicyبرای بررسی عملیات‌هایی که روی ترد اصلی(Main/UI Thread) انجام می‌شن مثل: دسترسی به فایل یا پایگاه‌داده درخواست‌های شبکه‌ای ایجاد یا اعمال lock عملیات سنگین CPU‏‏‏‏2. نوع VmPolicyبرای بررسی مشکلات مرتبط با حافظه، منابع و Context ، مثل: نشت  Activity یا Context نشت SQLiteCursor فایل‌های باز شده ولی بسته نشده استفاده نادرست از کلاس‌هایی مثل  Handler یا Executorچگونه StrictMode را فعال کنیم؟شما StrictMode را در کد کاتلین خود فعال می‌کنید، معمولاً در متد onCreate کلاس Application یا Activity اصلی برنامه. نکته بسیار مهم این است که StrictMode را فقط در نسخه‌های دیباگ (Debug Builds) فعال کنید و هرگز در نسخه‌های انتشار (Release Builds)  آن را فعال نگذارید.دلیل استفاده در نسخه‌های دیباگ: (Debug Builds)چون در حالت Release  باعث کندی یا کرش می‌شود.مثال:استفاده از StrictMode در کلاس Application:مثال عملی:فرض کن در MainActivity  به صورت مستقیم فایل می‌خوانی:اگر StrictMode روشن باشد، درLogcat هشدار می‌دهد: جمع بندی:‏StrictMode ابزاری بسیار مفید در اندروید است که به شما کمک می‌کند مشکلات عملکردی و نشت منابع را در اپلیکیشن‌تان شناسایی کنید. این ابزار باید فقط در حالت  Debug فعال شود، چون در حالت Release ممکن است باعث کرش یا کاهش عملکرد شود.استفاده از StrictMode به این دلیل مهم است که کمک می‌کند اشتباهاتی را پیدا کنید که ممکن است باعث کندی یا باگ در اپلیکیشن شوند. مثلاً اگر بدون توجه، عملیات سنگینی مثل خواندن فایل یا اتصال به اینترنت را در ترد اصلی (ترد مربوط به رابط کاربری) انجام دهید، یا منابعی مثل فایل یا دیتابیس را باز کنید ولی فراموش کنید آن‌ها را ببندید، StrictMode این خطاها را شناسایی و گزارش می‌کند. این مشکلات معمولاً در حالت عادی مشخص نمی‌شوند، اما می‌توانند باعث کاهش سرعت اپ یا حتی کرش شدن آن در آینده شوند.فعال‌سازی StrictMode از طریق دو تابع اصلی انجام می‌شود:‏StrictMode.setThreadPolicy() برای بررسی عملیات مربوط به ترد‏StrictMode.setVmPolicy() برای بررسی نشت منابع و حافظهاین ابزار مخصوصاً برای توسعه‌دهندگان هنگام تست و دیباگ بسیار کاربردی است، چون به بهبود کیفیت نهایی اپ کمک زیادی می‌کند.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش ها را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Mon, 26 May 2025 22:05:32 +0330</pubDate>
            </item>
                    <item>
                <title>‏Stateful و Stateless در Jetpack Compose</title>
                <link>https://virgool.io/@mohaammaadsadeq/stateful-%D9%88-stateless-%D8%AF%D8%B1-jetpack-compose-lysu5tcywqjo</link>
                <description>درJetpack Compose، کامپوننتهای Stateful و Stateless به دو دسته کلی تقسیم میشوند:۱. کامپوننت های Statelessیک کامپوننت Stateless  هیچ وضعیت داخلی (State) را مدیریت نمیکند. خروجی این کامپوننت فقط به ورودیهایی که دریافت میکند وابسته است. این نوع کامپوننتها به عنوان &quot;کامپوننتهای گنگ&quot; (Dumb Components) شناخته میشوند، زیرا منطق خاصی ندارند و فقط داده هایی که دریافت میکنند را نمایش میدهند.به بیان دیگر یک کامپوننت Stateless مانند یک کتاب است. هر بار که آن را باز میکنید، همان محتوا را نمایش میدهد، مگر اینکه به صورت دستی چیزی را در داخل آن تغییر دهید. در Jetpack Compose، یک کامپوننت Stateless هیچ تغییری را به خاطر نمیسپارد. هر بار که فراخوانی میشود، فقط آنچه را که به آن داده شده است، نمایش میدهد.مثال ۱:بیایید یک کامپوننت ساده برای نمایش پیام خوشآمدگویی را بررسی کنیم:در این مثال، تابع Greeting یک کامپوننت Stateless است، زیرا:فقط مقدار name را دریافت میکند.هیچ وضعیتی (State) را نگه نمیدارد.هر بار که name تغییرکند، مقدار جدید را نمایش میدهد.مثلاً اگر مقدار name برابر &quot;Mohammad&quot; باشد، این کامپوننت همیشه &quot;Hello , Mohammad&quot; را نمایش خواهد داد، مگر اینکه مقدار جدیدی برای name ارسال شود.مثال ۲:بررسی تابع MyCustomButton:کامپوزبل MyCustomButton به فراخوان خود وابسته است تا (label) و کلیک لیسنر را دریافت کند و هیچ شیء State را نگه نمیدارد. به همین دلیل، این یک کامپوزبل Stateless است.مزایا و معایب کامپوننتهای Stateless✅ مزایا:سادگی: خواندن، درک و تست آنها بسیار آسان است.قابلیت استفاده مجدد: میتوان آن را در بخشهای مختلف برنامه با دادههای متفاوت استفاده کرد.عملکرد بهتر: سریعتر اجرا میشود زیرا نیازی به مدیریت وضعیت ندارد.❌ معایب:محدودیت در عملکرد: نمیتواند بهتنهایی تغییرات  پویا یا تعاملات کاربر را مدیریت کند. ۲. کامپوننت Statefulیک کامپوننت Stateful دارای وضعیت داخلی (State) است و خروجی آن علاوه بر ورودیها، به وضعیت داخلی خودش نیز بستگی دارد. این نوع کامپوننتها به عنوان &quot;کامپوننتهای هوشمند&quot; (Smart Components) شناخته میشوند، زیرا میتوانند به ورودیهای کاربر واکنش نشان دهند، محاسبات انجام دهند و وضعیت خود را تغییر دهند. این تغییر وضعیت باعث بازسازی (Recompose) مجدد کامپوننت خواهد شد.به بیان دیگر یک کامپوننت Stateful مانند یک کنترل تلویزیون است. به خاطر میآورد که آخرین بار کدام دکمه را فشار دادهاید و صفحه نمایش تلویزیون را بر اساس آن تغییر میدهد.در Jetpack Compose، یک کامپوننت Stateful وضعیت داخلی خود را نگه میدارد و به تغییرات پاسخ میدهد.مثال ۱:بیایید یک دکمه بسازیم که تعداد کلیکهای کاربر را شمارش کند:در این مثال، ClickCounter یک کامپوننت Stateful است، زیرا:خودش متغیر count را ایجاد میکند و مقدار آن را نگه میدارد.مقدار count را هنگام کلیک کردن تغییر میدهد.به وضعیت داخلی خود وابسته است و هر بار که count تغییر کند، کامپوننت (Recompose) میشود.مثال ۲: بررسی Composable دارای وضعیت (Stateful) :در این مثال، تابع Greeting یک کامپوننت Stateful است زیرا:خودش وضعیت isExpanded را ایجاد میکند.این وضعیت را در داخل خود نگه میدارد.میتواند مقدار isExpanded را تغییر دهد.در اینجا، متغیر isExpanded مشخص میکند که متن باید کامل نمایش داده شود یا خیر و مقدار آن هنگام کلیک روی IconButton تغییر میکند.مزایا و معایب کامپوننتهای Stateful✅ مزایا:تعامل پذیری بالا: میتواند ورودیهای کاربر را مدیریت کند و به تغییرات پاسخ دهد.امکانات غنی تر: برای ایجاد رابطهای کاربری      تعاملی و پویا مناسب است.❌ معایب:پیچیدگی بیشتر: درک، تست و نگهداری آن دشوارتر است.عملکرد پایینتر: به دلیل مدیریت وضعیت، ممکن است کندتر باشد.چه زمانی از هرکدام استفاده کنیم؟✅ کامپوننت های Stateless مناسب هستند برای:نمایش دادههای ثابت و غیرپویا.عناصر ساده UI که نیازی به تعامل با کاربر ندارند.کامپوننتهایی که باید در بخشهای مختلف برنامه استفاده شوند.✅ کامپوننت های Stateful مناسب هستند برای:عناصر تعاملی که نیاز به پاسخگویی به ورودی کاربر دارند.مدیریت دادههای پویا که در طول زمان تغییر میکنند.رابط های کاربری پیچیده که باید وضعیت خود را کنترل کنند.نتیجه گیریدرک تفاوت بین Stateful و Stateless برای ساخت رابط های کاربری بهینه و قابل نگهداری در Jetpack Compose ضروری است.🔹 کامپوننت های Stateless ساده، قابل استفاده مجدد و سریع هستند، و برای نمایش دادههای ثابت ایدهآلاند. 🔹 کامپوننت های Stateful برای مدیریت تعاملات کاربر و دادههای پویا ضروریاند، اما پیچیدگی و هزینه عملکردی بیشتری دارند.📌 بهترین روش: در پروژههای واقعی، اغلب از ترکیب  Stateful و Stateless  استفاده میشود تا انعطافپذیری ، تستپذیری و قابلیت استفاده مجدد را افزایش دهیم.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Mon, 17 Mar 2025 11:17:38 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه اپلیکیشن اندرویدی را ایمن تر کنیم؟</title>
                <link>https://virgool.io/@mohaammaadsadeq/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%A7%D9%BE%D9%84%DB%8C%DA%A9%DB%8C%D8%B4%D9%86-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF%DB%8C-%D8%B1%D8%A7-%D8%A7%DB%8C%D9%85%D9%86-%D8%AA%D8%B1-%DA%A9%D9%86%DB%8C%D9%85-tbodcpbinhgp</link>
                <description>ساخت یک اپلیکیشن موفق اندروید فقط به داشتن ویژگی‌های جذاب و تجربه کاربری روان محدود نمی‌شود؛ بلکه نیازمند امنیت قوی نیز هست. در دنیای دیجیتال امروز، کاربران به اپلیکیشن‌ها اعتماد می‌کنند و اطلاعات حساسی مثل رمز عبور، جزئیات شخصی و اطلاعات پرداخت را در اختیار آن‌ها می‌گذارند. یک نقص امنیتی نه تنها می‌تواند به اعتبار اپلیکیشن شما آسیب برساند، بلکه ممکن است منجر به مشکلات قانونی نیز شود.در این پست، به مراحل کلیدی برای افزایش امنیت اپلیکیشن اندروید شما می‌پردازیم.
1. ذخیره‌سازی امن داده‌هاچرا مهم است؟داده‌های کاربران که روی دستگاه ذخیره می‌شوند، در صورت عدم امنیت کافی، می‌توانند در معرض خطر قرار گیرند؛ به‌ویژه در مواردی مانند گم شدن یا دزدیده شدن دستگاه.چگونه داده‌ها را ایمن کنیم؟استفاده از Encrypted SharedPreferences: برای ذخیره داده‌های سبک و حساس به صورت رمزنگاری شده.رمزنگاری پایگاه‌داده‌ها: از ابزارهایی مانند SQLCipher برای رمزنگاری دیتابیس‌های SQLite استفاده کنید.اجتناب از ذخیره داده‌های حساس روی دستگاه: برای اطلاعاتی مانند توکن‌ها و رمزهای عبور از APIهای امن استفاده کنید.مثال:برای ذخیره امن تنظیمات کاربر، می‌توانید از EncryptedSharedPreferences استفاده کنید:2. محافظت از APIهای حساسبرای جلوگیری از دسترسی غیرمجاز به ویژگی‌های حساس یا APIهای اپلیکیشن خود، اقدامات امنیتی زیر را انجام دهید:نکات:استفاده از OAuth 2.0 برای احراز هویت: با پیاده‌سازی OAuth 2.0 و احراز هویت مبتنی بر توکن، APIهای خود را ایمن کنید.مبهم‌سازی کد (Obfuscation): از ابزارهایی مانند ProGuard یا R8 استفاده کنید تا کد اپلیکیشن شما مبهم شود و مهندسی معکوس آن دشوارتر شود.مثال از قوانین ProGuard:3. استفاده از احراز هویت امنچرا مهم است؟روش‌های احراز هویت ضعیف می‌توانند به کاربران غیرمجاز اجازه دهند تا به اپلیکیشن دسترسی پیدا کنند.چگونه احراز هویت امن را پیاده‌سازی کنیم؟استفاده از OAuth2 برای احراز هویت API: از این پروتکل برای ایمن‌سازی ارتباطات بین اپلیکیشن و سرور استفاده کنید.پیاده‌سازی احراز هویت دو مرحله‌ای (2FA): با اضافه کردن یک لایه امنیتی اضافی، اطمینان حاصل کنید که فقط کاربران مجاز می‌توانند وارد شوند.ورود ایمن با استفاده از احراز هویت بیومتریک: از روش‌هایی مانند اثر انگشت یا تشخیص چهره بهره ببرید.مثال:برای اضافه کردن احراز هویت بیومتریک از BiometricPrompt API اندروید استفاده کنید:4. استفاده از HTTPS در همه جاچرا مهم است؟اگر اپلیکیشن شما از طریق اتصال ناامن HTTP با سرور ارتباط برقرار کند، مهاجمان می‌توانند با استفاده از حملات &quot;مرد میانی&quot; (MITM) داده‌ها را رهگیری و تغییر دهند.چگونه HTTPS را پیاده‌سازی کنیم؟استفاده از HTTPS (HTTP Secure): برای تمام ارتباطات شبکه‌ای از پروتکل امن HTTPS استفاده کنید.اجبار استفاده از HTTPS: با اضافه کردن تنظیمات امنیت شبکه (Network Security Configuration) استفاده از HTTPS را اجباری کنید.مثال:برای اجباری کردن استفاده از HTTPS، یک فایل network_security_config.xml اضافه کنید:پیکربندی زیر را به فایل AndroidManifest.xml خود اضافه کنید:5. امن‌سازی کدچرا مهم است؟مهاجمان می‌توانند فایل APK (Android Package Kit) شما را دی‌کامپایل کرده و به سورس کد دسترسی پیدا کنند. این موضوع اپلیکیشن شما را در برابر مهندسی معکوس و تغییرات مخرب آسیب‌پذیر می‌کند.چگونه کد خود را امن کنیم؟مبهم‌سازی کد (Obfuscation): از ابزارهایی مانند ProGuard یا R8 (ابزارهای داخلی اندروید) استفاده کنید تا کد شما مبهم شود و خواندن و درک آن برای مهاجمان دشوارتر گردد.کاهش داده‌های حساس هاردکد شده: هرگز اطلاعات حساسی مانند کلیدهای API یا اطلاعات کاربری را به‌صورت مستقیم در کد ذخیره نکنید. به جای آن از روش‌های امن مانند متغیرهای محیطی یا فضای ذخیره‌سازی رمزنگاری‌شده استفاده کنید.مثال:برای فعال‌سازی ProGuard، تنظیمات زیر را به فایل build.gradle خود اضافه کنید:6. محافظت در برابر مهندسی معکوسچرا مهم است؟مهاجمان می‌توانند اپلیکیشن شما را مهندسی معکوس کنند تا اطلاعات حساسی مانند کلیدهای API را استخراج کرده یا رفتار اپلیکیشن را تغییر دهند.چگونه محافظت کنیم؟استفاده از مبهم‌سازی کد (Obfuscation): از ابزارهایی مانند ProGuard یا R8 برای مبهم کردن کد اپلیکیشن استفاده کنید.استفاده از کتابخانه‌های شناسایی تغییرات: با استفاده از این کتابخانه‌ها، بررسی کنید که آیا فایل APK تغییر کرده است یا خیر.استفاده از Certificate Pinning: اطمینان حاصل کنید که اپلیکیشن شما فقط با سرورهای قابل‌اعتماد ارتباط برقرار می‌کند.استفاده از کتابخانه‌های Native: منطق حساس را با استفاده از NDK (Native Development Kit) به زبان C++ منتقل کنید، زیرا کد Native مهندسی معکوس را دشوارتر می‌کند.شناسایی دستگاه‌های روت‌شده: اگر اپلیکیشن تشخیص دهد که دستگاه روت شده است، دسترسی را مسدود کرده یا به کاربر هشدار دهید، چون دستگاه‌های روت‌شده بیشتر در معرض خطر هستند.۷. پیاده‌سازی مجوزهای زمان اجراچرا مهم است؟اعطای مجوزهای غیرضروری می‌تواند منجر به آسیب‌پذیری‌های امنیتی شود. به‌عنوان مثال، یک اپلیکیشن دوربین نباید به موقعیت مکانی کاربر دسترسی داشته باشد مگر اینکه واقعاً ضروری باشد.چگونه مجوزها را به‌طور امن مدیریت کنیم؟فقط مجوزهایی را درخواست کنید که اپلیکیشن شما واقعاً به آن‌ها نیاز دارد.در زمان اجرا مجوزها را درخواست کنید و توضیح روشنی در مورد دلایل نیاز به هر کدام ارائه دهید.مثال:درخواست مجوزها در زمان اجرا:
8. جلوگیری از SQL Injectionچرا مهم است؟اگر اپلیکیشن شما از ورودی‌های غیرمعتبر در querie های پایگاه‌داده استفاده کند، مهاجمان می‌توانند از این نقاط ضعف برای دسترسی یا دستکاری داده‌ها بهره‌برداری کنند.چگونه از SQL Injection جلوگیری کنیم؟از querie های پارامتری یا عبارات آماده استفاده کنید.از ادغام ورودی‌های کاربر به طور مستقیم در querie های SQL خودداری کنید.مثال:‏querie امن در پایگاه‌داده SQLite:نتیجه گیریامن‌سازی یک اپلیکیشن اندروید شامل چندین لایه حفاظتی است، از ذخیره‌سازی امن داده‌ها و ارتباطات شبکه گرفته تا حفاظت در برابر مهندسی معکوس و بدافزارها. با پیروی از این شیوه‌های بهترین و استفاده از ابزارهای مدرن مانند Room، EncryptedSharedPreferences و SafetyNet، می‌توانید خطر آسیب‌پذیری‌ها را به‌طور قابل‌توجهی کاهش داده و اعتماد کاربران خود را جلب کنید.به یاد داشته باشید که امنیت یک فرآیند مداوم است. به‌روزرسانی‌های منظم، بازرسی‌ها و پیگیری روندهای صنعت برای حفظ امنیت اپلیکیشن ضروری هستند!ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Tue, 24 Dec 2024 13:18:08 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت بین APK و AAB چیست؟</title>
                <link>https://virgool.io/@mohaammaadsadeq/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D8%A8%DB%8C%D9%86-apk-%D9%88-aab-%DA%86%DB%8C%D8%B3%D8%AA-jbntgw6xs2ej</link>
                <description>هنگام توسعه اپلیکیشن‌های اندروید، ارائه آنها به کاربران در قالب مناسب از نظر عملکرد، کارایی ذخیره‌سازی و تجربه کاربری بسیار مهم است. برای مدت طولانی، APK (Android Package) فرمت استاندارد برای توزیع اپلیکیشن‌های اندروید بود. اما گوگل در سال ۲۰۱۸ AAB (Android App Bundle) را معرفی کرد تا فرآیند تحویل اپلیکیشن‌ها را بهینه کند و عملکرد بهتری ارائه دهد.در این پست، تفاوت‌های بین APK و AAB، مزایا و معایب هرکدام را بررسی می‌کنیم .‏‏APK (Android Package) چیست؟‏APK فرمت سنتی بسته‌بندی اپلیکیشن‌های اندروید است. این فرمت شامل تمام منابع، کدها و دارایی‌هایی است که برای نصب و اجرای اپلیکیشن روی یک دستگاه نیاز است. زمانی که یک APK ایجاد می‌کنید، یک فایل تکی خواهید داشت که همه‌چیز را شامل می‌شود، بدون توجه به نوع دستگاه یا تنظیمات آن.اجزای یک APK:فایل Manifest: اطلاعات مربوط به اپلیکیشن، شامل مجوزها (Permissions).فایل‌های DEX: کدهای کامپایل شده جاوا/کاتلین.منابع (Resources): تصاویر، طرح‌بندی‌ها (Layouts) و سایر دارایی‌ها.کتابخانه‌های بومی (Native Libraries): فایل‌های باینری مخصوص دستگاه مانند ARM، x86 و غیره.نحوه کار APKزمانی که یک APK نصب می‌شود، کل فایل به‌طور کامل دانلود و روی دستگاه کاربر نصب می‌شود، حتی اگر برخی از بخش‌ها (مانند دارایی‌هایی که برای اندازه‌های صفحه‌نمایش پشتیبانی‌نشده هستند) موردنیاز نباشند.‏‏AAB (Android App Bundle) چیست؟‏AAB یک فرمت جدیدتر است که توسط گوگل معرفی شده است. به جای بسته‌بندی همه منابع در یک فایل واحد، AAB آنها را به ماژول‌های متعددی سازمان‌دهی می‌کند. این ماژول‌ها به گوگل پلی اجازه می‌دهند که فقط بخش‌هایی از اپلیکیشن را که برای یک دستگاه خاص موردنیاز هستند، ارائه دهد. این رویکرد باعث کاهش حجم اپلیکیشن برای کاربران نهایی می‌شود.نحوه کار AABساخت توسط توسعه‌دهنده: توسعه‌دهندگان اپلیکیشن خود را به صورت یک فایل AAB ایجاد می‌کنند.پردازش توسط گوگل پلی: گوگل پلی فایل AAB را پردازش کرده و یک سیستم تحویل پویا (Dynamic Delivery) ایجاد می‌کند.تولید و ارائه APK بهینه‌شده: زمانی که یک کاربر اپلیکیشن را دانلود می‌کند، گوگل پلی یک APK بهینه‌شده (که به آن Split APK گفته می‌شود) تولید و ارائه می‌کند. این APK دقیقاً بر اساس تنظیمات دستگاه کاربر (مانند تراکم صفحه‌نمایش، معماری CPU و زبان) سفارشی‌سازی شده است.تفاوت های کلیدی بین APK و AABویژگی‌های APK:حجم فایل: شامل تمام منابع است و حجم بیشتری دارد.تحویل: یک فایل واحد برای همه دستگاه‌ها.نصب: می‌توان آن را به‌صورت مستقیم Sideload کرد.مدیریت کد: شامل تمام کدها و منابع است.سهولت دیباگ: به دلیل بسته‌بندی یکپارچه، دیباگ آسان‌تر است.ویژگی‌های AAB:حجم فایل: APKهای بهینه‌شده تولید می‌کند و حجم را کاهش می‌دهد.تحویل: Split APKها بر اساس تنظیمات دستگاه تولید می‌شوند.نصب: برای تحویل بهینه به گوگل پلی نیاز دارد.مدیریت کد: ماژولار شده برای تحویل پویا.سهولت دیباگ: نیاز به مراحل اضافی برای دیباگ دارد.مزایای APK:قابلیت Sideloading: فایل‌های APK می‌توانند مستقیماً به اشتراک گذاشته شده و بدون استفاده از گوگل پلی نصب شوند. این ویژگی برای تست یا توزیع اپلیکیشن‌ها خارج از پلی استور بسیار مفید است.فایل تکی: همه چیز در یک فایل بسته‌بندی شده است که فرآیند توزیع و تست را ساده‌تر می‌کند.پشتیبانی گسترده: فایل‌های APK توسط تمام دستگاه‌های اندروید و فروشگاه‌های اپلیکیشن پشتیبانی می‌شوند.مزایای AAB:کاهش حجم اپلیکیشن: AAB با حذف منابع غیرضروری، اپلیکیشن‌ها را بهینه کرده و حجم دانلود و نصب را کاهش می‌دهد.عملکرد بهتر: با حذف منابع غیرضروری، اپلیکیشن سریع‌تر بارگذاری شده و حافظه کمتری مصرف می‌کند.ویژگی‌های پویا (Dynamic Features): AAB از تحویل پویا پشتیبانی می‌کند و به کاربران اجازه می‌دهد فقط بخش‌هایی از اپلیکیشن را که نیاز دارند، دانلود کنند. به عنوان مثال:دانلود بسته‌های زبانی خاص.نصب ویژگی‌های خاص فقط زمانی که موردنیاز باشند.آینده‌نگر: AAB فرمت مورد ترجیح گوگل است و از آگوست ۲۰۲۱ برای اپلیکیشن‌های پلی استور اجباری شده است.چالش‌های AAB:عدم امکان نصب مستقیم (Sideloading): فایل‌های AAB نمی‌توانند مانند APK مستقیماً نصب شوند. برای نصب نیاز به تولید APK خاص از طریق ابزارهایی مانند bundletool دارید.وابستگی به گوگل پلی: AAB برای ارائه APK‌های بهینه به گوگل پلی وابسته است که می‌تواند برای اپلیکیشن‌هایی که خارج از پلی استور توزیع می‌شوند، یک محدودیت باشد.پیچیدگی بیشتر: دیباگ و تست فایل‌های AAB نسبت به APK به ابزارها و مراحل اضافی نیاز دارد.چه زمانی از APK یا AAB استفاده کنیم؟موارد استفاده از APK:توزیع اپلیکیشن‌ها خارج از گوگل پلی.تست یا دیباگ محلی.اشتراک‌گذاری اپلیکیشن‌ها با پیکربندی‌های محدود.موارد استفاده از AAB:انتشار اپلیکیشن‌ها در گوگل پلی.بهینه‌سازی تحویل اپلیکیشن برای کاربران.پشتیبانی از طیف گسترده‌ای از دستگاه‌ها و پیکربندی‌ها.نتیجه گیری:هر دو فرمت APK و AAB مزایا و محدودیت‌های خاص خود را دارند. در حالی که APK همچنان برای اشتراک‌گذاری مستقیم و تست مفید است، AAB به دلیل بهینه‌سازی‌های حجمی و عملکردی، به فرمت اصلی گوگل پلی تبدیل شده است. درک زمان و نحوه استفاده از هر فرمت برای توسعه‌دهندگان اندروید ضروری است تا تحویل اپلیکیشن‌ها کارآمدتر و تجربه کاربری روان‌تری فراهم شود.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Mon, 16 Dec 2024 14:55:49 +0330</pubDate>
            </item>
                    <item>
                <title>‏Image Carousel در Jetpack compose</title>
                <link>https://virgool.io/@mohaammaadsadeq/image-carousel-%D8%AF%D8%B1-jetpack-compose-yz5ogoq3s98m</link>
                <description>یک (Image Carousel) یک مؤلفه رابط کاربری (UI) است که مجموعه‌ای از تصاویر را به‌صورت افقی نمایش می‌دهد و به کاربران اجازه می‌دهد با کشیدن انگشت یا کلیک کردن، بین تصاویر جابجا شوند. این مؤلفه به طور معمول در اپلیکیشن‌ها یا وب‌سایت‌ها برای نمایش محتوای ویژه، محصولات یا گالری‌ها استفاده می‌شود. در این پست به پیاده سازی Image Carousel می پردازیم:توضیحات:ویژگی‌های Image Carousel در Jetpack Compose عبارتند از:اسکرول افقی:کاربران می‌توانند تصاویر را به‌صورت افقی جابجا کنند، که این امکان را می‌دهد تا تعداد زیادی تصویر به‌طور داینامیک نمایش داده شود.عملکرد بهینه:از LazyRow استفاده می‌کند که فقط تصاویر قابل مشاهده را بارگذاری می‌کند و دیگر تصاویر تنها زمانی بارگذاری می‌شوند که به صفحه اضافه شوند. این امر عملکرد را برای لیست‌های بزرگ بهینه می‌کند.طراحی واکنش‌گرا:قابلیت تطبیق با اندازه‌های مختلف صفحه‌نمایش به کمک ویژگی‌هایی مانند fillMaxWidth و تنظیمات مختلف در رابطه با فاصله‌ها و اندازه‌ها.پشتیبانی از تصاویر پویا:تصاویر از لیست داده‌ها (مثل لیستی از URL یا منابع محلی) به‌صورت پویا بارگذاری می‌شوند.قابلیت سفارشی‌سازی:می‌توان از تنظیمات مختلف مانند فاصله بین تصاویر (spacedBy)، padding، تراز، و طراحی‌های سفارشی (مثل گوشه‌های گرد و پس‌زمینه) استفاده کرد.پشتیبانی از بارگذاری غیرهم‌زمان تصاویر:با استفاده از rememberAsyncImagePainter، تصاویر به‌صورت غیرهم‌زمان بارگذاری می‌شوند تا عملکرد بهتر و تجربه کاربری روان‌تری فراهم شود.نمایش توضیحات دسترسی‌پذیری:برای بهبود دسترسی‌پذیری، هر تصویر یک contentDescription دارد که می‌تواند برای کاربران با نیازهای خاص مفید باشد.کد نویسی:1.  ابتدا کتابخانه زیر را اضافه می کنیم:2. نوشتن Composable با نام ImageCarousel این کد یک کامپوننت ImageCarousel در Jetpack Compose تعریف می‌کند که یک لیست افقی از تصاویر را به‌صورت اسکرولی نمایش می‌دهد. این کامپوننت از LazyRow استفاده می‌کند.3. حالا بیایید این متد ()ImageCarousel را از MainScreen فراخوانی کنیم تا لیست تصاویر را نشان دهیم4. کد کاملخروجی کد:ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Sat, 30 Nov 2024 12:50:26 +0330</pubDate>
            </item>
                    <item>
                <title>تکنیک‌های بهینه‌سازی در Jetpack Compose</title>
                <link>https://virgool.io/@mohaammaadsadeq/%D8%AA%DA%A9%D9%86%DB%8C%DA%A9-%D9%87%D8%A7%DB%8C-%D8%A8%D9%87%DB%8C%D9%86%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%AF%D8%B1-jetpack-compose-mjmmwpdnzyf9</link>
                <description>در توسعه اپلیکیشن‌های Android با استفاده از Jetpack Compose، بهینه‌سازی عملکرد برای ارائه تجربه کاربری روان و سریع بسیار مهم است. بهینه‌سازی درست می‌تواند باعث کاهش مصرف حافظه، کاهش زمان رندر و کاهش Recomposition های غیرضروری شود، که در این پست به بررسی چند مورد میپردازیم.1. به حداقل رساندن Recompositionبازترکیب (Recomposition) فرآیندی است که Jetpack Compose برای به‌روزرسانی رابط کاربری انجام می‌دهد و با تغییر وضعیت‌ها (State) ایجاد می‌شود. اگرچه این فرآیند کارآمد است، اما Recomposition های غیرضروری می‌توانند عملکرد را کند کنند. برای مدیریت بهتر Recomposition ها، این نکات را در نظر بگیرید:محدود کردن محدوده State به جایی که نیاز است:متغیرهای State را فقط در همان کامپوزهایی که به آنها نیاز دارند نگه دارید. این کار تأثیر تغییر State را روی دیگر عناصر رابط کاربری کاهش می‌دهد.به بیان دیگر به این معناست که متغیرهایی که وضعیت (State) را ذخیره می‌کنند، فقط در همان بخشی از رابط کاربری که مستقیماً به آن‌ها نیاز دارد استفاده شوند، نه در کل برنامه یا کامپوزهای دیگر.مثال ساده:فرض کنید شما یک اپلیکیشن دارید که یک تعداد کلیک (Click Counter) را نشان می‌دهد. رابط کاربری شامل دو بخش است:بخش شمارش کلیک‌ها که عدد کلیک را نشان می‌دهد.بخش توضیحات که یک متن ثابت مثلاً &quot;روی دکمه کلیک کنید&quot; نمایش می‌دهد.اگر متغیر State (مثل clickCount) را در سطح بالای کل اپلیکیشن نگه دارید، هر بار که کاربر روی دکمه کلیک می‌کند و عدد کلیک تغییر می‌کند، هم بخش شمارش و هم بخش توضیحات Recomposition می‌شوند، حتی اگر بخش توضیحات نیازی به تغییر نداشته باشد.راه‌حل: محدود کردن State به بخش مرتبطمتغیر clickCount را فقط در همان بخشی که عدد کلیک نمایش داده می‌شود (بخش شمارش کلیک‌ها) نگه دارید. این کار باعث می‌شود تغییر عدد کلیک فقط روی همان بخش تأثیر بگذارد و بخش توضیحات نیازی به Recomposition نداشته باشد.استفاده از remember برای مقادیر کش‌شده:تابع remember مقادیر را در حافظه نگه می‌دارد و آنها را در Recomposition های بعدی مجدداً محاسبه نمی‌کند. این روش از محاسبات غیرضروری جلوگیری می‌کند.استفاده از ساختارهای داده‌ای پایدار (Stable):ارسال داده‌های پایدار که با annotations مانند Immutable@ یا Stable@ مشخص شده‌اند، به Jetpack Compose اعلام می‌کند که این مقادیر تغییر نخواهند کرد. این کار باعث کاهش Recomposition های غیرضروری می‌شود و عملکرد رابط کاربری را بهبود می‌بخشد.۲. اجتناب از عملیات سنگین داخل کامپوزهاکامپوزها باید تنها مسئول مدیریت و نمایش رابط کاربری باشند، نه انجام محاسبات سنگین. برای اینکه رابط کاربری روان و واکنش‌پذیر باقی بماند، عملیات‌های سنگین را در پس‌زمینه انجام دهید:اجرای وظایف سنگین با استفاده از Coroutine‌ها:برای کارهایی مانند دریافت داده از سرور یا انجام محاسبات پیچیده، از Coroutine‌ها استفاده کنید. این کار را می‌توانید داخل LaunchedEffect یا rememberCoroutineScope انجام دهید.۳. استفاده از کامپوزهای Lazy برای لیست‌هاهنگام نمایش لیست‌های طولانی، از کامپوزهای LazyColumn، LazyRow، یا LazyGrid استفاده کنید. این کامپوزها فقط آیتم‌های قابل مشاهده در صفحه را رندر می‌کنند و به این ترتیب باعث صرفه‌جویی در حافظه و زمان پردازش می‌شوند.۴. استفاده مؤثر از Modifier APIاین Modifiers ابزارهای قدرتمندی در Jetpack Compose برای مدیریت چیدمان و استایل‌دهی هستند. اما استفاده نادرست و غیربهینه از آنها می‌تواند عملکرد برنامه را کاهش دهد.کاهش زنجیره‌های Modifier:ترکیب بیش‌ازحد از Modifiers باعث پیچیدگی و کاهش عملکرد می‌شود. سعی کنید Modifiers مرتبط را گروه‌بندی کنید یا به‌طور منطقی ترکیب کنید.قرار دادن Modifiers مشترک خارج از Composable@:وقتی Modifierها را داخل یک تابع Composable@ تعریف کنید، در هر Recomposition دوباره محاسبه می‌شوند. برای جلوگیری از این مشکل، Modifierهایی که تغییر نمی‌کنند را خارج از تابع تعریف کنید.مثال:مشکل (استفاده غیربهینه):مشکل:در این مثال، زنجیره طولانی از Modifiers باعث پیچیدگی شده است و اگر تابع Recomposition شود، همه این Modifierها دوباره محاسبه می‌شوند.راه‌حل (استفاده بهینه):مزایا:وقتی Modifier‌ های مشترک تنها یک‌بار تعریف می‌شوند و بازترکیب روی آنها تأثیر نمی‌گذارد.کد خواناتر و مدیریت آسان‌تر می‌شود.۵. استفاده از derivedStateOf برای مدیریت کارآمد State های محاسبه‌شده تابع derivedStateOf ابزاری مفید برای مدیریت کارآمد State های محاسبه‌شده است. این تابع به شما کمک می‌کند که داده‌های وابسته به تغییرات State  دیگر را به صورت بهینه محاسبه کنید و از Recomposition های غیرضروری جلوگیری کنید.توضیح:وقتی وضعیت (State) در برنامه تغییر می‌کند، ممکن است بخواهید State های جدیدی را از آن استخراج کنید. به‌طور معمول، هر بار که State تغییر می‌کند، باید محاسبات جدید انجام شود. استفاده از derivedStateOf باعث می‌شود که فقط زمانی State محاسبه‌شده دوباره به‌روز شود که واقعاً نیاز باشد، و این می‌تواند عملکرد را بهبود دهد.مثال :فرض کنید یک برنامه دارید که دو عدد را دریافت می‌کند و حاصل جمع آنها را نمایش می‌دهد. هر بار که یکی از اعداد تغییر کند، باید حاصل جمع به‌روز شود.استفاده از derivedStateOf:توضیح کد: تابعderivedStateOf فقط زمانی محاسبه می‌شود که یکی از مقادیر number1 یا number2 تغییر کند.اگر هیچ‌کدام از این مقادیر تغییر نکنند، sum دوباره محاسبه نخواهد شد، حتی اگر سایر قسمت‌های رابط کاربری Recomposition شوند.۶. پروفایل و بررسی چیدمان‌های خود با استفاده از Layout Inspectorاز Layout Inspector در Android Studio برای نظارت بر چیدمان‌های Jetpack Compose خود استفاده کنید، تعداد Recomposition ها را مشاهده کنید و مشکلات عملکردی احتمالی را شناسایی کنید.چگونه از Layout Inspector استفاده کنیم؟۱. باز کردن Layout Inspector:از منوی Tools در Android Studio گزینه Layout Inspector را انتخاب کنید.این ابزار به شما امکان می‌دهد تا چیدمان‌های فعلی در اپلیکیشن خود را مشاهده و بررسی کنید.۲. مشاهده تعداد Recomposition ها:در پنل Layout Inspector، گزینه Show Recomposition Counts را فعال کنید.این ویژگی به شما نشان می‌دهد که هر کامپوزابل چند بار Recomposition شده است.با بررسی تعداد Recomposition ها می‌توانید تشخیص دهید کدام بخش‌های رابط کاربری بیش از حد Recomposition می‌شوند و نیاز به بهینه‌سازی دارند.۷. استفاده از داده‌های غیرقابل تغییر برای محتوای ثابتهنگام کار با داده‌های ثابت یا غیرقابل تغییر، از MutableState استفاده نکنید. برای محتوای ثابت، از متغیرهای معمولی یا remember بدون استفاده از MutableState استفاده کنید تا از اضافه‌بار حافظه جلوگیری کنید.توضیح بیشتر:داده‌هایی که تغییر نمی‌کنند (مثل متون ثابت، تصاویر پیش‌فرض، یا دیگر محتواهایی که همیشه یکسان هستند) نباید از MutableState استفاده کنند. MutableState برای وضعیت‌هایی است که نیاز به تغییر دارند، بنابراین استفاده از آن برای داده‌های ثابت تنها باعث مصرف بیشتر حافظه می‌شود و بهینه نیست. برای اینگونه داده‌ها، استفاده از متغیرهای ساده یا remember کافی است.مثال :استفاده نادرست (با MutableState):مشکل:در این مثال، برای محتوای ثابت MutableState استفاده شده است، که باعث می‌شود Jetpack Compose به طور غیرضروری حافظه بیشتری مصرف کند و هر بار که کامپوز قابل Recomposition می‌شود، مقدار جدید محاسبه شود، حتی اگر محتوای آن تغییر نکند.راه‌حل (استفاده از متغیر معمولی یا remember بدون MutableState):مزایا:در این روش، staticText فقط یک‌بار در حافظه ذخیره می‌شود و تنها در صورت نیاز به رندر مجدد، بدون محاسبه دوباره، استفاده می‌شود.حافظه کمتری مصرف می‌شود و عملکرد بهبود می‌یابد، زیرا برای محتوای ثابت نیازی به مدیریت وضعیت نیست.نتیجه گیری:با پیروی از این روش‌ها، هم عملکرد و هم تجربه کاربری اپلیکیشن‌های Jetpack Compose شما بهبود خواهد یافت.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Mon, 25 Nov 2024 12:57:50 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت‌های بین NotNull@ و Nonnull@ در جاوا</title>
                <link>https://virgool.io/@mohaammaadsadeq/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D9%87%D8%A7%DB%8C-%D8%A8%DB%8C%D9%86-notnull-%D9%88-nonnull-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7-wttc8dxg0wnz</link>
                <description>در زبان جاوا، اطمینان از این که متغیرها، پارامترها یا مقادیر بازگشتی null نیستند، برای جلوگیری از خطاهای زمان اجرا مانند NullPointerException بسیار مهم است. دو انوتیشن رایج به نام‌های NotNull@ و Nonnull@ معمولاً برای این منظور استفاده می‌شوند، اما نقش‌ها و زمینه‌های متفاوتی دارند. بیایید به تفاوت‌های این دو انوتیشن بپردازیم:
انوتیشن NotNull@ (از پکیج jakarta.validation.constraints.NotNull)انوتیشن NotNull@ به طور گسترده در جاوا برای اهداف اعتبارسنجی استفاده می‌شود. زمانی که این انوتیشن را روی یک فیلد، پارامتر یا مقدار بازگشتی متد اعمال می‌کنید، مشخص می‌کنید که این مقدار هرگز نباید null باشد. این موضوع به‌ویژه زمانی اهمیت پیدا می‌کند که با JavaBeans، اشیای انتقال داده (DTOs)، یا کلاس‌های موجودیت (Entity Classes) کار می‌کنید.قدرت واقعی NotNull@ زمانی ظاهر می‌شود که در کنار یک فریمورک اعتبارسنجی مانند Jakarta Bean Validation (قبلاً با نام JSR 303/JSR 380 شناخته می‌شد) استفاده شود. در زمان اجرا، این فریمورک بررسی می‌کند که آیا فیلد یا پارامتر انوتیشن‌شده null است یا خیر. اگر مقدار null باشد، یک استثنای اعتبارسنجی (Validation Exception) پرتاب می‌شود و از پردازش داده‌های نامعتبر توسط برنامه جلوگیری می‌شود.به بیان ساده، انوتیشن NotNull@ مطمئن می‌شود که مقدار  فیلد، پارامتر یا مقدار بازگشتی خالی (null) نباشد، مخصوصاً وقتی که بخواهیم اطلاعات کاربر را بررسی یا ذخیره کنیم.به‌عنوان مثال، کلاس User را در نظر بگیرید:در اینجا، انوتیشن NotNull@ تضمین می‌کند که مقدار username نمی‌تواند null باشد زمانی که شیء User در حال اعتبارسنجی یا ذخیره‌سازی است.انوتیشن Nonnull@ (از پکیج jakarta.annotation.Nonnull)از طرف دیگر، انوتیشن Nonnull@ بیشتر برای بهبود کیفیت کد و جلوگیری از مشکلات مربوط به null در مرحله توسعه استفاده می‌شود. وقتی Nonnull@ را به یک پارامتر متد، نوع بازگشتی یا یک فیلد اعمال می‌کنید، به توسعه‌دهندگان و ابزارهای تحلیل استاتیک می‌گویید که این مقدار هرگز نباید null باشد.برخلاف NotNull@، انوتیشن Nonnull@ هیچ اعتبارسنجی در زمان اجرا انجام نمی‌دهد. در عوض، به IDEهایی مثل IntelliJ IDEA یا Eclipse کمک می‌کند که مشکلات احتمالی را در زمان توسعه تشخیص دهند. به عنوان مثال، اگر سعی کنید مقدار null را به یک پارامتر با انوتیشن Nonnull@ ارسال کنید، IDE ممکن است یک هشدار یا خطا ایجاد کند و به شما این امکان را بدهد که مشکل را قبل از اجرای کد برطرف کنید.مثال زیر را در نظر بگیرید:در این مورد، انوتیشن Nonnull@ به توسعه‌دهنده و ابزارها اعلام می‌کند که مقدار username هرگز نباید null باشد، و این باعث کاهش احتمال وقوع خطای NullPointerException می‌شود.نکات کلیدی:هدف: انوتیشن NotNull@ بیشتر برای اعتبارسنجی در زمان اجرا استفاده می‌شود تا از صحت داده‌ها در هنگام اجرای برنامه اطمینان حاصل شود. در مقابل، انوتیشن Nonnull@ بیشتر برای جلوگیری از مشکلات احتمالی مربوط به null در زمان توسعه و با استفاده از تحلیل استاتیک به کار می‌رود.تأثیر:انوتیشن NotNull@ بر رفتار زمان اجرا تأثیر می‌گذارد.انوتیشن Nonnull@ کیفیت کد را در زمان کامپایل یا توسعه با ابزارهای کدنویسی بهبود می‌بخشد.زمان استفاده:از NotNull@ در مدل‌های داده‌ای خود استفاده کنید زمانی که نیاز دارید مطمئن شوید برخی فیلدها یا پارامترها null نیستند.از Nonnull@ در امضای متدها یا نوع‌های بازگشتی استفاده کنید تا عدم وجود null را در زمان کدنویسی مستند و enforce کنید.نتیجه گیری: هر دو انوتیشن NotNull@ و Nonnull@ ابزارهای مهمی در جعبه‌ابزار یک توسعه‌دهنده جاوا هستند و هرکدام هدف خاص خود را دارند. با درک و استفاده صحیح از این دو، می‌توانید کدی قوی‌تر و مقاوم‌تر در برابر خطا بنویسید و اطمینان حاصل کنید که مشکلات مربوط به null چه در زمان اجرا و چه در زمان توسعه به‌خوبی شناسایی و مدیریت می‌شوند.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Wed, 20 Nov 2024 10:56:23 +0330</pubDate>
            </item>
                    <item>
                <title>‏Shared Element Transition در jetpack Compose</title>
                <link>https://virgool.io/@mohaammaadsadeq/shared-element-transition-%D8%AF%D8%B1-jetpack-compose-g43nnep6i3cl</link>
                <description>در این پست می خواهیم باهم Shared Element Transition  را در Jetpack Compose یادبگیریم. پس برای این کار ما یک لیست کوچک از پیتزا ها خواهیم ساخت که بتوانیم این مبحث را یاد بگیریم ! وابستگیبرای استفاده از آن، وابستگی زیرا را به فایل  :app/build.gradle.ktsاضافه می کنیم:مقدمه‌ای بر این APIاین API سه ویژگی جدید را معرفی می‌کند:ویژگی SharedTransitionLayout —  برای فعال‌سازی انیمیشن انتقال بین کامپوزابل‌ها مورد نیاز است.ویژگی ()Modifier.sharedElement — این باید زمانی استفاده شود که بخواهید کامپوزابل دیگری را تطبیق دهید.ویژگی  ()Modifier.sharedBounds — این باید به‌عنوان محدودۀ کانتینر برای جایی که انتقال باید اتفاق بیافتد، استفاده شود.شروع ساخت اپلیکیشنبیایید با ایجاد کلاس داده Pizaa شروع کنیم:بعد از آن، به MainActivity برویم و لیست پیتزا ها را ایجاد کنیم:برای اینکه بدانیم کدام پیتزا توسط کاربر انتخاب شده، باید یک متغیر به نام selectedCoffee ایجاد کنیم.آخرین متغیری که باید اعلام کنیم showDetails است. این متغیر برای نمایش جزئیات پیتزا هست و زمانی که کاربر روی یک پیتزا کلیک می‌کند، استفاده خواهد شد.برای انیمیشن انتقال، SharedTransitionLayout را اضافه کنید و داخل آن،AnimatedContent را ایجاد کنید.حال بیایید MainContant را ایجاد کنیم. برای استفاده از انیمیشن‌ها، باید از SharedTransitionScope و AnimatedVisibilityScope استفاده کنیم.کد زیر را در بدنه MainContant  قرار میدهیم .مفهوم این بخش از کد این است که برای پیاده‌سازی انیمیشن‌های انتقالی بین کامپوزابل‌ها در Jetpack Compose، ابتدا یک شیء به نام SharedContentState ایجاد می‌شود که وضعیت انیمیشن‌های مشترک را ذخیره می‌کند. این شیء با استفاده از () rememberSharedContentState به خاطر سپرده می‌شود تا بتواند به‌طور مداوم وضعیت انیمیشن را ذخیره کند.کلید منحصر به فردی که به این شیء اختصاص داده می‌شود، برای شناسایی و تمایز بین عناصر مختلفی که قرار است انتقال داده شوند، استفاده می‌شود. به این ترتیب، هنگام انتقال بین کامپوزابل‌ها، ()rememberSharedContentState تضمین می‌کند که هر عنصر به‌درستی شناسایی و مدیریت شود.همچنین، با استفاده از AnimatedContentScope در modifier، انیمیشن‌ها هماهنگ می‌شوند و نحوه انجام انیمیشن انتقال بین کامپوزابل‌ها کنترل می‌شود.در اینجا DetailsScreen است که همان کار را در مورد بخش انیمیشن انجام می‌دهد.حال بیایید به MainActivity برگردیم و کد را کامل کنیم.این آموزش به شما کمک می‌کند تا انیمیشن‌های انتقالی جذاب و روان را در اپلیکیشن‌های Jetpack Compose خود پیاده‌سازی کنید و تجربه کاربری بهتری ارائه دهید.سورس پروژه :برای دیدن کد پروژه در گیت هاب کلیک کنید.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Wed, 13 Nov 2024 21:37:36 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت Data Binding و View Binding در اندروید</title>
                <link>https://virgool.io/@mohaammaadsadeq/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-data-binding-%D9%88-view-binding-%D8%AF%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-m8sy9knfng4o</link>
                <description>با پیچیده‌تر شدن برنامه‌ها، نیاز به روش‌هایی برای مدیریت مؤثرتر و با خطای کمتر افزایش یافت. در اینجا است که دو تکنیک Data Binding و View Binding به کمک توسعه‌دهندگان می‌آیند.‏Data Binding و View Binding چیست؟ هر دو تکنیک برای برقراری ارتباط بین کد و رابط کاربری (UI) استفاده می‌شوند، اما تفاوت‌های مهمی دارند که بسته به نوع پروژه، ممکن است یکی از آن‌ها را به دیگری ترجیح دهید.‏‏تفاوت‌ها، مزایا و کاربردهای Data Binding و View Binding در توسعه اندروید، مدیریت مؤثر اجزای رابط کاربری و ارتباط با آن‌ها حیاتی است. در روش‌های سنتی، توسعه‌دهندگان برای تعامل با عناصر رابط کاربری از ()findViewById استفاده می‌کردند. اما با پیچیده‌تر شدن برنامه‌ها، نیاز به روش‌های کارآمدتر و با خطای کمتر داریم. Data Binding و View Binding دو ابزار قدرتمندی هستند که توسط اندروید برای ساده‌سازی تعاملات رابط کاربری ارائه شده‌اند. هر کدام از این ابزارها کاربرد و ویژگی‌های خاص خود را دارند و در موقعیت‌های متفاوتی استفاده می‌شوند.View Binding چیست؟‏در اندروید View Binding کلاس‌های binding را برای هر فایل layout XML در پروژه شما ایجاد می‌کند. این کلاس‌هایbinding به شما این امکان را می‌دهند که به صورت مستقیم و امن به ویوها بدون نیاز به ()findViewById دسترسی پیدا کنید.ویژگی‌های کلیدی View Bindingویژگی ‏امنیت نوع (Type Safety): View Binding با تولید یک کلاس binding بر اساس فایل XML اطمینان می‌دهد که نوع‌ها به درستی رعایت شده‌اند. این ویژگی خطر بروز خطاهای null pointer را که ناشی از شناسه‌های اشتباه یا تبدیل‌های نادرست هستند، از بین می‌برد.مثال : فرض کنید در یک فایل XML به نام activity_main.xml یک TextView با شناسه textView دارید. با استفاده از View Binding، کلاس binding به صورت خودکار تولید می‌شود و به شما اجازه می‌دهد به صورت امن به این TextView دسترسی پیدا کنید.‏ویژگی ‏بدون سربار اضافی (No Overhead): این روش سبک و با کمترین سربار نسبت به Data Binding است، چرا که نیازی به استفاده ازannotation‌ها یا عبارات data binding ندارد.مثال: اگر شما بخواهید از Data Bindingاستفاده کنید، باید در فایل XML از &lt;layout&gt; استفاده کنید و به آن annotation اضافه کنید. اما با View Binding، فقط کافی است به binding class دسترسی پیدا کنید.‏ ‏ایمنی در برابر null: اگر یک ویو در layout موجود نباشد، کلاس binding تولید شده مرجعی به آن ویو نخواهد داشت. این کار احتمال بروز خطاهای زمان اجرا را کاهش می‌دهد.فرض کنید در فایل XML یک Button با شناسه button دارید و یک TextView با شناسه textView ندارید. با استفاده از View Binding، کلاس binding به صورت خودکار فقط مرجع Button را شامل می‌شود و از ایجاد خطاهای زمان اجرا جلوگیری می‌کند.سادگی و کارایی: پیاده‌سازی و استفاده از View Bindingبسیار ساده و کارآمد است. به همین دلیل، گزینه‌ای ایده‌آل برای پروژه‌هایی است که نیازی به ویژگی‌های پیشرفته data bindingندارند.مثال:‏فعال کردن View Binding در فایل build.gradle:استفاده از view binding در یک اکتیویتی:در این مثال، ActivityMainBinding کلاس binding تولید شده‌ای است که به فایل layout activity_main.xml مربوط می‌شود. شما می‌توانید به صورت مستقیم به textView دسترسی پیدا کنید، بدون نیاز به استفاده از ()findViewById.‏‏‏Data Binding‏ چیست؟کتابخانه Data Binding‏ ‏یک کتابخانه قدرتمندتر است که به توسعه‌دهندگان اجازه می‌دهد تا اجزای رابط کاربری را به صورت مستقیم به منابع داده در لایه‌های خود متصل کنند. این کار با استفاده از فرمت اعلامی (declarative) انجام می‌شود و نیاز به نوشتن کد برنامه‌نویسی برای این اتصال را کاهش می‌دهد. Data Binding مقدار کد اضافه (boilerplate code) را کاهش می‌دهد و به‌ویژه برای مدیریت به‌روزرسانی‌ها و تعاملات پیچیده رابط کاربری مفید است.ویژگی‌های کلیدی Data Binding:دوطرفه (Two-Way Binding): Data Binding از بسته‌بندی دوطرفه پشتیبانی می‌کند، به این معنی که تغییرات در رابط کاربری به‌طور خودکار داده‌های زیرین را به‌روزرسانی می‌کند و بالعکس. این ویژگی به‌ویژه در برنامه‌های مبتنی بر فرم مفید است، جایی که ورودی‌های کاربر باید در مدل داده منعکس شوند.مثال : فرض کنید یک فرم ثبت‌نام دارید که شامل یک فیلد EditText برای وارد کردن نام کاربر است. با استفاده از Data Binding، می‌توانید به‌طور خودکار تغییرات در EditText را به مدل داده منتقل کنید و همچنین تغییرات در مدل را به EditText بازتاب دهید:در اینجا، وقتی کاربر نام خود را وارد کند، user.name به‌روزرسانی می‌شود و اگر برنامه user.name را تغییر دهد، مقدار جدید به‌طور خودکار در EditText نمایش داده می‌شود.زبان بیان (Expression Language): شما می‌توانید عبارات را به‌طور مستقیم در فایل‌های XML بنویسید، که این کار را برای دستکاری و نمایش داده‌ها آسان می‌کند بدون نیاز به منطق اضافی در فعالیت (Activity) یا Fragment شما.در اینجا، اگر سن کاربر بیش از ۱۸ باشد، TextView متن &quot;بزرگسال&quot; را نشان می‌دهد، در غیر این صورت &quot;کودک&quot; را نمایش می‌دهد.داده‌های قابل مشاهده (Observable Data): Data Binding به‌خوبی با منابع داده قابل مشاهده مانند LiveData ادغام می‌شود و مدیریت به‌روزرسانی‌های رابط کاربری در پاسخ به تغییرات داده را آسان‌تر می‌کند.مثال: فرض کنید که شما از LiveData برای مدیریت وضعیت یک اپلیکیشن استفاده می‌کنید. با استفاده از Data Binding، می‌توانید به راحتی تغییرات در LiveData را در UI خود بازتاب دهید:و در فایل XML:با این تنظیمات، هر بار که user در UserViewModel تغییر کند، TextView به‌طور خودکار به‌روزرسانی خواهد شد.موارد استفاده پیشرفته (Advanced Use Cases): این روش ایده‌آل برای سناریوهایی است که در آن‌ها نیاز به اتصال مدل‌های داده پیچیده، پیاده‌سازی منطق سفارشی، یا انجام اتصال شرطی به‌طور مستقیم در XML دارید.مثال: فرض کنید که می‌خواهید یک دکمه ایجاد کنید که بر اساس شرایط خاصی فعال یا غیرفعال شود. با استفاده از Data Binding، می‌توانید این منطق را به‌راحتی در XML پیاده‌سازی کنید:در اینجا، اگر isActive در مدل داده user تغییر کند، وضعیت فعال یا غیرفعال بودن دکمه به‌طور خودکار به‌روز خواهد شد. این نوع اتصال، کد نویسی را ساده‌تر و منطق را شفاف‌تر می‌کند.فعال کردن data binding در فایل build.gradle :ایجاد یک data class:استفاده از data binding در یک Activity:وصل کردن  data  در XML:در این مثال، nameTextView به طور خودکار به‌روزرسانی می‌شود تا نام کاربر را نمایش دهد زمانی که Data Binding انجام می‌شود.چه زمانی از  View Binding و Data Binding استفاده کنیم؟از View Binding استفاده کنید اگر:به دنبال راهی ساده و کارآمد برای تعامل با ویوها هستید.نیازی به انجام عملیات پیچیده روی داده‌ها یا منطق binding در لایه‌های خود ندارید.می‌خواهید خطر بروز خطاهای null pointer را کاهش دهید و از findViewById() اجتناب کنید.از Data Binding استفاده کنید اگر:به اتصال دوطرفه (two-way binding) بین رابط کاربری و مدل داده نیاز دارید.می‌خواهید منطق و عبارات را مستقیماً در XML بنویسید تا به‌روزرسانی‌های پویا در UI داشته باشید.از منابع داده قابل مشاهده مانند LiveData استفاده می‌کنید و به دنبال یکپارچگی آسان با UI هستید.این تفاوت‌ها به شما کمک می‌کنند تا تصمیم بگیرید کدام روش برای پروژه شما مناسب‌تر است. View Binding برای پروژه‌های ساده و کم پیچیده، و Data Binding برای پروژه‌هایی که نیاز به پیوندهای پویا و پیچیده دارند مناسب است.نتیجه گیری:هر دو روش Data Binding و View Binding ابزارهای قدرتمندی در برنامه‌های اندروید هستند. View Binding برای موارد استفاده ساده مناسب است و جایگزینی سبک و ایمن برای ()findViewById محسوب می‌شود. از سوی دیگر، Data Binding یک راهکار غنی‌تر با قابلیت‌های بیشتر است که در مواردی که نیاز به به‌روزرسانی‌های پویا و تعاملات پیچیده با داده‌ها وجود دارد، به خوبی عمل می‌کند.و در نهایت انتخاب بهترین گزینه به نیازهای خاص پروژه بستگی دارد.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Sun, 03 Nov 2024 13:53:19 +0330</pubDate>
            </item>
                    <item>
                <title>تکنیک‌های ساده خواندن SMS برای توسعه‌دهندگان اندروید</title>
                <link>https://virgool.io/codenevis/%D8%AA%DA%A9%D9%86%DB%8C%DA%A9-%D9%87%D8%A7%DB%8C-%D8%B3%D8%A7%D8%AF%D9%87-%D8%AE%D9%88%D8%A7%D9%86%D8%AF%D9%86-sms-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-u0qhnoe15cvb</link>
                <description>با استفاده از زبان کاتلین، روش‌های مختلفی را برای خواندن پیام‌های متنی و کدهای تایید یکبار مصرف وجود دارد که در این پست  به API SMS Retriever، Content Resolver و Broadcast Receiver پرداخته می‌شود.همانطور که می دانید تجربه کاربری روان در زمینه احراز هویت اهمیت بسیاری دارد. یکی از روش‌های رایج، استفاده از رمزهای یکبار مصرف (OTP) ارسال‌شده از طریق SMS است.در این پست، به بررسی چندین روش برای خواندن SMS در اندروید با استفاده از کاتلین می‌پردازیم و نحوه پیاده‌سازی هر یک از آن‌ها را به صورت مرحله‌به‌مرحله نشان می‌دهیم.چرا خواندن SMS برای تأیید OTP اهمیت دارد؟خواندن پیام‌های SMS به شما این امکان را می‌دهد که فرآیند ورود را با بازیابی خودکار OTP ارسال‌شده به کاربران ساده‌تر کنید. این کار تجربه کاربری را بهبود می‌بخشد، زیرا خطاهای ناشی از وارد کردن دستی را کاهش داده و احراز هویت را سرعت می‌بخشد.روش اول: استفاده از SMS Retriever APISMS Retriever API ابزاری قدرتمند از گوگل است که به شما اجازه می‌دهد پیام‌های SMS را بدون نیاز به مجوزهای SMS دریافت کنید.مرحله 1: تنظیم پروژهابتدا مطمئن شوید که وابستگی‌های لازم را در فایل build.gradle خود اضافه کرده‌اید:مرحله 2: شروع SMS Retrieverدر اکتیویتی خود، SMS Retriever را مقداردهی اولیه کنید:مرحله 3: ساخت یک BroadcastReceiverیک BroadcastReceiver ایجاد کنید تا پیام‌های ورودی SMS را مدیریت کند. این Receiver کد OTP را برای شما استخراج می‌کند.مرحله 4: ثبت BroadcastReceiverدر اکتیویتی خود، BroadcastReceiver را برای گوش دادن به SMS ثبت کنید:مرحله 5: ارسال یک SMS با فرمت صحیحمطمئن شوید که SMS ارسالی شما به درستی فرمت‌بندی شده باشد، مانند این:روش دوم: استفاده از Content Resolverاگر به کنترل بیشتری نیاز دارید و می‌خواهید پیام‌های SMS را به‌طور مستقیم بخوانید، می‌توانید از ContentResolver استفاده کنید. این روش به مجوز READ_SMS نیاز دارد.مرحله 1: اعلام مجوزهامجوز زیر را به فایل AndroidManifest.xml خود اضافه کنید:مرحله 2: درخواست مجوزدر اکتیویتی خود، مجوز را بررسی کرده و درخواست کنید:مرحله 3: خواندن SMSحالا می‌توانید پیام‌های SMS را با استفاده از ContentResolver بخوانید:مرحله 4: مدیریت نتیجه مجوزمطمئن شوید که نتیجه مجوز را مدیریت کنید:روش سوم: استفاده از BroadcastReceiver برای خواندن SMSهای ورودیاین روش یک راه ساده برای خواندن پیام‌های SMS با مجوزهای لازم فراهم می‌کند و به شما کنترل بر روی پیام‌های ورودی در حین دریافت آن‌ها می‌دهد.مرحله 1: اعلام مجوزهامجوز زیر را به فایل AndroidManifest.xml خود اضافه کنید:مرحله 2: ایجاد یک BroadcastReceiverیک BroadcastReceiver ایجاد کنید که به پیام‌های SMS ورودی گوش دهد:مرحله 3: ثبت Receiver در ManifestBroadcastReceiver خود را در فایل AndroidManifest.xml ثبت کنید:مرحله 4: مدیریت مجوزهامطمئن شوید که مجوزها را مدیریت می‌کنید، به‌ویژه در دستگاه‌های دارای Android 6.0 (API سطح 23) و بالاتر:حال با این سه روش شما می توانید پیامک های OTP را مدیرت کنید.تفاوت‌های کلیدیدر ادامه، تفاوت‌های کلیدی بین این روش‌ها را بررسی می‌کنیم تا به شما کمک کنیم بهترین گزینه برای نیازهای اپلیکیشن‌تان را انتخاب کنید.مورد استفاده:‏روش ‏‏SMS Retriever API: بهترین گزینه برای تأیید OTP و پیام‌های موقت.روش ‏‏BroadcastReceiver: مناسب برای اپلیکیشن‌هایی که نیاز به دسترسی فوری به پیام‌های ورودی دارند. روش Content Resolver: مناسب برای اپلیکیشن‌هایی که به دسترسی گسترده‌تر به پیام‌های SMS نیاز دارند (مثلاً برنامه‌های پیام‌رسان).مجوزهای مورد نیاز:روش  ‏SMS Retriever API: نیازی به مجوز برای خواندن SMS ندارد. ‏روش BroadcastReceiver: به مجوزهای RECEIVE_SMS و READ_SMS نیاز دارد. ‏روش Content Resolver: به مجوز READ_SMS نیاز دارد.حریم خصوصی:روش ‏SMS Retriever API: حریم خصوصی کاربر را افزایش می‌دهد و به همه پیام‌های SMS دسترسی ندارد.‏روش BroadcastReceiver: حریم خصوصی کمتری دارد؛ تمامی پیام‌های SMS ورودی را رهگیری می‌کند.روش ‏Content Resolver: حریم خصوصی کمتری دارد؛ به تمامی پیام‌های SMS دسترسی دارد.پیچیدگی پیاده‌سازی:روش ‏SMS Retriever API: ساده‌تر برای بازیابی OTP.روش ‏BroadcastReceiver: پیچیدگی متوسط؛ نیاز به مدیریت مجوزها و پیام‌های دریافتی دارد.‏روش Content Resolver: پیچیده‌تر؛ نیاز به مدیریت مجوزها و SMS دارد.تجربه کاربری:روش ‏SMS Retriever API: بدون وقفه و درخواست مجوز برای کاربر.‏روش BroadcastReceiver: ممکن است تجربه کاربری را با درخواست مجوز قطع کند.روش ‏Content Resolver: ممکن است تجربه کاربری را با درخواست مجوز قطع کند.فیلتر پیام‌ها:روش SMS Retriever API: به‌طور خودکار پیام‌ها را بر اساس معیارهای از پیش تعیین‌شده فیلتر می‌کند.روش ‏BroadcastReceiver: نیاز به پردازش دستی پیام‌های رهگیری‌شده دارد.روش ‏Content Resolver: نیاز به فیلتر و پردازش دستی پیام‌ها دارد.بازیابی هم‌زمان:روش ‏SMS Retriever API: ‏SMS را فقط زمانی بازیابی می‌کند که با فرمت مشخصی برای API ارسال شده باشد.روش BroadcastReceiver: پیام‌های SMS را به محض ورود رهگیری می‌کند.‏روش Content Resolver: می‌تواند در هر زمان پیام‌های SMS را از صندوق ورودی بخواند.فرمت پیام SMS:روش ‏SMS Retriever API: نیاز به فرمت خاصی دارد (مثلاً با هش).روش ‏BroadcastReceiver: نیازی به فرمت خاصی ندارد؛ تمامی پیام‌های ورودی را رهگیری می‌کند.‏روش Content Resolver: نیازی به فرمت خاصی ندارد؛ می‌تواند هر پیام SMS را بخواند.خلاصه:روش ‏SMS Retriever API برای بازیابی OTP و احراز هویت گزینه‌ای ایده‌آل است و رویکردی ساده و دوستدار حریم خصوصی ارائه می‌دهد.‏روش BroadcastReceiver پیام‌های SMS ورودی را به‌صورت هم‌زمان دریافت می‌کند، اما نیاز به مجوز دارد و تمامی پیام‌ها را پردازش می‌کند که ممکن است همیشه برای حفظ حریم خصوصی کاربر مناسب نباشد.روش ‏Content Resolver دسترسی گسترده‌تری به SMS فراهم می‌کند، اما نیاز به تنظیمات بیشتر و مجوزهای کاربر دارد و مناسب اپلیکیشن‌هایی است که به مدیریت جامع SMS نیاز دارند.نتیجه گیری:هر روش مزایا و معایب خاص خود را دارد، بنابراین بهترین انتخاب بسته به نیازهای خاص اپلیکیشن شما و تجربه کاربری مطلوب شما متفاوت است!ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Mon, 28 Oct 2024 10:39:54 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت بین Stateflow و Sharedflow</title>
                <link>https://virgool.io/@mohaammaadsadeq/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D8%A8%DB%8C%D9%86-stateflow-%D9%88-sharedflow-qdhjkbe18kfj</link>
                <description>‏StateFlow چیست؟‏StateFlow یک نگهدارنده حالت (state holder) است. همیشه دارای یک مقدار است (اولیه یا به‌روزرسانی‌شده)، و آخرین مقدار خود را به جمع‌کننده‌هایش(Collectors) ارسال می‌کند. از StateFlow زمانی استفاده می‌شود که بخواهید یک بخش از حالت را نشان دهید که در طول زمان تغییر می‌کند.‏StateFlow مشابه LiveData است زیرا به شما اجازه می‌دهد تغییرات یک مقدار را مشاهده کنید و به طور خودکار کامپوننت‌های رابط کاربری را وقتی که مقدار تغییر می‌کند، به‌روز رسانی کنید.نکته:جمع‌کننده‌ یا همان Collector در برنامه‌نویسی با Flow به موجودیتی گفته می‌شود که داده‌های ارسال‌شده توسط یک Flow را دریافت می‌کند. جمع‌کننده‌ها (collectors) مسئول دریافت و پردازش مقادیر جاری از جریان داده‌ها هستند. به طور ساده، Collector همان بخشی از برنامه است که به جریان داده‌ها گوش می‌دهد و به محض دریافت داده‌های جدید، آن‌ها را پردازش می‌کند.برای مثال، وقتی از یک Flow داده‌هایی را منتشر می‌کنید، یک Collector می‌تواند آن داده‌ها را دریافت کند و بر اساس آن‌ها عملیات خاصی انجام دهد، مانند به‌روزرسانی رابط کاربری یا ذخیره داده‌ها.مثال برا StateFlow: فرض کنید یک اپلیکیشن پخش موسیقی دارید. پخش‌کننده دارای حالت‌هایی مانند در حال پخش، توقف موقت یا  متوقف‌شده است. شما می‌توانید از StateFlowاستفاده کنید تا حالت کنونی پخش‌کننده را نشان دهید و آن را مشاهده کنید. به این صورت که هر زمان وضعیت پخش تغییر کند، رابط کاربری و بخش‌های دیگر برنامه به‌روز می‌شوند.‏‏SharedFlow چیست؟‏SharedFlow شبیه به یک کانال پخش (broadcast channel) است. می‌تواند چندین مقدار را ارسال کند و جمع‌کننده‌های (collector) متعددی می‌توانند به آن مقادیر گوش دهند. برخلاف ‏StateFlow ،‏SharedFlow  ‏مقدار اولیه ندارد، اما می‌توانید تنظیم کنید که چند مقدار قبلی را برای جمع‌کننده‌های جدید بازپخش کند.مثالSharedFlow : تصور کنید یک برنامه چت دارید که کاربران می‌توانند پیام ارسال کنند. وقتی یک کاربر پیام می‌فرستد، همه کاربران آنلاین باید آن را دریافت کنند. SharedFlow می‌تواند برای پخش این پیام‌ها به همه کاربران آنلاین استفاده شود. این امکان را فراهم می‌کند که همه گیرندگان همزمان به داده‌های پخش شده دسترسی داشته باشند.تفاوت های StateFlow و SharedFlow نوع داده:‏‏‏نوع داده StateFlow: نمایانگر یک حالت قابل تغییر (mutable) است که در طول زمان تغییر می‌کند. فقط آخرین حالت را به جمع‌کننده‌های خود ارسال می‌کند.نوع داده ‏SharedFlow: نمایانگر یک جریان از مقادیری است که در طول زمان ارسال می‌شوند. می‌تواند مقادیر متعددی را به جمع‌کننده‌ها ارسال کند.تغییرپذیری:تغییرپذیری StateFlow: حالتی که توسط StateFlow نگهداری می‌شود قابل تغییر است و می‌توان آن را با استفاده از ویژگی value به‌روزرسانی کرد.تغییرپذیری ‏SharedFlow: مقادیری که توسط SharedFlow ارسال می‌شوند، غیرقابل تغییر هستند؛ زمانی که یک مقدار ارسال شد، دیگر قابل تغییر نیست.رفتار در زمان اشتراک‌گذاری:اشتراک‌گذاری ‏StateFlow: زمانی که جمع‌کننده‌ای به StateFlow مشترک می‌شود، بلافاصله آخرین وضعیت موجود را دریافت می‌کند. این ویژگی برای سناریوهایی مثل اپلیکیشن‌های بانکی که کاربر باید همیشه آخرین وضعیت حساب خود را مشاهده کند، بسیار مفید است.‏اشتراک‌گذاری SharedFlow: وقتی جمع‌کننده‌ای به SharedFlow مشترک می‌شود، هیچ مقداری بلافاصله دریافت نمی‌کند و فقط مقادیری که پس از شروع جمع‌آوری ارسال شده‌اند را دریافت می‌کند. مثل زمانی که در یک گروه پیام‌رسانی به تازگی عضو می‌شوید و پیام‌های جدید را دریافت می‌کنید.نکته: در اینجا &quot;مشترک می‌شود&quot; به معنای Subscribe کردن به یک جریان داده است. وقتی می‌گوییم جمع‌کننده‌ای (collector) به StateFlow* یا SharedFlow مشترک می‌شود، یعنی آن جمع‌کننده به این جریان متصل می‌شود تا بتواند داده‌ها یا تغییرات حالت را از جریان دریافت کند.در واقع، در برنامه‌نویسی زمانی که یک جمع‌کننده به یک جریان مشترک می‌شود، از آن نقطه به بعد هر داده یا تغییر جدیدی که در جریان اتفاق بیفتد، به جمع‌کننده ارسال می‌شود. این فرآیند به طور غیرهمزمان (asynchronous) و بدون نیاز به درخواست مکرر جمع‌کننده انجام می‌شود.مثلاً در یک اپلیکیشن چت، اگر شما به SharedFlow پیام‌ها مشترک شوید، هر پیام جدیدی که در چت ارسال شود به شما نمایش داده می‌شود.هم‌ترازی مقادیر (Conflation):هم‌ترازی مقادیر ‏StateFlow: به طور خودکار مقادیر ارسال‌شده را هم‌تراز می‌کند، به این معنا که فقط آخرین وضعیت را جمع‌کننده‌ها دریافت می‌کنند. این ویژگی زمانی مفید است که به‌روزرسانی‌های سریع و مداوم داریم، مثل وضعیت آب‌وهوا که فقط آخرین تغییر مهم است.‏هم‌ترازی مقادیر SharedFlow: مقادیر ارسال‌شده را هم‌تراز نمی‌کند؛ همه مقادیر ارسال‌شده تا زمانی که جمع‌آوری شوند، در دسترس هستند. این ویژگی برای مواردی مثل نوتیفیکیشن‌های یک فروشگاه آنلاین مفید است، جایی که هر به‌روزرسانی و پیام ممکن است مهم باشد.نکته: &quot;هم‌تراز&quot; به معنی Conflation در زمینه‌ی برنامه‌نویسی با جریان‌های داده (مثل Flow، StateFlow و SharedFlow) است. وقتی می‌گوییم یک جریان داده &quot;هم‌تراز&quot; می‌شود، منظور این است که اگر مقادیر زیادی به سرعت ارسال شوند، فقط آخرین مقدار به جمع‌کننده‌ها (collectors) ارائه می‌شود و مقادیر قبلی که هنوز پردازش نشده‌اند نادیده گرفته می‌شوند.به عبارت دیگر، هم‌ترازی به معنای این است که مقادیر قبلی حذف می‌شوند تا فقط آخرین مقدار برای جمع‌کننده ارسال شود. این ویژگی در StateFlow به‌طور پیش‌فرض وجود دارد. به عنوان مثال:فرض کنید شما یک اپلیکیشن وضعیت آب‌وهوا دارید که به سرعت تغییرات دمایی را دریافت می‌کند. اگر جریان هم‌تراز باشد، فقط آخرین دما به جمع‌کننده ارسال می‌شود و تغییرات قبلی نادیده گرفته می‌شوند. این باعث می‌شود که رابط کاربری شما فقط آخرین وضعیت را نمایش دهد و نیازی به پردازش تمام تغییرات قبلی نداشته باشد.در مقابل، در SharedFlow چنین هم‌ترازی به‌طور خودکار وجود ندارد و همه مقادیر به ترتیب به جمع‌کننده‌ها ارائه می‌شوند، مگر اینکه خودتان آن را تنظیم کنید.بافرینگ:بافرینگ ‏StateFlow: توانایی بافر کردن ندارد، زیرا تنها یک حالت واحد را نشان می‌دهد.بافرینگ SharedFlow: می‌تواند مقادیر ارسال‌شده را برای جمع‌کننده‌هایی که به‌صورت فعال مصرف نمی‌کنند، بافر کند، بر اساس اندازه بافر و استراتژی سرریز تعیین‌شده. این ویژگی برای اپلیکیشن‌های شبکه‌ای مثل استریم موسیقی که باید داده‌ها را در زمان مناسب به مصرف‌کننده‌ها ارائه دهند، مفید است.نکته: بافرینگ (Buffering) در زمینه جریان‌های داده (Flow) به معنای ذخیره‌سازی موقت داده‌ها قبل از ارسال به جمع‌کننده‌ها (collectors) است. وقتی بافر فعال باشد، داده‌های ارسال‌شده در بافر ذخیره می‌شوند تا جمع‌کننده‌ها بتوانند بعداً آن‌ها را دریافت و پردازش کنند.به بیان ساده‌تر، اگر جریان داده به سرعت مقادیر جدید تولید کند ولی جمع‌کننده نتواند به همان سرعت آن‌ها را پردازش کند، بافر داده‌ها را موقتاً ذخیره می‌کند تا وقتی جمع‌کننده آماده شد، داده‌های ذخیره‌شده را دریافت کند. این امر کمک می‌کند که داده‌ها از دست نروند.مثال:فرض کنید در یک اپلیکیشن چت، پیام‌های زیادی از سوی کاربران ارسال می‌شود. اگر کاربر یا سرور شما نتواند همه پیام‌ها را به‌سرعت پردازش کند، بافر کردن پیام‌ها به شما کمک می‌کند تا همه پیام‌ها به‌طور موقت ذخیره شوند و بعداً به کاربر نمایش داده شوند.ارتباط یک به چند یا چند به چند:‏ارتباط StateFlow: معمولاً برای ارتباط یک به چند استفاده می‌شود؛ یعنی چندین جمع‌کننده وضعیت مشترکی را مشاهده و به آن واکنش نشان می‌دهند. مثال: حالت لاگین کاربران در یک اپلیکیشن بانکداری که همه اجزای رابط کاربری باید وضعیت ورود یا خروج کاربر را بدانند.‏ارتباط SharedFlow: برای سناریوهای چند به چند مناسب است، جایی که چند تولیدکننده می‌توانند مقادیر را ارسال کنند و چندین جمع‌کننده نیز به طور مستقل آن‌ها را مصرف می‌کنند. مثال: چت‌های گروهی در یک اپلیکیشن پیام‌رسان.مقداردهی اولیه:مقداردهی اولیه ‏StateFlow: باید با یک وضعیت اولیه از طریق سازنده MutableStateFlow مقداردهی اولیه شود. مثلاً، در شروع یک اپلیکیشن پخش ویدیو، حالت پیش‌فرض می‌تواند &quot;توقف‌شده&quot; باشد.مقداردهی اولیه ‏SharedFlow: می‌تواند بدون مقدار اولیه ایجاد شود و به محض در دسترس بودن مقادیر شروع به ارسال آن‌ها کند. مثل داده‌های حسگرها در یک اپلیکیشن ردیابی سلامت که با شروع فعالیت کاربر ارسال می‌شوند.استفاده در رابط کاربری (UI):‏رابط کاربری StateFlow: اغلب در کدهای مربوط به UI برای نمایش حالت‌های UI استفاده می‌شود که نیاز به مشاهده توسط چندین جزء رابط کاربری دارند. مثل حالت‌های صفحه ورود که وضعیت ورود یا خروج کاربر را نمایش می‌دهد.رابط کاربری ‏SharedFlow: برای مدیریت رویدادهای غیرهمزمان یا جریان‌های داده مفید است، جایی که بخش‌های مختلف برنامه نیاز به اطلاع از تغییرات دارند. مثل نوتیفیکیشن‌های لحظه‌ای در اپلیکیشن‌های خرید آنلاین که همه مشتریان باید از رویدادها مطلع شوند.نتیجه‌گیری:‏StateFlow برای مدیریت حالت‌های متغیر و نمایش آخرین وضعیت به چندین جمع‌کننده مناسب است، مانند به‌روزرسانی رابط کاربری. این جریان همواره آخرین مقدار را نگه می‌دارد و به محض اشتراک‌گذاری، آن را به جمع‌کننده‌ها ارسال می‌کند. SharedFlow ‏برای پخش چندین مقدار به جمع‌کننده‌های متعدد در طول زمان کاربرد دارد. این جریان برای مواردی که نیاز به مدیریت رویدادهای متوالی (مثل پیام‌ها یا نوتیفیکیشن‌ها) است، مناسب بوده و قابلیت بافرینگ و بازپخش مقادیر را دارد.هر دو ابزار قدرتمندی برای مدیریت داده‌ها در سناریوهای مختلف برنامه‌نویسی اندروید هستند.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Wed, 09 Oct 2024 15:34:22 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت بین constructor و init در کاتلین</title>
                <link>https://virgool.io/@mohaammaadsadeq/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D8%A8%DB%8C%D9%86-constructors-%D9%88-init-%D8%AF%D8%B1-%DA%A9%D8%A7%D8%AA%D9%84%DB%8C%D9%86-nq6sib2fchxs</link>
                <description>در کاتلین، constructors و بلوک‌های init برای مقداردهی اولیه کلاس‌ها استفاده می‌شوند، اما اهداف و ویژگی‌های متفاوتی دارند. در اینجا چهار تفاوت اصلی بین constructors و بلوک‌های init در کاتلین آمده است:1. نحوه تعریف کردن و Syntax:تعریف ‏‏Primary Constructor : در سربرگ کلاس، بلافاصله بعد از نام کلاس اعلام می‌شود.تعریف Secondary Constructor: در بدنه کلاس با استفاده از کلمه کلیدی constructor اعلام می‌شود.مثال:بلوک init:با استفاده از کلمه کلیدی init در داخل بدنه کلاس تعریف می‌شود.یک کلاس می‌تواند چندین بلوک init داشته باشد که به ترتیبی که ظاهر می‌شوند اجرا می‌شوند.مثال:2. هدف ایجاد هرکدام به شرح زیر می باشد:هدف ‏‏‏‏‏‏‏‏‏‏Primary Constructor‏: یک روش برای ساخت یک شیء از کلاس است که به شما امکان می‌دهد اطلاعات لازم را به آن بدهید. مثلاً وقتی یک کلاس کتاب دارید، سازنده اصلی می‌تواند نام کتاب و نویسنده را به عنوان ورودی بگیرد تا آن شیء ساخته شود.هدف Secondary Constructor: اگر بخواهید constructor های بیشتری برای ساختن شیء داشته باشید، از Secondary Constructor استفاده می‌کنید. مثلاً اگر بخواهید کتابی را فقط با نام نویسنده و بدون سال انتشار بسازید، از ‏‏Secondary Constructor استفاده می‌کنید.هدف بلوک init: برای انجام کارهای خاصی که نیاز به منطق پیچیده دارد یا وقتی می‌خواهید یک چیزی را بررسی کنید، استفاده می‌شود. مثلاً اگر بخواهید وقتی یک کتاب ساخته می‌شود، مطمئن شوید که سال انتشار منفی نباشد، از init استفاده می‌کنید. این بلوک بلافاصله بعد از اینکه سازنده اصلی کارش را انجام داد، اجرا می‌شود. این بلوک بلافاصله پس از سازنده اصلی اجرا می‌شود.برای درک بهتر تفاوت‌ها، مثال زیر را مطالعه کنید:فرض کنید می‌خواهیم یک کلاس برای اطلاعات یک کتابخانه بسازیم.مثال ‏‏‏‏‏‏‏‏‏‏‏‏‏Primary Constructor‏:برای پارامترهایی مانند نام کتاب، نام نویسنده و سال انتشار استفاده می‌شود. این سازنده به ما امکان می‌دهد که به سادگی اطلاعات اصلی یک کتاب را در هنگام ایجاد آن مقداردهی کنیم.مثال ‏‏Secondary Constructor:اگر بخواهیم راه‌های دیگری برای ساخت شیء از کلاس book ارائه دهیم، می‌توانیم از ‏‏Secondary Constructor استفاده کنیم. برای مثال، ‏‏Secondary Constructor می‌تواند حالتی را تعریف کند که فقط نام کتاب و نویسنده داده شود و سال انتشار به صورت پیش‌فرض صفر باشد.مثال بلوک init:اگر نیاز به اجرای منطق پیچیده‌تر یا اعمال برخی اطلاعات (مانند چاپ یک پیام خوش‌آمدگویی به محض ایجاد یک کتاب) داشته باشیم، می‌توانیم از بلوک init استفاده کنیم. این منطق بلافاصله بعد از مقداردهی اولیه اجرا می‌شود. به عنوان مثال، می‌توانیم بررسی کنیم که اگر سال انتشار منفی بود، یک پیغام خطا چاپ شود.در این مثال، ‏‏‏‏‏‏‏‏‏‏Primary Constructor برای مقداردهی ویژگی‌ها استفاده می‌شود، ‏‏Secondary Constructor راهی جایگزین برای مقداردهی ارائه می‌دهد، و بلوک init برای بررسی‌های اضافه و اعمال منطق اضافی پس از مقداردهی استفاده می‌شود.3. ترتیب اجرا:‏‏‏‏‏‏‏‏‏‏‏‏اجرای Primary constructor به شکل است که این Constructor ابتدا اجرا می‌شود و سپس بلوک‌های init به ترتیب اجرا می‌شوند. اگر ‏‏Secondary Constructor وجود داشته باشد، آن باید به ‏‏ ‏‏‏‏‏‏‏‏‏‏Primary Constructor ارجاع دهد و بلوک‌های init بعد از اتمام کار ‏‏ ‏‏‏‏‏‏‏‏‏‏Primary Constructor اجرا می‌شوند.4. مقداردهی ویژگی‌ها(Property):مقداردهیPrimary Constructor : بهترین گزینه برای مقداردهی مستقیم ویژگی‌ها است. به این معنی است که می‌توانید به راحتی مقادیر ویژگی‌ها (Property) را هنگام ساخت شیء به آن‌ها بدهید.مقداردهی‏‏Secondary Constructor : می‌تواند ویژگی‌ها را نیز مقداردهی کند، اما معمولاً برای یکپارچگی (سازگاری) به سازنده اصلی ارجاع می‌دهد تا کد تمیز و یکسانی داشته باشد.مقدار دهی بلوک init : بلوک init برای مقداردهی ویژگی‌هایی که نیاز به منطق پیچیده دارند یا به ویژگی‌های دیگر وابسته‌اند، بسیار مفید است و می‌توان از آن برای تنظیم مقادیر پیش‌فرض یا انجام کارهای اضافی در زمان ساخت شیء استفاده کرد.نتیجه گیری:‏‏constructors در کاتلین عمدتاً برای انتقال پارامترها و مقداردهی به ویژگی‌ها به کار می‌روند، در حالی که بلوک‌های init برای اجرای منطق پیچیده‌ای هستند که باید بعد از سازنده اصلی اجرا شود. هر دو نقش مهمی در راه‌اندازی درست یک نمونه از کلاس دارند.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Sun, 06 Oct 2024 12:46:46 +0330</pubDate>
            </item>
                    <item>
                <title>‏singleton در کاتلین</title>
                <link>https://virgool.io/@mohaammaadsadeq/singleton-%D9%88-object-%D8%AF%D8%B1-%DA%A9%D8%A7%D8%AA%D9%84%DB%8C%D9%86-exeuhmiflqsb</link>
                <description>‏singleton در کاتلین:در کاتلین، سینگلتون‌ها با استفاده از کلمه کلیدی object ایجاد می‌شوند. این کار تضمین می‌کند که تنها یک نمونه از شیء ایجاد شده و در سراسر برنامه استفاده می‌شود.‏(Thread Safety) در سینگلتون‌های کاتلین:‏Thread Safety در سینگلتون‌های کاتلین به این معناست که وقتی یک شیء سینگلتون ایجاد می‌شود، حتی اگر چندین رشته (Thread) همزمان بخواهند به آن دسترسی پیدا کنند، مشکلی پیش نخواهد آمد. کاتلین این فرآیند را به‌طور خودکار مدیریت می‌کند و اطمینان می‌دهد که تنها یک نمونه از سینگلتون در زمان اجرای برنامه ساخته شود، حتی اگر دسترسی همزمان از چندین بخش برنامه صورت بگیرد.به عبارت دیگر، در زبان‌های برنامه‌نویسی معمولاً وقتی چندین رشته بخواهند به یک منبع مشترک دسترسی داشته باشند، احتمال ایجاد مشکل وجود دارد مگر اینکه خود برنامه‌نویس مکانیزم‌هایی برای جلوگیری از این تداخل پیاده‌سازی کند. اما در کاتلین، برای سینگلتون‌ها نیازی به این کار نیست. کامپایلر به طور خودکار از Thread Safety برای ایجاد و مدیریت سینگلتون‌ها اطمینان حاصل می‌کند، به طوری که فقط یک نمونه از شیء ایجاد و استفاده شود، بدون نگرانی از ایجاد تداخل‌های احتمالی در زمان دسترسی‌های همزمان.در مثال بالا، شیء سینگلتون به صورت Thread-safe مقداردهی اولیه می‌شود. بلوک init فقط یک بار اجرا خواهد شد، صرف نظر از اینکه چند رشته همزمان در حال تلاش برای دسترسی به شیء سینگلتون باشند. این بدان معناست که حتی اگر چندین رشته بخواهند به طور همزمان به شیء دسترسی پیدا کنند، فرآیند مقداردهی اولیه تنها یک بار انجام می‌شود و تمامی دسترسی‌های بعدی به همان نمونه اولیه هدایت می‌شوند.‏(Objects) در کاتلین و  (Thread Safety):در کاتلین، یک Object اساساً یک سینگلتون است. ویژگی‌های Thread Safety که برای سینگلتون‌ها توضیح داده شد، به تمامی اشیایی که با استفاده از کلمه کلیدی object در کاتلین تعریف می‌شوند، اعمال می‌شود. این بدان معناست که هر شیء ایجاد شده با کلمه کلیدی object به طور ذاتی Thread Safety است و نیازی به اقدامات اضافی برای اطمینان از Thread Safety وجود ندارد.تفاوت بین Singleton و Object:در کاتلین، کلمه کلیدی مستقیمی برای &quot;سینگلتون&quot; وجود ندارد؛ به جای آن، از کلمه کلیدی object برای ایجاد کلاس‌های تک‌نمونه‌ای (Single-instance) استفاده می‌شود که در عمل سینگلتون هستند. بنابراین، یک Object در کاتلین به طور طبیعی سینگلتون است و هر دو اصطلاح &quot;singleton &quot; و &quot;Object&quot; را می‌توان به صورت متناوب در کاتلین استفاده کرد.یک مثال از Object:‏Thread Safety در object کاتلین:  همان‌طور که قبلاً ذکر شد، کاتلین اطمینان می‌دهد که شیء ‌ای مانند NetworkManager به صورت Thread Safety مقداردهی اولیه می‌شود. شما می‌توانید با اطمینان از چندین رشته به تابع ()sendRequest فراخوانی انجام دهید، بدون نگرانی از ایجاد چندین نمونه یا مشکلات مربوط به مقداردهی اولیه همزمان.ایمنی رشته‌ای با مقداردهی اولیه به روش Lazy  اگر نیاز به کنترل بیشتری بر روی مقداردهی اولیه سینگلتون خود دارید، می‌توانید از مکانیزم Lazy در کاتلین استفاده کنید. این ویژگی به شما اجازه می‌دهد تا منطق مقداردهی اولیه را تعریف کرده و اطمینان حاصل کنید که Thread Safety بر اساس نیازهای شما رعایت شود. با استفاده از Lazy، مقداردهی اولیه تنها زمانی انجام می‌شود که برای اولین بار به شیء دسترسی پیدا شود، و کاتلین به صورت خودکار Thread Safety را مدیریت می‌کند.در این مثال، نمونه‌ی MySingleton به صورت Lazy  و به شکل Thread Safety با استفاده از LazyThreadSafetyMode.SYNCHRONIZED مقداردهی اولیه می‌شود. این حالت از Synchronization اطمینان حاصل می‌کند که در صورت دسترسی همزمان از چندین رشته، تنها یک نمونه از MySingleton ایجاد خواهد شد و فرآیند مقداردهی اولیه به صورت Thread Safety مدیریت می‌شود. این روش ایده‌آل برای زمانی است که می‌خواهید سینگلتون فقط در زمان نیاز مقداردهی اولیه شود و در عین حال Thread Safety را تضمین کنید. نتیجه‌گیری:سینگلتون‌های کاتلین (که با استفاده از کلمه کلیدی object ایجاد می‌شوند) به‌صورت ذاتی Thread Safety  هستند.  ‏object کاتلین عملاً سینگلتون محسوب می‌شوند و از همان ویژگی‌های Thread Safety بهره می‌برند.  مقداردهی اولیه Lazy  می‌تواند برای کنترل بیشتر بر فرآیند ایجاد و مقداردهی استفاده شود و Thread Safety را در مواقع مورد نیاز تضمین کند.  طراحی کاتلین ایجاد سینگلتون‌ها و object‏ های Thread Safety‏ را ساده کرده و پیچیدگی و خطاهای احتمالی مرتبط با synchronization را کاهش می‌دهد.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Sun, 08 Sep 2024 12:57:08 +0330</pubDate>
            </item>
                    <item>
                <title>محمد صادق مهرافزون(بیوگرافی)</title>
                <link>https://virgool.io/@mohaammaadsadeq/%D9%85%D8%AD%D9%85%D8%AF-%D8%B5%D8%A7%D8%AF%D9%82-%D9%85%D9%87%D8%B1%D8%A7%D9%81%D8%B2%D9%88%D9%86%D8%A8%DB%8C%D9%88%DA%AF%D8%B1%D8%A7%D9%81%DB%8C-qox8el5lodlp</link>
                <description>در این پست میخوام یک بیوگرافی درمورد خودم بهتون بدم تا بیشتر با من آشنا بشید😊خلاصه رزومه:&quot;من محمد صادق مهرافزون، برنامه‌نویس اندروید با بیش از ۴ سال سابقه در توسعه اپلیکیشن‌های موبایل. تجربه کار با زبان‌های جاوا و کاتلین، jetpackCompose، معماری‌های MVP MVC , MVVM و استفاده از کتابخانه‌هایی مانند Retrofit ، Dagger2 و... را در رزومه‌ام دارم. همچنین، اپلیکیشن های موفقی همچون &#x27;شماره جهانی&#x27;، &#x27;رهگیر&#x27; و &#x27;خاطرنشان&#x27; را در بازار منتشر کرده ام. از جمله فعالیت‌های دیگر من، سابقه تدریس آنلاین در فرادرس و مشارکت در پروژه‌های متعدد openSource در گیت‌هاب است. من به کارهای تیمی و پروژه‌های جدید با چالش‌های مختلف علاقه‌مند هستم.&quot;اپلیکشن های من دربازار:1. اپلیکیشن رهگیر:زمانی که خریدی انجام میدهید و یا بسته ای پست می کنید، یک کد رهگیری برای شما صادر میشود این ،کد برای پیگیری مرسولات پستی شماست. حالا اپلیکیشن رهگیر در اختیار شماست تا با وارد کردن این کد رهگیری آخرین وضعیت ارسال بسته خود را استعلام بگیرید و جزئیات آن را مشاهده کنید.2. اپلیکیشن خاطرنشان:اپلیکیشن خاطرنشان یک اپلیکیشن برنامه ریزی است که دارای امکانات جذاب از جمله قفل برنامه ، دو زبانه ، انتخاب تم دلخواه ، تقویم اختصاصی، دسته بندی  و ... است که شما از طریق این برنامه می توانید کارهای خود را برنامه ریزی و هدف گذاری کنید. 4. اپلیکیشن شماره جهانی:با اپلیکیشن شماره جهانی شما می توانید برای تمامی سرویس ها، خیلی سریع و راحت شماره مجازی خریداری کنید   5. اپلیکیشن جاسوس باهوش:این اپلیکیشن ساده شده از بازی مافیا است برای دورهمی ها شمالینک اپلیکیشن ها در بازارپروژه های Open-source من در گیت هاب:من در گیت هاب پروژه های اوپن سورس هم کار کردم که لیست آن به شرح زیر است :1. مینی پروژه ساخت Api با spring boot2. پروژه DictionaryJetpackCompose دیکشنری ساده با  ( JetpackCompose ,Hilt for Android, Room, kotlin Coroutines,Navigation)3. پروژه MyPostApplication  با  ( Clean Architecture , MVVM Pattern, kotlin and java , single Activity)4. پروژه AnalysisCoins با ( Retrofit , Kotlin Coroutine ,MVVM) 5. پروژه TopFootball با (Rx java ,Navigation Component ,Retrofit)6. پروژه MrFile کار با فایل های گوشیلینک گیت هاب مناگر برای کسب و کار خودتون نیاز به اپلیکیشن دارید از طریق راههای ارتباطی لطفا پیام بدین همچنین آماده همکاری با تیم های برنامه نویسی و نوشتن پروژه های دانشجویی هستم.اینستاگرامgmail: misterdeveloper01@gmail.comمقاله به ثبت رسیده من:  بررسی و مروری برچالش های طراحی و توسعه اپلیکیشن موبایللینک مقاله </description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Sat, 13 Jul 2024 20:32:03 +0330</pubDate>
            </item>
                    <item>
                <title>انتقال داده‌ها بین صفحات در Jetpack Compose</title>
                <link>https://virgool.io/codenevis/%D8%A7%D9%86%D8%AA%D9%82%D8%A7%D9%84-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7-%D8%A8%DB%8C%D9%86-%D8%B5%D9%81%D8%AD%D9%87-%D9%86%D9%85%D8%A7%DB%8C%D8%B4-%D8%AF%D8%B1-jetpack-compose-lgbs00z55yrp</link>
                <description>Jetpack Compose یک سیستم navigation قدرتمند برای ساخت تجربیات کاربری بصری (UI) در برنامه‌های اندرویدی شما فراهم می‌کند. هنگام جابجایی بین صفحات، ممکن است نیاز داشته باشید که داده‌های را از یک صفحه لیست به یک صفحه جزئیات به اشتراک بگذارید. در این پست ما دو روش خوب برای دستیابی به این هدف را بررسی می‌کنیم و همچنین مزایا و معایب هر کدام را شرح می‌دهیم تا شما بتوانید راه حل مدنظر خود را انتخاب کنید.چالش‌های مربوط به آرگومان‌های Jetpack Compose Navigation:در حالی که Jetpack Compose navigation روشی راحت برای جابجایی بین صفحات ارائه می‌دهد، در حال حاضر محدودیت‌هایی در هنگام ارسال اشیاء داده‌ای پیچیده به عنوان آرگومان دارد. در زیر به برخی از نکات کلیدی اشاره شده است:محدودیت‌های آرگومان‌های Jetpack Compose Navigation:آرگومان‌های Jetpack Compose navigation در حال حاضر به انواع داده‌های اولیه و اشیاء Parcelable محدود هستند. این به این معناست که نمی‌توانید اشیاء پیچیده یا کلاس‌های داده سفارشی را به طور مستقیم به عنوان آرگومان ارسال کنید. (داده های اولیه مانند int, string و ...) (اشیاء Parcelable: مثل Bundle) آرگومان‌های navigation برای قطعات کوچک داده که نیاز به جابجایی بین صفحات دارند، طراحی شده‌اند. برای مجموعه داده‌های بزرگتر یا اشیاء پیچیده، توصیه می‌شود از Shared ViewModel یا راه‌حل‌های مدیریت وضعیت دیگر استفاده کنید.روش‌های انتقال داده بین صفحات:1. روش اول : انتقال داده به صورت رشته JSON (راه‌حل موقت) یک راه‌حل موقت رایج برای این محدودیت، تبدیل شیء داده‌ای شما (مثلاً مدل TV show) به یک رشته JSON با استفاده از کتابخانه‌هایی مانند GSON یا Moshi است. در اینجا یک تقسیم‌بندی از مراحل آورده شده است:      1. ایجاد مدل داده: یک کلاس داده تعریف کنید که نمایانگر شیء TVShow شما باشد. این کلاس شامل ویژگی‌هایی مانند عنوان، توضیحات و امتیازات خواهد بود.2. Serializing به JSON: در صفحه لیست، هنگامی که کاربر بر روی یک آیتم TVShow کلیک می‌کند، TVShow مربوطه را به JSON تبدیل کنید.3. navigation با آرگومان: از کتابخانه navigation استفاده کنید تا به صفحه جزئیات بروید. رشته JSON که Serializing کرده‌اید را به عنوان یک آرگومان به صفحه جزئیات ارسال کنید.4. Deserializing در صفحه جزئیات: در تابع composable صفحه جزئیات، به آرگومان‌های دریافتی دسترسی پیدا کرده و رشته JSON را دوباره به شیء اصلی TV show  را Deserializing کنید.5. استفاده از شیء: اکنون شما شیء TVShow را در صفحه جزئیات دارید. از ویژگی‌های آن برای پر کردن عناصر رابط کاربری و نمایش جزئیات نمایش می توانید استفاده کنید.همه کد ها کنار هم:مزایا:پیاده‌سازی ساده، به‌ویژه برای پروژه‌هایی با وابستگی‌های کم.مناسب برای سناریوهایی که پیچیدگی شیء پایین است.معایب:موجب سربار تبدیل داده‌های غیرضروری می‌شود که می‌تواند بر عملکرد هنگام انتقال مکرر داده‌ها یا اشیاء پیچیده تأثیر بگذارد.از مزایای سیستم composable در Jetpack Compose برای مدیریت داده‌ها بهره نمی‌برد.2. روش دوم : استفاده از Shared ViewModel (توصیه‌شده)این روش جداسازی بهتری از وابستگی ها را ترویج می‌دهد و از تبدیل غیرضروری داده‌ها جلوگیری می‌کند. در اینجا نحوه کار آن آمده است:1. ایجاد Shared ViewModel: یک کلاس ViewModel تعریف کنید که شیء داده‌ای شما (مدل TV show) را نگه دارد و متدهایی برای دسترسی و به‌روزرسانی آن ارائه دهد.2. دسترسی به ViewModel در هر دو صفحه: در صفحات لیست TVShows و جزئیات، به یک نمونه از Shared ViewModel دسترسی پیدا کنید.3. انتقال داده: در صفحه لیست TVShows، شیء داده‌ای Shared ViewModel را با اطلاعات TV show انتخاب شده به‌روز کنید.4. مشاهده (Observing) داده‌ها: در صفحه جزئیات TVShows، از composable ViewModel برای دسترسی به همان نمونه ViewModel استفاده کنید. ویژگی selectedTvShow را Observe کنید.مزایا:جداسازی  رابط کاربری و منطق داده(data logic). بهبود مدیریت جریان داده‌ها در برنامه شما. جلوگیری از تبدیل داده‌های تکراری، بهبود عملکرد برای اشیاء پیچیده یا به‌روزرسانی‌های مکرر.معایب:نیاز به تنظیمات اضافی با ViewModelها در مقایسه با روش رشته JSON دارد.کدام روش مناسب است؟از روش رشته JSON برای سناریوهای ساده‌تر که پیچیدگی اشیاء پایین است و سربار تبدیل داده‌ها نگرانی بزرگی نیست، استفاده کنید. این روش ممکن است برای نمونه‌سازی‌ها یا پیاده‌سازی‌های سریع مناسب باشد.برای اشیاء داده‌ای پیچیده یا سناریوهایی با به‌روزرسانی‌های مکرر داده، روش Shared ViewModel را در نظر بگیرید تا جداسازی تمیزتری از وابستگی ها حفظ شود و از تبدیل داده‌های تکراری جلوگیری شود.نتیجه‌گیری :با درک این روش‌ها، می‌توانید به طور مؤثری اشیاء را بین صفحات در برنامه‌های Jetpack Compose خود انتقال دهید و تجربه کاربری کلی و جریان داده‌ها در برنامه خود را بهبود بخشید. روشی را انتخاب کنید که با پیچیدگی و نیازهای عملکردی پروژه شما بهترین تطابق را دارد.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Thu, 11 Jul 2024 12:37:22 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت کتابخانه و فریمورک در برنامه نویسی</title>
                <link>https://virgool.io/codenevis/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%D9%88-%D9%81%D8%B1%DB%8C%D9%85%D9%88%D8%B1%DA%A9-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-knnzbbooniiv</link>
                <description>در دنیای توسعه نرم‌افزار، تفاوت‌ها و نقش‌های ابزارهایی مانند کتابخانه‌ها و فریمورک ها (framework) اغلب موضوع بحث قرار می‌گیرند که در این پست، قصد داریم به بررسی این دو بپردازیم.نکته: یک کتابخانه و یک  فریمورک هر دو ابزارهایی هستند که در توسعه نرم‌افزار استفاده می‌شوند، اما نقش‌ها و ویژگی‌های متفاوتی دارند.کتابخانه(Library):کتابخانه یک مجموعه از کدها یا روال‌های پیش‌نویس شده است که توسط توسعه‌دهندگان برای انجام وظایف متداول استفاده می‌شود. این کدها و روال‌ها توسط برنامه‌نویسان مورد استفاده قرار می‌گیرند تا عملیات خاصی را انجام دهند، به عبارت دیگر، کتابخانه‌ها ابزارهایی هستند که توسعه‌دهندگان می‌توانند از آن‌ها برای انجام کارهای مختلف در برنامه‌ها استفاده کنند و به آن‌ها کمک می‌کنند تا زمان خود را صرفه‌جویی کنند.ویژگی‌های کلیدی یک کتابخانه:قابلیت مدولاریت: کتابخانه‌ها مدولار هستند، به این معنی که می‌توانید بخش‌های خاصی از کتابخانه را بدون اینکه نیاز به استفاده از کل مجموعه توابع داشته باشید، استفاده کنید.کنترل: توسعه‌دهندگان وقتی از یک کتابخانه استفاده می‌کنند، بیشتر کنترل بر جریان برنامه‌شان را حفظ می‌کنند. آن‌ها می‌توانند تصمیم بگیرند که کدام توابع را از کتابخانه استفاده کنند و چگونه از آن‌ها استفاده کنند.متمرکز بر توابع خاص: کتابخانه‌ها به طور عمومی بر ارائه توابع برای وظایف یا قابلیت‌های خاص متمرکز هستند.مثال: کتابخانه‌ی math در زبان‌های برنامه‌نویسی توابعی برای عملیات ریاضی مانند محاسبه‌ی جذر مربعی یا توابع مثلثی ارائه می‌دهد.فریمورک(framework): از سوی دیگر، فریمورک مجموعه‌ای گسترده‌تر از ابزارها، راهنماها و کدهای قابل استفاده مجدد است که یک ساختار برای ساخت یک برنامه کامل فراهم می‌کند. برخلاف کتابخانه‌ها که بیشتر به مجموعه‌ای از توابع شبیه هستند، فریمورک‌ها جریان و ساختار برنامه شما را تعیین می‌کنند. توسعه‌دهندگان از فریمورک برای ساخت برنامه خود استفاده می‌کنند و جزئیات را با نوشتن کدی که در ساختار فریمورک قرار می‌گیرد، تکمیل می‌کنند.به عنوان مثال در برنامه‌نویسی موبایل، فرض کنید می‌خواهید یک اپلیکیشن موبایل بسازید. اگر از یک کتابخانه استفاده کنید، ممکن است توابعی برای مدیریت UI، دسترسی به دیتابیس یا ارتباط با سرور به شما بدهد، اما این شما هستید که باید تصمیم بگیرید چگونه این توابع را کنار هم قرار دهید و ساختار اپلیکیشن خود را بسازید.اما اگر از یک فریمورک مانند React Native یا Flutter استفاده کنید، این فریمورک‌ها یک ساختار کلی برای برنامه شما ارائه می‌دهند و شما باید کد خود را در این ساختار قرار دهید. به عنوان مثال، فریمورک React Native به شما اجازه می‌دهد تا با استفاده از زبان JavaScript و کامپوننت‌های آماده، اپلیکیشن موبایل بسازید. این فریمورک‌ها به شما کمک می‌کنند تا سریع‌تر و با اشتباهات کمتر برنامه‌نویسی کنید، چرا که بسیاری از تصمیمات ساختاری از قبل توسط فریمورک گرفته شده است.ویژگی‌های کلیدی یک فریمورک:وارونگی کنترل (Inversion of Control یا IoC): در یک فریمورک، جریان کنترل معکوس می‌شود. به جای اینکه توسعه‌دهنده توابعی از فریمورک را فراخوانی کند، این فریمورک است که کد توسعه‌دهنده را فراخوانی می‌کند. این به عنوان &quot;اصل هالیوود&quot; معروف است - &quot;ما را صدا نزنید؛ ما شما را صدا می‌کنیم.&quot;جامع بودن: فریمورک‌ها جامع‌تر هستند و برای کل برنامه یک ساختار فراهم می‌کنند. آنها اغلب شامل الگوهای از پیش تعریف شده، بهترین شیوه‌ها و قراردادها هستند.قابلیت توسعه‌پذیری: توسعه‌دهندگان می‌توانند قابلیت‌های فریمورک را با نوشتن کدی که به ساختارهای مشخص فریمورک منطبق باشد، گسترش دهند. به عنوان مثال، در Flutter، توسعه‌دهندگان می‌توانند با نوشتن ویجت‌های سفارشی و استفاده از APIها و قابلیت‌های مختلف، قابلیت‌های این فریمورک را گسترش دهند.نتیجه گیری:به طور خلاصه، در حالی که هر دو کتابخانه‌ها و فریمورک‌ها کدهای پیش‌نویس شده‌ای برای توسعه‌دهندگان فراهم می‌کنند، اصلی‌ترین تفاوت در سطح کنترل و ساختاری است که ارائه می‌دهند. کتابخانه‌ها توابع خاصی را فراهم می‌کنند که توسعه‌دهندگان می‌توانند بر اساس نیازشان استفاده کنند، در حالی که فریمورک‌ها یک ساختار کامل‌تر فراهم می‌کنند و جریان و طراحی کلی یک برنامه را تعیین می‌کنند.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Mon, 08 Jul 2024 02:27:33 +0330</pubDate>
            </item>
                    <item>
                <title>reified در کاتلین چیست؟</title>
                <link>https://virgool.io/codenevis/reified-%D8%AF%D8%B1-%DA%A9%D8%A7%D8%AA%D9%84%DB%8C%D9%86-%DA%86%DB%8C%D8%B3%D8%AA-ov2xkuilqwgm</link>
                <description>در محیط‌های JVM مانند Android، Desktop یا Spring Boot که از Kotlin استفاده می‌کنید، type ها در زمان اجرا پاک می‌شوند که این موضوع قابلیت نوشتن الگوریتم‌های عمومی و خوانا را محدود می‌کند.با این حال، Kotlin این مشکل را با معرفی کلمه کلیدی reified حل کرده است، که type را در زمان اجرا حفظ می‌کند.reified  چگونه کار می‌کند؟استفاده از reified محدودیت‌هایی دارد. تابع شما باید inline باشد. inlining چه کاری انجام می‌دهد؟ به زبان ساده، inlining یعنی تمام کدهای یک تابع به جای اینکه جداگانه اجرا شوند، مستقیماً به محل فراخوانی آن تابع منتقل می‌شوند. این کار به بهبود عملکرد و جلوگیری از برخی مشکلات مربوط به type ها کمک می‌کند. برای توضیح مفهوم inlining در کاتلین، بیایید نگاهی به این مثال بزنیم:وقتی شما تابع printWords را به صورت inline تعریف می‌کنید، به کامپایلر می‌گویید که هر جایی این تابع فراخوانی شد، به جای اجرای جداگانه تابع، کد داخل آن را به محل فراخوانی منتقل کند.بنابراین، کد شما در زمان کامپایل به این شکل تبدیل می‌شود:در اینجا، به جای اینکه تابع printWords دو بار جداگانه اجرا شود، کد داخل آن تابع مستقیماً به محل‌های فراخوانی منتقل شده است. بنابراین، مفهوم inlining به این معنی است که کد تابع به محل فراخوانی منتقل می‌شود تا هم عملکرد بهبود یابد و هم محدودیت‌های مربوط به type ها از بین برود. Reified چیست؟ کلمه کلیدی reified در کاتلین به شما اجازه می‌دهد تا  type های جنریک را در زمان اجرا (runtime) حفظ کنید. در حالت عادی،  type های جنریک در کاتلین و جاوا در زمان کامپایل پاک می‌شوند (به این فرآیند type erasure می‌گویند)، به این معنی که اطلاعات  type ها در زمان اجرا در دسترس نیستند. اما با استفاده از reified می‌توانید این اطلاعات را در زمان اجرا نیز حفظ کنید. برای استفاده از reified، تابع شما باید inline باشد.مزایای استفاده از reified:حفظ type ها در زمان اجرا: می‌توانید به نوع جنریک در زمان اجرا دسترسی داشته باشید.نوشتن کدهای عمومی و قابل استفاده مجدد: می‌توانید توابعی بنویسید که با type های مختلف کار می‌کنند و اطلاعات نوع‌ها در زمان اجرا حفظ می‌شود.بهبود عملکرد: با inlining، سربار فراخوانی توابع کاهش می‌یابد و کد بهینه‌تری اجرا می‌شود.مثال : این کد نشان می‌دهد چگونه reified می‌تواند در کاتلین استفاده شود تا نوع‌های جنریک را در زمان اجرا حفظ کند. بیایید به طور جزئی‌تر به هر بخش از کد نگاهی بیندازیم:کد اصلیدر این بخش، word یک متغیر از نوع String است و در همان محلی که این متغیر تعریف شده است، نوع آن به صورت مستقیم شناخته می‌شود. این بدین معنی است که ما می‌توانیم با استفاده از ::class به نوع این متغیر دسترسی داشته باشیم و simpleName آن را چاپ کنیم که در اینجا &quot;String&quot; خواهد بود.تابع printType بدون reifiedدر این تابع، ما یک تابع جنریک printType داریم که بدون استفاده از reified تعریف شده است. در کاتلین، توابع جنریک به صورت پیش‌فرض در زمان اجرا اطلاعات نوع‌شان را از دست می‌دهند (type erasure). بنابراین، این کد به درستی کامپایل نمی‌شود زیرا T::class نمی‌تواند در زمان اجرا دسترسی به اطلاعات نوع T داشته باشد.تابع printType با reified و inlineدر این تابع، ما از reified و inline استفاده کرده‌ایم. با استفاده از reified T، می‌توانیم نوع T را در زمان اجرا حفظ کنیم. با استفاده از inline، کد تابع به محل فراخوانی منتقل می‌شود که این اجازه را به ما می‌دهد که از T::class در تابع استفاده کنیم و اطلاعات نوع T در زمان اجرا دسترسی پیدا کند.استفاده از تابع printTypeدر اینجا، ما تابع printType را با استفاده از متغیر word از نوع String فراخوانی می‌کنیم. با استفاده از reified، تابع قادر است نوع T را شناسایی کرده و اسم آن را چاپ کند که در اینجا به عنوان خروجی &quot;String&quot; به دست می‌آید.به طور کلی، استفاده از reified و inline در کاتلین به شما اجازه می‌دهد تا از نوع‌های جنریک در زمان اجرا استفاده کنید و از مزایایی مانند حفظ نوع‌ها و بهبود عملکرد کد برخوردار شوید، به شرطی که توابع شما inline باشند و از reified استفاده کنید.در چه مواردی reifiedاستفاده می شود؟توابع جنریک: وقتی که می‌خواهید تابعی را تعریف کنید که بتواند با نوع‌های جنریک مختلف کار کند و نیاز به دسترسی به نوع جنریک در زمان اجرا دارید.مواردی که نیاز به بررسی و یا عملکرد متفاوت بر اساس نوع در زمان اجرا دارند: مثلاً بررسی نوع یک متغیر در زمان اجرا یا انجام عملیات خاص بر اساس نوع.تبدیل داده‌ها به صورت دینامیک در زمان اجرا: برای مثال، تبدیل یک لیست از یک نوع خاص به آرایه‌ای از آن نوع.کار با کتابخانه‌های رفلکشن: برای استفاده از قابلیت‌های رفلکشن بر روی نوع‌های جنریک.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Fri, 05 Jul 2024 01:26:49 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه از نشت حافظه در برنامه نویسی اندروید جلوگیری کنیم؟</title>
                <link>https://virgool.io/codenevis/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%A7%D8%B2-%D9%86%D8%B4%D8%AA-%D8%AD%D8%A7%D9%81%D8%B8%D9%87-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%D8%AC%D9%84%D9%88%DA%AF%DB%8C%D8%B1%DB%8C-%DA%A9%D9%86%DB%8C%D9%85-kybol5ey6ier</link>
                <description>نشت حافظه یا همان (Memory leaks) در برنامه‌های اندروید زمانی رخ می‌دهد که برنامه به اشیائی که دیگر نیازی به آن‌ها نیست، ارجاع می‌دهد و باعث می‌شود جمع‌آوری زباله (garbage collector) نتواند حافظه آن‌ها را بازیابی کند. با گذشت زمان، این نشت‌ها می‌توانند منجر به افزایش استفاده از حافظه و در نتیجه کاهش عملکرد برنامه یا حتی خرابی آن شوند.نکته : در اینجا منظور از &quot;ارجاع&quot; همان &quot;reference&quot; است که به ارتباط یا اشاره به یک شیء در حافظه اشاره دارد. وقتی می‌گوییم &quot;ارجاع به یک شیء&quot; یعنی یک متغیر یا یک مکان در برنامه به آن شیء خاص اشاره می‌کند و می‌تواند از آن استفاده کند. جمع‌آوری زباله یا garbage collector چیست؟جمع‌آوری زباله (Garbage Collector) بخشی از سیستم مدیریت حافظه در محیط‌های برنامه‌نویسی است که به طور خودکار اشیاء و داده‌های غیرقابل استفاده را از حافظه پاک می‌کند. وظیفه اصلی جمع‌آوری زباله این است که حافظه‌ای را که دیگر توسط برنامه استفاده نمی‌شود، شناسایی و آزاد کند تا بتوان از این حافظه برای نیازهای جدید برنامه استفاده کرد.در برنامه‌های اندروید و به طور کلی در زبان‌های برنامه‌نویسی مدرن مانند جاوا، جمع‌آوری زباله به توسعه‌دهندگان کمک می‌کند تا نیازی به مدیریت دستی حافظه نداشته باشند و بدین ترتیب از مشکلات مرتبط با نشت حافظه و خرابی برنامه‌ها جلوگیری شود.1. درک نشت حافظه:نشت حافظه زمانی رخ می‌دهد که اشیاء به درستی از حافظه خارج نشوند و این باعث می‌شود که برنامه به مرور زمان حافظه بیشتری مصرف کند.در اندروید، جمع‌آوری زباله به صورت خودکار حافظه را با شناسایی و جمع‌آوری اشیائی که دیگر استفاده نمی‌شوند، بازیابی می‌کند.2. مدیریت چرخه حیات Activity و Fragment:Activityها و Fragment ها دارای چرخه حیات هستند و مدیریت اشیاء در این چرخه‌ها ضروری است. به عنوان مثال، منابعی مانند اتصالات شبکه یا اتصالات به پایگاه داده باید در متد onDestroy آزاد شوند تا از نگه‌داشتن ارجاعات پس از پایان چرخه حیات کامپوننت جلوگیری شود.3. با Context محتاط باشید:هنگامی که یک context با عمر کوتاه‌تر (مثل context مربوط به activity) کافی است، از استفاده context برنامه اجتناب کنید.در نگه‌داشتن ارجاعات به context، مواظب باشید زیرا ممکن است منجر به نشت حافظه شود.4. اجتناب از ارجاعات استاتیک: از متغیرهای استاتیک یا ارجاعات به context خودداری کنید.ارجاعات استاتیک می‌توانند در کل چرخه حیات برنامه باقی بمانند و باعث نشت حافظه شوند.اگر نیاز به استفاده از ارجاعات استاتیک دارید، به جای Activity context از Application context استفاده کنید.5. استفاده از WeakReferences:وقتی نیاز دارید یک ارجاع را نگه دارید اما نمی‌خواهید از جمع‌آوری زباله جلوگیری کنید، از WeakReference استفاده کنید. WeakReference به جمع‌آورنده زباله اجازه می‌دهند در صورت نیاز حافظه شیء را بازیابی کند.این امر به جلوگیری از نشت حافظه کمک می‌کند و باعث می‌شود که برنامه عملکرد بهتری داشته باشد.6. آزادسازی منابع:منابعی مانند پایگاه‌های داده، فایل‌ها و اتصالات شبکه را به صورت صریح (Explicitly) آزاد کنید.از try-with-resources یا بلوک‌های finally استفاده کنید تا آزادسازی منابع تضمین شود.7. اجتناب از حافظه‌پنهانی بیش از اندازه: درباره cashing اطلاعات بزرگ هوشیار باشید.از راهکارهای cashing  که به طور خودکار اطلاعات قدیمی را حذف یا اندازه cashing را محدود می کند استفاده کنید.اندازه cashing را محدود کرده و از راهکارهایی مانند حذف مبتنی بر زمان یا LRU (کمترین استفاده اخیر (Least Recently Used)) استفاده کنید تا اطمینان حاصل شود که اطلاعات قدیمی حذف می‌شوند.8. مدیریت درست تغییرات پیکربندی:هنگام مدیریت تغییرات پیکربندی، مانند چرخش‌های صفحه، اطمینان حاصل کنید که ارجاعات شیء را به به درستی مدیریت می شود تا از نشت حافظه جلوگیری شود. از ViewModels یا راهکارهای دیگر استفاده کنید تا اطلاعات را در طول تغییرات پیکربندی نگه دارید بدون اینکه نشت حافظه ایجاد شود.نکته : تغییرات پیکربندی یا (Handle Config Changes) به تغییراتی اشاره دارد که در ویژگی‌های یک برنامه رخ می‌دهد که می‌تواند بر اساس شرایط مختلف محیطی تغییر کند. به عنوان مثال، زمانی که یک کاربر صفحه نمایش دستگاه خود را چرخانده و از حالت عمودی به افقی یا برعکس تغییر می‌دهد، تغییرات پیکربندی رخ می‌دهد.در برنامه‌نویسی اندروید، وقتی یک تغییر پیکربندی اتفاق می‌افتد، ممکن است Activity یا Fragment کنونی مجدداً ایجاد شود و مراحل مختلف زندگی آن‌ها مجدداً طی شود. این تغییرات می‌توانند به چالش کشیدن مدیریت اطلاعات مربوط به وضعیت فعلی برنامه منجر شوند، به ویژه اگر ارتباطی با عملکرد فعلی کاربر داشته باشند.بنابراین، هنگامی که می‌گوییم &quot;مدیریت  تغییرات پیکربندی&quot;، منظورمان این است که باید به طور صحیح و از روش‌های مختلف، از جمله استفاده از ViewModels، اطلاعات مربوط به وضعیت و ارتباطات برنامه را در طول تغییرات پیکربندی حفظ کنیم تا از مشکلاتی مانند نشت حافظه جلوگیری شود.9. به‌روزرسانی Dependencies:وابستگی‌های برنامه‌ی خود، از جمله کتابخانه‌های شخص ثالث، را به‌روز نگه دارید.10. استفاده از کتابخانه‌های تشخیص نشت حافظه:ابزارهایی مانند LeakCanary می‌توانند به طور خودکار نشت حافظه‌ها را در طول توسعه تشخیص دهند و گزارش دهند.این ابزارها را در فرآیند توسعه‌ی خود استفاده کنید تا بتوانید نشت حافظه‌ها را به سرعت شناسایی کنید.11. با سینگلتون‌ها محتاط باشید:سینگلتون‌ها ممکن است به طور نامحدود ارجاعات را نگه دارند که منجر به نشت حافظه شود. در نظر داشته باشید از فریمورک های تزریق وابستگی مانند Dagger استفاده کنید تا مدیریت چرخه حیات اشیاء را انجام داده تا  نمونه‌های سینگلتون با عمر طولانی خودداری شود.12. اجتناب از ایجاد اشیاء غیرضروری:از ایجاد اشیاء موقت، به‌ویژه داخل حلقه‌ها، کاهش دهید، زیرا ممکن است منجر به تخصیص بیش از حد حافظه شود.13. استفاده هوشمندانه از Application Class:هنگامی که اشیاء با عمر طولانی را در Application Class  ذخیره می‌کنید، مواظب باشید.اشیاء موجود در اینجا ممکن است در طول چرخه حیات کامل برنامه باقی بمانند.در این پست، به راهکارهای متعددی که می‌توانند به جلوگیری از نشت حافظه کمک کنند، پرداختیم.ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Wed, 05 Jun 2024 14:59:13 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه یک پیغام کامیت خوب بنویسیم؟</title>
                <link>https://virgool.io/codenevis/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D9%BE%DB%8C%D8%BA%D8%A7%D9%85-%DA%A9%D8%A7%D9%85%DB%8C%D8%AA-%D8%B1%D8%A7-%D8%AE%D9%88%D8%A8-%D8%A8%D9%86%D9%88%DB%8C%D8%B3%DB%8C%D9%85-erqvujwahbfl</link>
                <description>نوشتن یک پیغام کامیت  خوب برای گیت‌هاب (GitHub) می‌تواند به شما و همکارانتان کمک کند که به راحتی تغییرات کد را دنبال کنید و درک بهتری از تاریخچه پروژه داشته باشید. در این پست نکاتی برای نوشتن یک پیغام کامیت خوب آورده شده است:فرمت نهایی پیغام کامیت:نکات مهم:1.  متن پیغام خود را بهتر است در حالت امری بنویسید، به عنوان مثال :fix: fix bug2. کوتاه و خلاصه بنویسید. سعی کنید پیغام کامیت خود را در 50 کاراکتر خلاصه کنید تا در صفحه گیت هاب به درستی خوانده و دیده شود. همچنین از کلمات و نماد های غیرضروری خودداری کنید.3. اول پیغام خود را با حرف بزرگ شروع کنید.بررسی کامل فرمت پیغام کامیت:مورد اول &lt;Type&gt; : برای نشان دادن نوع تغییرات موجود باید نوع تغییر را با یکی از انواع زیر مشخص کنید:کلمه کلیدی feat : برای خلاصه کردن یک ویژگی جدید در کدمان.کلمه کلیدی fix : زمانی که دیباگی  را در کد انجام دادید با این پیغام کد خود را کامیت کنید.کلمه های کلیدی دیگری را مثل refactor ، style ، ci و build را هم می توانید استفاده کنید.مورد دوم  (scope): این مورد را به ادامه type  اضافه می کنیم تا اطلاعات مختصری درباره نوع تغییر داشته باشیم.مورد سوم (body): این مورد برای اضافه کردن توضیحات بیشتر پیغام کامیت است.  شکل نوشتاری آن به این صورت است که بعد از پیغام اصلی یعنی (&lt;Type&gt; ([optional scope]): &lt;description&gt;) یک خط فاصله می اندازیم بعد شروع به نوشتن می کنیم . توجه: توضیحات بهتر است 72 کاراکتر باشد.مورد چهارم (footer): پاورقی برای اطلاعات اضافی مانند بررسی شده  یا نوشته شده توسط فرد مربوطه است.به عنوان مثال:  Signed-by : Sadegh&lt;Sadegh@gmail.com&gt;و footer هم بعد از body یک خط فاصله می دهیم.نکته : در پروژه های شخصی خود می توانید فقط از بخش اصلی  (&lt;Type&gt; ([optional scope]): &lt;description&gt;) استفاده کنید و معمولا در پروژه های شخصی دو بخش بعدی دلبخواهی است.مثال واقعی با استفاده از فرمت گفته شده:ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!کانال تلگرام: mister_developerrاینستاگرام: mister_developerrموفق و پیروز باشید</description>
                <category>محمد صادق مهرافزون</category>
                <author>محمد صادق مهرافزون</author>
                <pubDate>Sat, 01 Jun 2024 14:35:45 +0330</pubDate>
            </item>
            </channel>
</rss>