<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های علیرضا نظری</title>
        <link>https://virgool.io/feed/@alirezanazari</link>
        <description>Android Team Lead at blu Bank</description>
        <language>fa</language>
        <pubDate>2026-06-10 13:07:06</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/34113/avatar/lIVhlb.png?height=120&amp;width=120</url>
            <title>علیرضا نظری</title>
            <link>https://virgool.io/@alirezanazari</link>
        </image>

                    <item>
                <title>در نسخه اندروید بلوبانک چگونه دیپ‌لینک ها را پیاده سازی کردیم؟ (Conditional DeepLink)</title>
                <link>https://virgool.io/@alirezanazari/conditional-deep-link-iiz6x9oflvn8</link>
                <description>زمین بازی را عوض کردیم؟؟ =))قبل از اینکه دیپ‌لینک رو بررسی کنیم باهم یه دور ساختار لینک و URL رو بررسی کنیم با این تفاوت که خیلی ساده بگم به protocol ما scheme و به domain ما host هم میگیم:ساختار لینک یا URLاما در اندروید راه های مختلفی برای پیاده سازی دیپ‌لینک هست, ساده ترین نوع اون تعریف intent-filter در manifest پروژه تا حالت سینه به سینه و طی کردن فلو برای رفتن به یک صفحه مشخص وجود داره:&lt;intent-filter android:label=&amp;quotBluBank&amp;quot android:autoVerify=&amp;quottrue&amp;quot&gt;
    &lt;action android:name=&amp;quotandroid.intent.action.VIEW&amp;quot /&gt;
    &lt;category android:name=&amp;quotandroid.intent.category.DEFAULT&amp;quot /&gt;
    &lt;category android:name=&amp;quotandroid.intent.category.BROWSABLE&amp;quot /&gt;
    &lt;data android:scheme=&amp;quothttps&amp;quot android:host=&amp;quotapplication.blubank.com&amp;quot /&gt;
    ...
&lt;/intent-filter&gt;اما با اومدن نویگیشن کامپوننت کار ما برای ایجاد دیپ‌لینک بسیار راحت شده و اگر پروژه تون لاگین یا ثبت‌نام نداشته باشه به راحتی با چند خط کد می‌تونید انواع دیپ‌لینک رو پیاده سازی و لذت ببرید :دی&lt;fragment&gt;
    &lt;deepLink
        android:id=&amp;quot@+id/deepLink&amp;quot
        app:uri=&amp;quotblubank://application/goto?page=card/update&amp;quot /&gt;
&lt;/fragment&gt;اگر هم نیاز به دریافت ورودی تو صفحه مقصد دارید به راحتی با تعریف argument می‌تونید داینامیک یکسری دیتا رو بگیرید و در uri دیپ‌لینک مشخص کنید کدوم query یا path اون آرگیومنت رو پر میکنه:&lt;fragment&gt;
    &lt;argument
        android:name=&amp;quotnumber&amp;quot
        app:argType=&amp;quotstring&amp;quot /&gt;
    &lt;deepLink
        android:id=&amp;quot@+id/chargeDeepLink&amp;quot
        app:uri=&amp;quotblubank://application/goto?page=pay/charge&amp;phone={number}&amp;quot /&gt;
&lt;/fragment&gt;همین چند خط برای خیلی از پروژه ها کافیه و به همین سادگی و به همین خوشمزگی می‌تونید بین هزارن (:دی) صفحه از پروژه‌تون با دیپ‌لینک جابجا بشید.اما اگر پروژه بانکی کار کنید که امنیت حرف اول رو میزنه و همینطور پروژه تون نیاز دارید اول کاربر ثبت نام و لاگین کنه اونوقت دیگه به همین سادگی نیست.تو پروژه آیگپ که نویگیشن کامپوننت وجود نداشت ما بصورت سینه به سینه انتقال میدادیم و اگر تو یه فلویی شرایطی برقرار نبود اجازه ادامه نمی‌دادیم. (سورس کدش موجوده اگر حوصله خوندن و دیدن کد کثیف داشتید حتما تو گیتهاب سرچ کنید ببینید :دی)تو پروژه X که اکتیویتی بیس بود ما به صفحه مقصد میزدیم و اگر به ۴۰۱ میخوردیم صفحه لاگین رو بالا میاوردیم و بعد برگشت و ادامه فعالیت.اما تو بلوبانک ما نه خواستیم سینه به سینه جلو بریم و فلو رو طی کنیم و نه ریکویست الکی بزنیم و ۴۰۱ بخوریم و الکی بار اضافه کنیم.نویگیشن کامپوننت اینجا به هیچ عنوان جواب نمیده و اصلا فکری براش نکردن و پس برنامه‌نویسان غیور ایرانی دست به شگفتی زدند و این سد را با یک چشم (یک و نیم ماه پس از عمل چشم) و در نیم اسپرینت شکستند و حماسه ای خلق کردند. (بچه بیا پایین سرمون درد گرفت :)) )در همین بین  که به نویگیشن کامپوننت فحش میدادم, یک مقاله ای از دوستان بانک آلمانی خوندیم که اساتید نتونسته بودن هندل کنند و لاگین رو جدا و اکتیویتی کرده بودند و از سینگل اکتیویتی خارج شدند. دیپ‌لینک ها رو به اکتیویتی لاگین میگرفتن و به بعد اجازه هندل میدادن. (ایران 1 - آلمان 0)خلاصه که حماسه ای خلق کردیم و الان هر دیپ‌لینکی رو آخ نگفتیم و با یکسری تریک به هدف مون رسیدیم. کد ها شاید در نگاه اول ایده‌آل بنظر نیان اما جوری توسعه داده شده تا زمانی که نویگیشن کامپوننت ساپورت کنه (که بعید میدونم) ما با کمترین تغییرات به کارمون ادامه بدیم و ریفکتور کنیم.چند مورد که برای پیاده سازی Conditional Deep Link بایستی رعایت کنیم:نویگیشن کامپوننت ابزاری برای مدیریت دستی دیپ‌لینک ها نداره و اگر دیپ‌لینکی تعریف کنید توش بدون اجازه و بدون اعتنا به اینکه کدش رو تو manifest ردید یا نه اجرا و به مقصد می‌بره.خب برای این مورد ما دیپ لینک های برنامه رو که در منی‌فست تعریف کردیم رو در گراف با همون scheme تعریف نمی‌کنیم.مثلا اگر با لینک http://google.com بیاد رو به یک scheme من در آوردی تبدیل میکنیم تا نویگیشن کامپوننت آنها رو خودکار هندل نکنه و خودمون این وسط بایستیم و Conditional Deep Link رو داشته باشیم:http://google.com  =&gt;  deeplink://google.com
blubank://application/goto?page=card/update =&gt; customized://application/goto?page=...در این حالت ما در onCreate یا onNewIntent اکتیویتی مون دیپ لینک ها رو میگیریم و شرایط رو بررسی و اجازه جابجایی می‌دیم.مثلا ما یک کلاس Navigator داریم و دیپ‌لینک های ورودی رو به اون میدیم, کلاس شرایط لاگین بودن یا نبودن, فرگمنت لاگین در back stack هست یا نه, دیپ لینک نیاز به لاگین دارد یا نه و.. رو بررسی و تصمیم به ادامه دادن میگیره یا پیغام مناسب رو نشون میده.با این روش نه سینگل اکتیویتی رو نقض کردیم نه ریکویست اضافه زدیم و نه سینه  به سینه رفتیم. فقط تو نقطه شروع یک بررسی کردیم و بعد اجازه رفتن مستقیم به صفحه مورد نظر و یا اول لاگین و بعد رفتن به صفحه  مورد نظر رو دادیم و به هدفمون رسیدیم.پس حالت دیپ لینک در گراف مربوطه این شکلی شد:&lt;deepLink
    android:id=&amp;quot@+id/deepLink&amp;quot
    app:uri=&amp;quotcustomized://application/goto?page=card/updatw&amp;quot /&gt;این رو هم عنوان کنم که با ادرسی که تو گراف تعریف کردید کسی از بیرون نمی‌تونه وارد شه بحاطر اینکه تو منیفست ست نشده و با اصلی میان داخل و طبق کد و تصمیم شما ادامه میدن.حالا فقط چالش ها همینه و مورد اضافه‌ای نیست؟ چرا هست با این روش شما میتونید هر کاری بکنید. اول اینکه ساختار دیپ‌لینک ها رو نقض نکنید و  با کلاس Navigatorتون میتونید این وسط خیلی دیپ لینک ها رو نرمالایز normalize کنید.مثلا قبل از پیاده سازی دیپ لینک ما دو صفحه رو یکی در نظر گرفته بودیم و با یه boolean استیت صفحه رو مشخص میکردیم اما دیپ لینک دو مدل بود و جدا در نظر گرفته بود.من یا باید میومدم ریفکتور میکردم چند تا صفحه رو یا حماسه جدید خلق میکردم. که یا علی گفتم و حماسه ای به پا کردم دوووبارره, یاعلی بگو خدا هوامونو داااره (بچههه بیا پایین باز سرمون درد گرفت)فرگمنت من این شکلی بود:&lt;fragment&gt;
    &lt;argument
        android:name=&amp;quotisCharge&amp;quot
        app:argType=&amp;quotboolean&amp;quot /&gt;
&lt;/fragment&gt;که برای دیپ‌لینک این صفحه یک query param به ته لینک اضافه کردم تا بتونم دو حالتی رو چک کنم و اسمش رو مثلا additional-data گذاشتم تا تو کل دیپ‌لینک ها یک دست باشه:&lt;fragment&gt;
     &lt;argument
         android:name=&amp;quotisCharge&amp;quot
         app:argType=&amp;quotboolean&amp;quot /&gt;
    &lt;deepLink
         android:id=&amp;quot@+id/chargeDeepLink&amp;quot
         app:uri=&amp;quotxx://app/goto?page=pay/charge-list&amp;add-data={isCharge}&amp;quot /&gt;
     &lt;deepLink
         android:id=&amp;quot@+id/internetDeepLink&amp;quot
         app:uri=&amp;quotxx://app/goto?page=pay/internet-list&amp;add-data={isCharge}&amp;quot /&gt;
 &lt;/fragment&gt;و تو کلاس نویگیتور نوشتم:fun Uri.normalizeExternalDeepLinks(): Uri {
    val newDeepLink = this.buildUpon()
    when (val page = this.getQueryParameter(&amp;quotpage&amp;quot)) {
        CHARGE_DEEP_LINK,
        INTERNET_DEEP_LINK -&gt; {
            val isCharge = newDeepLink.toString().contains(CHARGE_DEEP_LINK)
            newDeepLink.appendQueryParameter(&amp;quotadd-data&amp;quot, isCharge.toString())
        }
    }
    return newDeepLink.build()
}این هم یک چالشی بود که حل شد و یسری چالش های دیگر مثل گرفتن دیپ لینک در صفحه مقصد که نویگیشن کامپوننت ابزاری برای این نداره که تو صفحه مقصد بفهمید چه دیپ‌لینکی اومده و نفهم کامله و برای اون تا این لحظه آبان ۱۴۰۰ چیزی اضافه نکرده و ترجیح میدم خودتون بهش بر بخورید و نسبت به توضیحات بالا تریکی بزنید و اگر نشد better call Saul چیزه کال علیرضا :دییسری چالش دیگه هم بود که خدایی دستم درد کرد اینقدر نوشتم و اگر شد در آینده ورژن دو این مقاله رو می‌نویسم.امیدوارم تونسته باشم منظور رو رسونده باشم و براتون مفید باشه و شوخی های تو متن هم  صرفا جهت قابل تحمل کردن مقاله بوده. علیرضا نظری</description>
                <category>علیرضا نظری</category>
                <author>علیرضا نظری</author>
                <pubDate>Fri, 05 Nov 2021 13:49:30 +0330</pubDate>
            </item>
                    <item>
                <title>خداحافظ فایربیس : ردیابی کرش ها و مانیتورینگ برنامه با سرویس قدرتمند Yandex - AppMetrica</title>
                <link>https://virgool.io/MobileLab/yandex-appmetrica-firebase-alternative-rdkgftisi5d0</link>
                <description>Yandex - AppMetricaدر این مقاله میخواهیم در مورد جایگزین قدرتمند فایربیس (Firebase) صحبت کنیم که برای مانیتورینگ , گزارش گیری و مهم تر از همه ردیابی کرش های احتمالی در برنامه های اندروید و iOS هست که بعد از انتشار در مارکت های آنلاین کمک های زیادی به ما خواهند کرد.همینطور شاید در جریان تحریم های هوآوی توسط گوگل و دولت آمریکا باشید که باعث شده گوشی های جدید این شرکت و برنامه های ما با مشکلات جدیدی روبرو شه و نتونه کد ها و Dependency های GSM یا همون گوگل پلی سرویسز رو اجرا کنه و کلی دیالوگ های آزار دهنده نشون بده که میگه : “application won’t run without google play services which are not supported by your device”خب ما با استفاده از سرویس قدرتمند Yandex که AppMetrica نام داره میتونیم تمام کدهای GSM رو به این پلتفرم تغییر بدیم و از شر این ارور های آزار دهنده رها بشیم و همینطور از استفاده از این سرویس که هم پیاده سازیش راحته و هم فیلتر نیست و پر امکانات تر هست , لذت ببریم .اپ متریکا یک سرویس قدرتمندی که به ما در مانیتورینگ , گزارش گیری , ارسال ایونت های مختلف , ذخیره اطلاعات کاربران , پوش نوتیفیکیشن و از همه مهم تر ردیابی کرش های رخ داده در برنامه مون کمک میکنه که به جد میتونم بگم خطاها رو دقیق تر و بهتر از فایربیس لیست میکنه .ثبت نامبا استفاده از این لینک میتونید به راحتی یک حساب کاربری در Yandex بسازید و از تمام سرویس های اون به طور کاملا رایگان استفاده کنید.تنظیمات اولیه فایل گریدل برنامه رو باز کنید و کد های زیر رو به اون اضافه کنید :apply plugin: ‘appmetrica-plugin’

android {
    appmetrica { 
       postApiKey = “YOUR_POST_API_KEY” 
       mappingBuildTypes = [‘release’]
    }
}

dependencies {
    implementation ‘com.yandex.android:mobmetricalib:3.15.0’
}بعد از اضافه کردن کد های بالا , فایل گریدل پروژه رو باز کنید و خط زیر رو به اون اضافه کنید:classpath ‘com.yandex.android:appmetrica-build-plugin:0.1.3’پروژه رو Sync کنید و الان آماده استفاده از AppMetrica تو برنامه مون هستیم.تنظیمات اولیه AppMetricaخب بریم برای ستاپ کردن اپ متریکا و با توجه به نیاز هامون میتونیم مشخص کنیم از کدوم فیچر ها استفاده کنیم و کدوم غیرفعال باشند :val config = YandexMetricaConfig.newConfigBuilder(API_KEY)
        .withNativeCrashReporting(false)
        .withLocationTracking(false)
        .withAppVersion(BuildConfig.VERSION_NAME)
        .build() 

YandexMetrica.activate(this, config)
YandexMetrica.enableActivityAutoTracking(this)اول از همه نیازه که یک Api Key بسازید که با استفاده از این لینک میتونید پروژه تون رو اضافه کنید و Api Key و Post Api Key رو از داشبورد بردارید.اگر پروژه شما شامل کدهای نیتیو (C++) هست و میخواهید که کرش های نیتیو هم شناسایی کنید فقط کافیه مقدار withNativeCrashReporting رو true کنید و همینطور میخواهید موقعیت مکانی کاربران تون رو داشته باشید هم مقدار withLocationTracking رو تغییر بدید .همینطور با مشخص کردن ورژن برنامه تون میتونید خطا ها و کل اطلاعات رو دسته بندی کنید و در داشبورد اپ متریکا ببینید.ذخیره اطلاعات کاربرانپنل لسیت کاربرانشما میتونید اطلاعات کاربران برنامه تون رو با استفاده از AppMetrica ذخیره کنید و اونها رو با فیلتر های مختلقی  مثل کشور , شهر , نوع دستگاه و.. روی داشبورد مشاهده کنید.val userProfile = UserProfile.newBuilder()
        .apply(Attribute.name().withValue(name))
        .apply(Attribute.customString(“Email”).withValue(email))
        .build()

YandexMetrica.setUserProfileID(id)
YandexMetrica.reportUserProfile&#40;userProfile&#41;اپ متریکا مقادیری مثل نام , جنسیت و تاریخ تولد رو از قبل ساخته و با استفاده از اونها میتونید اطلاعات کاربران رو ذخیره کنید . همنیطور امکان ذخیره اطلاعات اضافی مثل ایمیل , عکس و.. رو بهتون میده که با استفاده از Attribute.customString/Boolean/Number شما میتونید هر نوع اطلاعاتی رو ذخیره کنید.ارسال ایونت ایونت ها در داشبورداپ مریکا این امکان رو به شما میده که ایونت های مختلفی رو ارسال و ذخیره کنید . برای مثال با باز شدن هر صفحه از برنامه یک ایونت بفرستیم که معادل setCurrentScreent در فایربیس میتونه باشه و همینطور میتونید عملکرد های مختلف مثل کلیک رو با ارسال ایونت و ذخیره آنها شناسایی کنید.YandexMetrica.reportEvent(string)ذخیره درآمدپنل درآمد در داشبوردبا استفاده از اپ متریکا شما میتونید درآمد های حاصل از اپلیکیشن تون رو ذخیره و گزارش گیری کنید و بعنوان یک حسابدار از این سرویس استفاده کنید . شما میتونید هر محصول رو با اسم و آیدی مشخص و تعداد و.. در Yandex ذخیره کنید تا اطلاعات کاملی از فروش و سود برنامه تون داشته باشید.val revenue = Revenue.newBuilderWithMicros(1000, Currency.getInstance(“IRR”))
        .withProductID(“PD-123”)
        .withQuantity(1)
        .build()

YandexMetrica.reportRevenue(revenue)گزارش دستی خطا لیست کرش های برنامه اپ متریکا در کنار ثبت خودکار خطا ها , به شما این امکان رو میده که دستی خطاهایی رو به سمت پنل بفرستید و در داشبورد بررسی شون کنید :try {
     …
} catch (ex: Exception) {
    YandexMetrica.reportUnhandledException(ex)
}نتیجه اپ متریکا سرویس Yandex یک پلتفرم کاملا رایگان و قدرتمند که به شما برای گزارش گیری و مانیتورینگ برنامه تون کمک های زیادی میکنه و به جرات میتونم بگم تجربه استفاده بهتری نسبت به فایربیس با این سرویس داشتم که از لحاظ گزارش خطاها واقعا بهتر و دقیق تر هست و همینطور فیلتر نیست و با خیال راحت میتونیم از این سرویس استفاده کنیم.منبع : https://appmetrica.yandex.com/docs/quick-start/concepts/quick-start.htmlسورس کد نمونه : https://gist.github.com/alirezanazari/cecec7f8d4231d04ad9a121137e98b16</description>
                <category>علیرضا نظری</category>
                <author>علیرضا نظری</author>
                <pubDate>Sun, 25 Oct 2020 15:39:32 +0330</pubDate>
            </item>
                    <item>
                <title>پیاده سازی Theme در برنامه های اندرویدی</title>
                <link>https://virgool.io/AndroidPPub/theme-in-android-ifwzs7yym4xd</link>
                <description>سلام !! تو این مقاله میخوام باهم تم یا چند رنگی رو در برنامه های اندرویدی رو بررسی کنیم و اینکه Theme شب و روز (Light , Dark) رو پیاده سازی کنیم ، که با انجام اینکار پیاده سازی رنگ بندی های دیگ تفاوتی نداره و به سادگی قابل پیاده سازیه .البته من فقط بیس رو میگم و خروجی این نیست :)))خب ما در برنامه آیگپ از چندین تم و رنگ های مختلفی رو پشتیبانی میکنیم و دست کاربر در انتخاب رنگ و ظاهر برنامه بازه ، خیلی ها مثل من پرسپولیسی اند و تم قرمز رو انتخاب میکنن و خیلیا با حالت شب (Dark Theme) احساس بهتری حین استفاده از برنامه دارند و هر کسی طبق سلیقه خودش میتونه رنگ و تم مورد علاقه ش رو انتخاب کنه .برای پیاده سازی این مبحث اگر پروژه ای دارید که شروع نکردید کار سختی جز یسری کانفیگ ها ندارید و اگر هم پروژه طراحی شده و بزرگی دارید سخت ترین کارش تغییر لایه هاست و رنگ های ثابت رو به Attribute ها تغییر بدین که نسبت به تعداد لایه ها کار زمان بری میتونه باشه.از طرف دیگ پشتیانی Theme در اندروید زیر ۵ (Api 21) هم درد سر های خاص خودش رو داره که اگر حواستون نباشه باگ های زیادی رو متاسفانه برای طیف وسیعی از این کاربران :( بوجود میاره ...خب بعد از توضیح یکسری موارد بریم برای پیاده سازی Theme در برنامه هامون:برای اینکار بهتره ساختار برنامه تون از Single Activity پشتیبانی کنه ولی باز هم با همون ساختار اکتیویتی هم میتونید پیاده سازی کنید که نیاز به یسری کد های اضافه و مدیریت اون در  هر اکتیویتی داره.برای نگهداری وضعیت تم انتخابی کاربر میتونیم از Shared Preferences استفاده کنیم و وضعیت رو در اون ذخیره و بازیابی کنیم . https://gist.github.com/alirezanazari/5ee9a04153b2214a301c494c90c1efce همونطور که در کد بالا میبینید با استفاده از enum تم Dark و Light رو تعریف و در Shared Preferences با استفاده از متد ها ذخیره و بازیابی میکنم . در اولین متد یعنی getTheme یسری استایل با بررسی وضعیت تم انتخابی برگشت داده میشه که این Style رو در MainActivity و متد OnCreate و قبل از صدا زدن Super اون مقدار دهی میکنیم.  https://gist.github.com/alirezanazari/f37606361ec1b634f20ab72bb08bcd71 خب حالا این استایل ها چی اند ؟ ما تو اکثر پروژه ها یسری رنگ های ثابت داریم ; رنگ عنوان ها ، متون معمولی ، رنگ پس زمینه ، رنگ تولبار ، ساب تایتل ها ، دکمه ها و... که ما این رنگ ها رو بصورت Attribute تعریف و در لایه هامون به جای رنگ های ثابت استفاده میکنیم .برای اینکار فایل attrs.xml رو میسازیم و attribute ها و موارد ثابتی که بالا شمردیم رو تعریف میکنیم ، که فرمت هر attr میتونه color باشه که در TextColor , HintColor , Background و هرجایی که رنگ ثابت میدادیم و reference برای جاهایی که drawable , shape میگیرن مقدار دهی کنیم . https://gist.github.com/alirezanazari/9a6bf225b6bffac390cf44d9d504894c خب بعد از  این کار در فایل styles.xml با تعریف رنگ های Accent و Primary و همینطور فونت و.. یک فایل در پوشه res بنام themes.xml می سازیم که از BaseTheme تعریف شده ارث میبرن و رنگ هامون در هر تم رو مشخص میکنند. https://gist.github.com/alirezanazari/8e52d02aaac5d576199078d90f433a02 همونطور که تو کد های بالا میبینید تمام رنگ ها و Attribute های که در پروژه و نسبت به UI نیاز بود رو پیاده سازی کردیم .در کد بالا علاوه بر یسری رنگ ها Drawable هایی هم دیده میشه که ما میتونیم در لایه ها استفاده کنیم .خب میرسیم به استفاده از این مقادیر در لایه های برنامه مون که برای این کار به راحتی بجای رنگ و مقادیر ثابت با علامت ? و نام اون Attribute لایه مون رو رنگ بندی میکنیم.&lt;ImageView
    android:id=&amp;quot@+id/icSeen&amp;quot
    android:layout_width=&amp;quot@dimen/icons_size&amp;quot
    android:layout_height=&amp;quot@dimen/icons_size&amp;quot
    android:tint=&amp;quot?appTextTitleColor&amp;quot
    app:srcCompat=&amp;quot@drawable/ic_eye&amp;quot /&gt;

&lt;TextView
    android:layout_width=&amp;quotwrap_content&amp;quot
    android:layout_height=&amp;quotwrap_content&amp;quot
    android:textColor=&amp;quot?appTextTitleColor&amp;quot
    android:textSize=&amp;quot@dimen/medium_textSize&amp;quot
    tools:text=&amp;quotقسمت ۰۱&amp;quot /&gt;برای همه بخش ها به این صورت عمل میکنیم و رنگ ها رو با استفاده از attribute ها مقدار دهی میکنیم .همینطور Theme پیش فرض رو در بخش application در فایل manifests تغییر میدیم :android:theme=&quot;@style/LightTheme&quot;برای دیدن وضعیت رنگ ها در لایه مون نیازی نیست هر بار ران کنیم و در لایه XML و بخش Preview و قسمت بالا میتونیم بین Theme ها سوییچ کنیم .تمام کانفیگ ها انجام شد و حالا فقط سوییچ کردن بین تم ها مونده که بعضی برنامه ها برای انجام اینکار کارهای عجیبی مثل باز و بستن برنامه یا pop کردن تمام فرگمنت های اکتیویتی و شروع از نقطه اولیه و.. که هیچکدوم از این ها پیشنهاد نمیشه و تغییر تم باید بصورت smooth باشه و کاربر همون نقطه ای که سوییچ کرده از همون صفحه بتونه به کارش ادامه بده و مجبور به تکرار نباشه . برای تغییر تم همونطور که گفتم باید از پترن Single Activity استفاده کنیم و تمام فرگمنت های زیری رو  Attach/deAttach کنیم و اینکار هم نیاز نیست لیست تمام فرگمنت ها رو داشته باشیم و با attach/deattch کردن فرگمنت روت مون یا آیدی container مون بقیه صفحات آپدیت میشن .private fun updateViewForNewTheme(isDark: Boolean) {
    theme.setTheme(if (isDark) Theme.ThemeType.DARK else Theme.ThemeType.LIGHT)
    val fragment = activity?.supportFragmentManager?.findFragmentById(R.id.fragment_container)
    fragment?.let {
        activity?.supportFragmentManager?.beginTransaction()?.let {
            it.detach(fragment)
            it.attach(fragment)
            it.commit()
        }
    }
}برای اینکار بهتره یک فرگمنت روت داشته باشیم به عنوان  Main Fragment و بقیه صفحات رو تو اون اد کنیم و در خط اول onCreateView و قبل از super تم رو اپلای کنیم .context?.theme?.applyStyle(theme.getTheme(), true)خب بعد از ذخیره تم در Shared Preferences و تغییر اون یسری نکات ضروریه که گفته بشه:برای پشتیبانی Theme در دیوایس های زیر اندروید ۵ بایستی یک فایل values-21/themes.xml داشته  باشید که فایل تم که بالا ساختیم رو به این فایل انتقال بدیم و برای زیر ۵ از فایل values/themes.xml استفاده میکنیم که تنها تفاوتش در shape و drawable هایی که بصورت زیر تعریف شده :&lt;shape
    android:shape=&amp;quotrectangle&amp;quot
    xmlns:android=&amp;quothttp://schemas.android.com/apk/res/android&amp;quot&gt;

    &lt;solid
        android:color=&amp;quot?cardBackgroundColor&amp;quot/&gt;

    &lt;corners
        android:radius=&amp;quot@dimen/dp10&amp;quot/&gt;

&lt;/shape&gt;ست کردن رنگ ها در drawable ها و SVG ها باعث کرش در اندروید های زیر ۵ میشه و برای اینکار از دو فایل بالا استفاده میکنیم و در زیر ۵ از رنگ های ثابت برای هر تم استفاده میکنیم .مورد دوم که باید توجه کرد اینه که در inflate کردن لایه ها مخصوصا در فرگمنت و اداپتر ها برای پیروی لایه از Theme جاری برنامه از Context اکتیویتی بجای Application استفاده کنید چون تم در Main Acitivy ست شده و باید از کانتکست اون استفاده بشه :override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.row_profile_avatar , parent , false))
}و مورد سوم که شاید شما لایه ها و ویو هاتون رو بصورت کد جاوا یا کاتلین و بدون xml بنویسید که برای گرفتن تم و ست کردن رنگ ها از کد زیر میتونیم استفاده کنیم :private fun getColorFromAttr(context:Context , attrResId: Int): Int {
    val typedValue = TypedValue()
    val a = context.obtainStyledAttributes(typedValue.data, intArrayOf(attrResId))
    val color = a.getColor(0, 0)
    a.recycle()
    return color
}که حتما Context اکتیویتی و اون attribute که مدنظرتون رو بدید و رنگ دریافتی رو ست کنید.lastEnableTabTitle?.setTextColor(theme.getColorFromAttr(context ,R.attr.appTabDisableColor))خب این هم از پیاده سازی Theme در برنامه های اندرویدی که امیدوارم مفید بوده باشه براتون .وب سایت من </description>
                <category>علیرضا نظری</category>
                <author>علیرضا نظری</author>
                <pubDate>Fri, 24 Apr 2020 15:02:34 +0430</pubDate>
            </item>
                    <item>
                <title>لود تصاویر در کاتلین با کتابخانه Coil</title>
                <link>https://virgool.io/MobileLab/coil-mtkyqsnyzy7h</link>
                <description>کتابخانه Coil اولین لایبرری لود تصاویر در کاتلین است که سریع , سبک و مدرن هست که با استفاده از Coroutine , Okhttp , Okio به لود تصاویر کمک میکنه . Coil مخفف کلمه Coroutine Image Loader هست .کتابخانه Coilهمونطور که میدونید لایبرری های زیادی برای لود عکس در اندروید وجود داره مثل گلاید , پیکاسو و Fressco اما Coil یسری برتری هایی نسبت به بقیه داره که جلوتر بررسی میکنیم:با کاتلین نوشته شده کاتلین ویژگی های زیادی نسبت به جاوا داره که کمک های زیادی به ما میکنه مثل Extension Function , Lambda و.. که تو این کتابخونه به خوبی ازشون استفاده شده و شما عکس هاتون رو میتونید مستقیما با استفاده از ImageView لود کنید که جلوتر نمونه هاش رو میبینیم .استفاده از Coroutines کتابخونه Coil از لایبرری Coroutine استفاده میکنه که تو مباحث تردینگ و async به خوبی عمل میکنه کم حجم و سبک کتابخونه Coil نسبت به گلاید 8 برابر کد کمتری داره و همینطور کمتر از پیکاسو و Fressco عه و حدود 1500 متد به فایل APK اضافه میکنه که باز هم کمتر از کتابخونه های دیگست .همینطور این کتابخونه تو تست نویسی کمک های زیادی میکنه و به دلیل استفاده نکردن از annotation به کم شدن سرعت کامپایل برنامه کمک زیادی میکنه .نمونهبه کمک این لایبرری شما پردازش های مختلفی مثل کم کردن حجم در لود تصاویر که برای نمونه عکس 500*500 رو در دیسک حفظ و 100*100 رو در ایمیج ویو نماش میده . با این حال شما میتونید کیفیت تصاویر رو مشخص کنید و اینکه نمایش تصاویر 100*100 گزینه مناسبی برای نمایش بصورت PlaceHolder هستش .همینطور نمایش انیمیشن و لودر در زمان بارگزاری تصاویر رو هم ساپورت میکنه .نمونه کد های استفاده : https://gist.github.com/colinrtwhite/2b5a1a7dc353c0cf6c5a9ebeba456458#file-coil-kt بنظرم Coil کتابخونه بسیار خوبیه و میتونه جایگزین Glide و.. بشه در پروژه های کاتلین حتی در مقیاس بزرگ مورد استفاده قرار بگیره . استفاده از اون بسیار ساده ست و امکانات خیلی خوبی داره . برای مثال با Extension Function و براحتی با صدا زدن ImageView.load() براحتی تصاویر لود میشن که تو خوانایی کد هم کمک زیادی میکنه . همینطور با دادن URL عکس رو دانلود و Drawable رو در اختیارتون قرار میده که تو کاستوم ویو ها و... هم کمک زیادی میتونه بکنه .امیدوارم که این مقاله مفید بوده باشه و برای اطلاعات بیشتر به صفحه Coil برید و خوشحال میشم نظراتتون رو بدونم و در این باره بحث کنیم .</description>
                <category>علیرضا نظری</category>
                <author>علیرضا نظری</author>
                <pubDate>Mon, 13 Apr 2020 17:09:39 +0430</pubDate>
            </item>
                    <item>
                <title>تجربه کار با فلاتر : مناسب برای پروژه های متوسط</title>
                <link>https://virgool.io/coderlife/flutter-exprience-tdte2qfuouyi</link>
                <description>اول از هرچی بگم که حدود پنج سالی میشه که در حوزه برنامه نویسی اندروید مشغول به فعالیت ام و وقتی شروع به کار با فلاتر کردم و اون رو با مباحث مختلف در کاتلین و جاوا مثل چند زبانه ، رنگ بندی (تم) و همینطور رندر کردن و سرعت و.. مقایسه کردم که به نتایج زیر رسیدم .بنظر من تا این لحظه یعنی ۱۵ فروردین ۱۳۹۹ فلاتر برای پروژه های متوسط بسیار مناسب و حتی شاید بهترین گزینه باشه و مزیت هایی داره که باعث بهتر بودن پروژه میشه .اولین چیزی که تو فلاتر منو جذب کرد و عاشقش شدم رندر یوآی و صفحات بود که با استفاده از Core های زبان C++ و Skia ویجت هارو ترسیم میکنه و اگر شما هم مثل من هی تو تنظیمات و Developer Options گزینه Show Layout Bounds رو فعال میکنید  متوجه میشید که در فلاتر تمام صفحه یکبار ترسیم میشه و هیچ Bound ی بین ویجت ها نیست و سرعت خیلی خوبی داره .اما این نوع رندر صفحات هم یسری مشکلاتی داره و برای تغییر در ایتم ها و حتی یک تکست ساده باید باید کل صفحه رو دوباره ساخت و تمام ایتم ها بخاطر یک تکست ساده دوباره ترسیم میشن و setState کردن زیاد خوشم نیومد در حالی که شما در جاوا و xml یک ویو رو آپدیت میکنید و هزینه زیادی نداره .این موضوع زمانی دیده میشه که شما یک برنامه تایمر در هردو پلت فرم بسازید و با آپدیت کردن تایمر متوجه این موضوع و فرقشون خواهید شد.همینطور در فلاتر دیباگ کردن یکمی سخت تر شده و امکاناتی که اندروید استدیو و جاوا ، کاتلین برای کرش ها  میداد که با کپی پیس کردن به باگ میرسیدیم سخت تر شده و انتظار میرفت قوی تر نسبت به قبل پیش میرفت که اینطور نشد و همینطور Log گرفتن که print ساده جایگزینش شده .قبل از این که فلاتر رو شروع کنم به یادگیری ، این عقیده رو داشتم و دارم که پروژه ای که میخواد اصولی نوشته شه و قابل توسعه و بهترین باشه باید با زبان نیتیو و یا همون زبانی که سازندگان اون پلت فرم پیشنهاد میدن نوشته بشه و فکر میکردم فلاتر نظرم رو تغییر بده که اینطور نشد.اما فلاتر و دارت واقعا ویژگی های زیاد و خوبی داره که برای ما برنامه نویس های موبایل مخصوصا اندروید آرزو محسوب میشد ، ویژگی هایی مثل :اجرای سریع تغییرات Hot Reloadاین ویژگی واقعا دلنشینه و بعضی از ما برای اجرای پروژه ها از کمتر از یک دقیقه تا شاید پنج شش دقیقه (من تا ده دقیقه هم فکر کنم رفتم) برای اجرای برنامه زمان هدر دادیم و وقتی مدیر میاد بالا سرمون میگیم داره بیلد میشه :) ، این ویژگی عالیه و با یه ذخیره کردن کد ها ، ویو و تغییرات اعمال میشن و با Cmd + \ ریلود میکنیم که الحق لذت بخشه .اضافه کردن لایبرری اضافه کردن لایبرری و Dependency در اندروید مخصوصا برای ما ایرانی ها مشکلات و اعصاب خرد کنی های زیادی داره و همینطور مثل مورد بالا تایم زیادی رو شاید صرفش کرده باشیم . اما در فلاتر این مشکلات وجود نداره و کتابخانه ها رو به راحتی میتونید تو بخش PubSpec اضافه کنید و سایت pub.dev میتونید کلی لایبرری برای کارهای مختلف پیدا کنید و مثل آب خوردن به پروژه تون اضافه کنید.دارت (Dart) دوست داشتنیزبان دارت از جاوااسکریپت ارث بری کرده و واقعا کدنویسی باهاش لذت بخشه . تمام مشکلاتی که ما با جاوا داشتیم و با اومدن کاتلین بهبود داده شد در دارت هم حل شده و اون ویژگی های بعلاوه یسری مباحث دیگ مثل Stream , Future بهترش کرده . کد نویسی Async و High order function و dynamic variable و.. همه و همه در دارت وجود دارند .طراحی UIطراحی یوای و ویجت ها در فلاتر بسیار راحت و قدرتمندتر نسبت به جاوا و همینطور مباحث مثل تم براحتی قابل پیاده سازیه ، به سادگی میشه کلاس هایی رو از ویجت ها ارث بری کرد و نوشت و بعنوان ویجت در هر جای برنامه استفاده کرد . همینطور برای طراحی یوای های پیچیده و انیمیشن ها هم فلاتر انتخاب خوبی میتونه باشه .طراحی همزمان برای ios , Android و Cross Platform بودن با فلاتر شما بیش از ۹۰ درصد کدهاتون ثابت اند و میتونید هم برای ios هم برای Android  (و وب ) یک کد ثابت و چند خروجی بگیرید (که البته برای ios همچنان نیاز به سیستم مک برای خروجی گرفتن هستش) که باز هم این موضوع برای پروژه های متوسط انتخاب خوبی میتونه داشته باشه که در هر دو پلت فرم موبایل کاربر های خودشون رو داشته باشن و همینطور آپدیت همزمان بدن .تست نویسیتست نویسی در فلاتر برای Widget , Logic  وجود داره و حتی راحت تر هم شده برای مثال در ویجت ها اسکرول کنید ، یک متن پیدا کنید یا یک ویجت خاص رو پیدا کنید و همینطور صحیح بودن Property و مقدار ویجت هارو تست کنید .محیط IDEکد های فلاتر در چند ادیتور مختلف قابل نوشتن هست و همینطور امکانات مثل auto complete و.. در اون وجود داره که اضافه کردن پلاگین فلاتر در اندروید استدیو ، intelige ، vs code و Xcode قابل استفاده است که ترجیح و انتخاب من باز هم اندروید استدیو هست .نتیجهدر کل فلاتر پر از ویژگی های مثبت هستش و کدنویسی باهاش مخصوصا برای برنامه نویس های اندروید لذت بخشه ، خیلی از مشکلات رفع و بهبود داده شده و همینطور بروز و مدرن هست . طبیعتا بین فلاتر و React Native فلاتر باید انتخاب شه و از لحاظ سرعت و استفاده از منابع خیلی خیلی سرتره و بنظرم طراحی بعضی نرم افزار های متوسط با فلاتر هم انتخاب خوبی میتونه باشه . اما اگر این مشکل رندر و setState نبود یا در اینده حل بشه واقعا خرده ای نمیشه به فلاتر گرفت .این مطلب نظر من درباره فلاتر و تجربه کار با اون بود و احتمال اشتباه هم درش هست اما خوشحال میشم نظرتون رو بدونم و بیشتر باهم در موردش صحبت کنیم .وب سایت منلینکدین </description>
                <category>علیرضا نظری</category>
                <author>علیرضا نظری</author>
                <pubDate>Fri, 03 Apr 2020 14:49:45 +0430</pubDate>
            </item>
            </channel>
</rss>