Codeit Mobile
94 subscribers
3 photos
1 video
244 links
📱 آموزش برنامه‌نویسی موبایل

Kotlin • Android

🚀 آموزش ساده، کاربردی و پروژه‌محور
💡 مخصوص توسعه‌دهندگان موبایل
Download Telegram
📌 رشته‌ها رو هوشمندانه بساز!
🧩 توی کاتلین، دیگه لازم نیست با + و جداکننده‌ها کلنجار بری.
🔹 String Templates بهت اجازه میدن متغیرها و عبارات رو مستقیم داخل متن قرار بدی.
💡 کافیه از $ استفاده کنی و بعدش اسم متغیر یا یک عبارت داخل {} بیاری.

مثال واقعی: فرض کن داری اسم کاربر و سنش رو نمایش میدی.
👇 یه تابع ساده با String Templates:

fun greetUser(name: String, age: Int): String {
return "سلام $name! سن تو ${age} ساله. تا ۱۰ سال دیگه ${age + 10} ساله میشی 😎"
}


📖 این کد بدون هیچ + و تبدیل اضافه، مقادیر رو داخل رشته جا میده.
خوانایی بالاتر، خطای کمتر، و کدی تمیزتر.

🎯 نکته: هر جا خواستی محاسبه یا فراخوانی تابع انجام بدی، از {} استفاده کن.

#Kotlin #StringTemplates #AndroidDev #CleanCode #Beginner #Codeit #Android #Kotlin
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🎯 تفاوت nullable و non-nullable در Kotlin
همه ما می‌دونیم که یکی از بزرگ‌ترین مزیت‌های Kotlin نسبت به جاوا، حذف NullPointerException هست.
اما چطوری؟ با دو نوع داده‌ی اصلی: nullable و non-nullable.

🔹 Non-nullable: هر متغیری که بدون ? تعریف بشه، دیگه هیچوقت نمیتونه null بگیره.
🔹 Nullable: با اضافه کردن ? به انتهای نوع، می‌تونیم بپذیریم که مقدار ممکنه null باشه.

💡 مثال واقعی: وقتی از سرور داده می‌گیریم، خیلی وقتا فیلدها ممکنه null باشن.

کد زیر رو ببینید:

fun main() {
val name: String = "Ali" // non-nullable
val nullableName: String? = null // nullable

// safe call: فقط اگر null نباشه، ادامه بده
println(nullableName?.length) // null -> خروجی null

// Elvis operator: مقدار پیش‌فرض
val length = nullableName?.length ?: 0
println("طول نام: $length")
}


📌 توضیح:
با ?. (safe call) اگر مقدار null باشه، از خطا جلوگیری می‌کنه و خودش null برمی‌گردونه.
با ?: (Elvis) می‌تونیم یه مقدار پیش‌فرض بدیم. اینطوری دیگه خبری از NullPointerException نیست.

نتیجه عملی:
- همیشه از ? برای مقادیر احتمالی null استفاده کن.
- از !! فقط وقتی مطمئنی مقدار null نیست (و ترجیحاً اصلاً استفاده نکن).
- با safe call و Elvis کدت خواناتر و ایمن‌تر میشه.

#Kotlin #NullableVsNonNullable #AndroidDev #NullSafety #SafeCall #ElvisOperator #Codeit #Android #Kotlin
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1
🔒 Null Safety در Kotlin؛ ترس از Null رو برای همیشه کنار بذار!

بسیاری از باگ‌های برنامه‌نویسی توی اندروید به خاطر NullPointerException هست. 😫 اما Kotlin با یه سیستم هوشمند، این مشکل رو ریشه‌کن کرده!

چطور کار میکنه؟
هر متغیر میتونه دو نوع باشه:
String? → میتونه null باشه
String → هرگز null نیست

🧠 مثال عملی:
فرض کن از سرور اسم کاربر رو می‌گیری. احتمال null وجود داره:

val name: String? = fetchUserName() // ممکنه null برگردونه
val length = name?.length ?: 0 // اگه null باشه، 0 می‌ذاره
println("Length: $length")


📌 توضیح کد:
با ?. (Safe Call) اگه name null باشه، length هم null میشه. با ?: (Elvis Operator) مقدار پیش‌فرض می‌دیم. نتیجه: بدون کرش!

🎯 بعدش چیکار کنیم؟
از عملگرهای !! فقط در مواقع مطمئن استفاده کن (مثلاً بعد از چک کردن if).

خلاصه: Null Safety مثل یه کمربند ایمنی می‌مونه – توی Kotlin دیگه NPE نمی‌بینی! 🚀

#NullSafety #Kotlin #JetpackCompose #AndroidDev #Codeit #Android #Kotlin #Programming
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile

━━━━━━━━━━━━━━━
@CodeitMobile
1
🔥 اپراتور Elvis (?:) در Kotlin ‒ نجات‌دهنده از null!

زمانی که با متغیرهای nullable کار می‌کنی، همیشه باید مقداردهی پیش‌فرض داشته باشی تا از NPE جلوگیری کنی. اپراتور Elvis (?:) مثل یک کوتاه‌نویس عمل می‌کند: اگر مقدار سمت چپش null باشه، مقدار سمت راست اجرا می‌شه.

مثال واقعی: فرض کن توی یک پروژه‌ی لاگین، اسم کاربر رو از سرور می‌گیری. اگر null بود، باید مقدار پیش‌فرض “کاربر ناشناس” نشون داده بشه.

val userName: String? = serverResponse?.name
val displayName = userName ?: "کاربر ناشناس"


📌 توضیح کد:
متغیر userName ممکنه null باشه. با ?: اگر null بود، "کاربر ناشناس" جایگزین می‌شه. این کار از کدهای طولانی if جلوگیری می‌کنه و کد خواناتر می‌شه.

💡 نکته: اپراتور Elvis رو می‌تونی با زنجیره‌ای از ?. و ?: ترکیب کنی تا یک‌خطی null-safe بنویسی.

برداشت نهایی: همیشه برای مقادیر nullable یک fallback داشته باش. Elvis دوست صمیمی Kotlin developer هاست!

#ElvisOperator #Kotlin #NullSafety #AndroidDev #Beginner #Codeit #Android #Kotlin
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
🔹 تا حالا توی «Kotlin» از «if» فقط برای شرط‌گذاری استفاده می‌کردی؟ 😲
🔸 وقتشه ببینی «if» می‌تونه یه مقدار برگردونه! یعنی مثل یه عبارت عمل کنه، نه فقط دستور.

یعنی به جای نوشتن چند خط کد برای مقداردهی، می‌تونی مستقیم از «if» خروجی بگیری.
⚡️ این ویژگی باعث میشه کدت خواناتر، کم‌حجم‌تر و حرفه‌ای‌تر بشه.

💡 مثال واقعی: فرض کن می‌خوای بر اساس امتیاز کاربر، یه پیام خوشامدگویی متفاوت نشون بدی.

📌 کد ساده با «if as expression»:

val score = 85
val message = if (score >= 90) {
"عالی! عالی! 🏆"
} else if (score >= 70) {
"خوب بود، ادامه بده 💪"
} else {
"نیاز به تلاش بیشتر داره 📚"
}
println(message)


🔍 اینجا «if» دقیقا مثل یه تابع عمل می‌کنه و مقدار نهایی رو به «message» نسبت میده.
🔁 دیگه نیازی به متغیر موقت یا «var» نداری، همه چیز یک‌خطی و تمیزه.

🎯 نکته مهم: حتما باید همه شاخه‌ها (if, else if, else) مقدار برگردونن، وگرنه کامپایل خطا میده.

🔥 یه قدم کوچیک به سمت کدنویسی حرفه‌ای‌تر با «Kotlin». از امروز تو پروژه‌هات از این قابلیت استفاده کن.

#Codeit #Android #Kotlin #Jetpack #KotlinTips #CleanCode #AndroidDev #Programming
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
🚀 تو کاتلین، پراپرتی‌ها فقط متغیر نیستن – پشت پرده کلی قدرت دارن!
یکی از مهم‌ترین ابزارهاشون «backing field» هست که درکش برای کد تمیز و حرفه‌ای ضروریه.

🔹 مشکل کجاست؟
وقتی یه پراپرتی داریم و می‌خوایم توی «setter» یا «getter» یه کار اضافه انجام بدیم، مستقیم به اسم پراپرتی دسترسی داریم. اما اگه توی «setter» دوباره از اسم پراپرتی استفاده کنیم، باعث فراخوانی بی‌نهایت (recursion) می‌شه!

🔸 راه‌حل: «backing field»
کاتلین یه کلمه جادویی به اسم field داره که به حافظه واقعی پراپرتی اشاره می‌کنه و از حلقه بی‌نهایت جلوگیری می‌کنه.

💡 کاربرد واقعی:
مثلاً برای اعتبارسنجی مقدار ورودی، ذخیره مقدار محاسبه‌شده، یا جلوگیری از مقادیر نامعتبر.

کد زیر یه کلاس «Person» داره که سن رو فقط بین ۰ تا ۱۲۰ قبول می‌کنه:

class Person {
var age: Int = 0
set(value) {
if (value in 0..120) {
field = value
} else {
println("Invalid age: $value")
}
}
}


🧠 توضیح کد:
توی «setter» از field برای ذخیره مقدار جدید استفاده شده. اگه مستقیماً age = value می‌نوشتیم، دوباره «setter» صدا زده می‌شد و برنامه کرش می‌کرد.

نکته مهم:
اگه هم «getter» و هم «setter» رو بازنویسی نکنی، کاتلین خودش «backing field» رو مدیریت می‌کنه. ولی وقتی یکی از اون‌ها رو تغییر میدی، برای دسترسی به مقدار اصلی باید از field استفاده کنی.

📌 خلاصه:
«backing field» بهت کنترل کامل روی ذخیره‌سازی مقدار پراپرتی رو میده بدون ایجاد وابستگی بی‌نهایت. این یه ابزار قدرتمند برای اعتبارسنجی، لاگ‌گیری و محاسبات در لحظه‌ست.

#Codeit #Android #Kotlin #Jetpack #KotlinProperties #BackingField #CleanCode #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2
🔒 فهم درست «Visibility Modifiers» توی کاتلین، تفاوت بین کد تمیز و کد آشغال رو مشخص می‌کنه
خیلی از توسعه‌دهنده‌ها می‌دونن که «private» یعنی فقط داخل کلاس دیده بشه، ولی خیلی‌ها «internal» رو اشتباه می‌گیرن.

📌 «public» — پیش‌فرض، همه‌جا دیده میشه (همون default جاوا).
📌 «private» — فقط داخل همون فایل یا کلاس.
📌 «internal» — فقط داخل همون ماژول (مثل ماژول اندروید).
📌 «protected» — فقط داخل کلاس و زیرکلاس‌ها (در کاتلین protected مثل private نیست).

🔧 کاربرد واقعی توی یک «ViewModel» اندروید:
باید منطق داخلی رو از بیرون پنهان کنی تا فقط از طریق «StateFlow» حالت رو نشون بدی.

مثال کد ساده:

class ProfileViewModel : ViewModel() {

// فقط خود ViewModel می‌تونه مقدار رو تغییر بده
private val _userName = MutableStateFlow("")
val userName: StateFlow<String> = _userName.asStateFlow()

internal fun updateUserName(newName: String) {
// فقط کلاس‌های هم‌ماژول (مثل Fragment) می‌تونن صدا بزنن
_userName.value = newName
}
}


🧠 توضیح:
- «MutableStateFlow» رو «private» کردیم تا کسی خارج از کلاس نتونه مستقیم بهش دسترسی داشته باشه.
- «StateFlow» رو «public» گذاشتیم تا UI فقط بخوندش.
- «updateUserName» رو «internal» کردیم تا فقط داخل ماژول صدا زده بشه، نه از کتابخونه‌های بیرون.

💡 نتیجه عملی: با استفاده درست از «visibility modifiers» امنیت داده رو بالا می‌بری، API تمیزتر می‌نویسی و از باگ‌های زمان کامپایل جلوگیری می‌کنی.

#Codeit #Android #Kotlin #Jetpack #CleanCode #KotlinVisibility #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2
📱 یک تابع پرکاربرد در «Kotlin» که کد رو خواناتر و کوتاهتر میکنه: «apply»!

🔧 «apply» یک «Scope Function» هست که بهتون اجازه میده بدون تکرار اسم آبجکت، به پراپرتی‌هاش دسترسی داشته باشید و اون رو تنظیم کنید. به‌جای نوشتن چندین خط «obj.prop»، با «apply» همه چیز توی یک بلاک جمع میشه.

🎯 کجا به کار میاد؟ وقتی یک آبجکت جدید میسازید و باید چند تا پراپرتی رو مقداردهی کنید (مثلاً تنظیمات یک View یا یک DTO). «apply» آبجکت رو برمی‌گردونه، پس میتونید زنجیره‌ای استفاده کنید.

💡 مثال واقعی: فرض کنید یک «TextView» دارید و میخواید متن، رنگ و اندازه رو تنظیم کنید. بدون «apply» کد تکراری زیاد میشه. با «apply»:

val textView = TextView(context).apply {
text = "Hello"
textSize = 18f
setTextColor(Color.BLUE)
gravity = Gravity.CENTER
}


🧠 توضیح: داخل بلاک «apply»، «this» همون آبجکته، پس مستقیماً به متدها و پراپرتی‌هاش دسترسی دارید. نتیجه همون آبجکت هست، ولی با مقادیر تنظیم شده. کد خواناتر، کم‌حجم‌تر و خالی از تکرار!

نکته مهم: «apply» رو بیشتر برای مقداردهی اولیه (configuration) استفاده کنید، نه برای عملیات زنجیره‌ای طولانی. اینطوری خوانایی به حداکثر میرسه.

🚀 با «apply» کد خودتون رو حرفه‌ای‌تر کنید، مخصوصاً توی «Jetpack Compose» یا موقع تنظیم «ViewModel».

#Codeit #Android #Kotlin #Jetpack #ScopeFunctions #Apply #CleanCode #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1
📂 «Portfolio»‌ای که واقعاً استخدامت کند، فقط لیست پروژه نیست.
یک داستان حرفه‌ای از مهارت‌های توست. 🚀

بسیاری از اندروید دولوپرها کلی پروژه می‌سازند اما استخدام نمی‌شوند.
علت؟ «Portfolio» مثل ویترین مغازه است؛ اگر مرتب و هدفمند نباشد، مشتری (کارفرما) رد می‌شود.

نکات کلیدی که «Portfolio» تو رو از بقیه جدا می‌کنه:

۱. کیفیت به جای کمیت – یک پروژه کامل با «Clean Architecture» و تست، بهتر از ده تا پروژه ناقصه.
۲. تمرکز روی مشکلات واقعی – اپلیکیشنی که یه نیاز روزمره رو حل کنه، جذاب‌تر از یه «To‑Do List» تکراریه.
۳. مستندسازی درست – حتماً هر پروژه رو با «README» حرفه‌ای، توضیح معماری و «Screenshots» همراه کن.
۴. حضور در «GitHub» – کد تمیز و «Commit»‌های معنادار نشون‌دهنده نظم ذهنیته.

یکی از بهترین راه‌ها مشارکت در پروژه‌های «Open Source» یا فورک یه «Library» معروف و اضافه کردن قابلیت جدیده.
این کار اعتماد کارفرما رو جلب می‌کنه.

اگر «Portfolio» نداری، همین حالا یکی از اپ‌های روزمره مثل «مدیریت هزینه» یا «یادآور دارو» رو با «Jetpack Compose» و «Room» بساز و تو «GitHub» منتشر کن.

یادت باشه: «Portfolio» نباید صرفاً لینک باشه، بلکه باید نشون بده چطور فکر می‌کنی. 💡

#Codeit #Android #Kotlin #Jetpack #PortfolioTips #CareerGrowth #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1
🧩 «MutableList» در کاتلین، لیستی است که می‌توانید اعضای آن را تغییر دهید، اضافه کنید یا حذف کنید.
برخلاف «immutable list» که فقط خواندنی است، «MutableList» برای سناریوهای پویا عالی است.

📌 کاربرد: زمانی که نیاز دارید لیست کاربران، آیتم‌های سبد خرید یا نتایج جستجو را در حین اجرا تغییر دهید.

👨‍💻 کد ساده:
val names = mutableListOf("Ali", "Sara")
names.add("Reza")
names.remove("Sara")
names[0] = "Amir"
println(names) // خروجی: [Amir, Reza]

این کد نشان می‌دهد که چگونه اعضای لیست را اضافه، حذف و ویرایش کنید.

🔄 برای کار با داده‌های پویا در «ViewModel» یا «Repository» از این نوع استفاده کنید.
- همراه با «StateFlow» یا «LiveData» برای واکنش‌گرایی.

🎯 نکته: همیشه نوع «MutableList» را با متدهای کاربردی مثل forEach یا filter ترکیب کنید تا کد تمیزتر شود.

#Codeit #Android #Kotlin #Jetpack #MutableList #KotlinBasics #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
🔧 کال کردن جاوا از کاتلین – وقتی کد جاوا داری ولی با کاتلین کار میکنی، هیچ نگرانی نیست! کاتلین کاملاً با جاوا سازگاره و می‌تونی مستقیم از کلاس‌های جاوا توی پروژه استفاده کنی. 😎

⚠️ نکته مهم: توابع جاوا که مقدار nullable برمی‌گردونن، توی کاتلین به صورت «Platform Type» دیده می‌شن. یعنی مشخص نیست nullable هست یا نه. پس حواست باشه و با «!!» یا «?» مدیریتش کن.

🛠️ مثال عملی: فرض کن یه کلاس جاوا داری به اسم «JavaCalculator» که دو متد داره. می‌خوای توی کاتلین ازش استفاده کنی و ورودیش رو با «Null Safety» ترکیب کنی.

// فراخوانی مستقیم متد جاوا از کاتلین
val calculator = JavaCalculator()
val result = calculator.add(5, 10)
println("Result: $result") // Result: 15

// استفاده از SAM Conversion برای Java interface
val runnable = Runnable { println("Hello from Kotlin") }
Thread(runnable).start()


توضیح کد:
- متد «add» مستقیم صدا زده شده و مشکل نداره.
- برای «Runnable» از SAM Conversion استفاده کردیم تا کد خواناتر بشه.
- اگر متد جاوا «@Nullable» داشته باشه، توی کاتلین با «?» می‌گیری.

💡 نکته حرفه‌ای: برای دسترسی به متدهای static جاوا از «@JvmStatic» یا «Companion Object» استفاده کن. همچنین با «@JvmOverloads» می‌تونی overloaded functions رو برای جاوا مهیا کنی.

📌 گرفته عملی:
- همیشه نوع خروجی متدهای جاوا رو چک کن (با «@Nullable» یا «@NotNull»).
- برای callback های جاوا از SAM Conversion استفاده کن.
- از «Kotlin -> Java Interop» برای کد تمیزتر بهره ببر.

#Codeit #Android #Kotlin #Jetpack #JavaInterop #NullSafety #AndroidDev #KotlinTips
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
کار با تاریخ و زمان در اندروید همیشه چالش‌برانگیز بوده؛ مخصوصاً وقتی با مناطق زمانی مختلف و فرمت‌های غیراستاندارد سر و کار دارید.

📅 در کاتلین مدرن، کتابخانهٔ «java.time» بهترین گزینه است. دیگر نیازی به «SimpleDateFormat» یا «Calendar» ندارید.

🔍 یک مشکل رایج: تبدیل یک «Timestamp» به تاریخ محلی کاربر با رعایت منطقهٔ زمانی.

🧠 راه‌حل: استفاده از «Instant» و «ZoneId» برای تبدیل دقیق.

با این دو کلاس، همیشه نتیجه‌ی درست می‌گیرید.

👇 یک مثال عملی:

import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter

val timestamp: Long = 1700000000000L // مثال
val instant = Instant.ofEpochMilli(timestamp)
val zone = ZoneId.of("Asia/Tehran")
val zonedDateTime = ZonedDateTime.ofInstant(instant, zone)
val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm")
val persianDate = zonedDateTime.format(formatter)
println(persianDate) // خروجی: ۱۴۰۲/۰۸/۲۰ ۱۲:۳۰


💡 این کد تایم‌استمپ را به تاریخ و زمان محلی بر اساس منطقه زمانی تهران تبدیل می‌کند.

⚙️ نکتهٔ پیشرفته: برای ذخیره در «Room Database»، بهتر است تاریخ را به «Long» (timestamp) تبدیل کنید و هنگام نمایش با «java.time» به فرمت دلخواه تغییر دهید.

🚀 با این روش، همهٔ پیچیدگی‌های «Daylight Saving Time» و مناطق زمانی خودکار مدیریت می‌شود.

📌 حتماً از این رویکرد در پروژه‌های جدید استفاده کنید.

#Codeit #Android #Kotlin #Jetpack #DateTime #javaTime #KotlinTips #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥21
توی قسمت پنجم سری آموزشی «Flow»، سراغ «onEach» و «launchIn» میریم؛ دو ابزار قدرتمند برای مدیریت هوشمندانه جریان دادهها! 🧩
«onEach» بهت اجازه میده قبل از اینکه مقدار به دست مصرفکننده برسه، یه عملیات میانی روش انجام بدی؛ مثل ذخیرهسازی یا لاگ گرفتن. 📝
«launchIn» هم کار «collect» رو انجام میده ولی بدون اینکه مجبور باشی خودت «Coroutine» بسازی؛ فقط کافیه «Scope» رو بدی. 🚀
این دو باهم یه ترکیب عالی برای «ViewModel» هستن؛ دادهها رو دریافت میکنی، پردازش میکنی و رابط کاربری رو هم بلاک نمیکنی. 🔥
فرض کن دادههای دمای سنسور رو میگیری و باید هر مقدار رو توی «Room Database» ذخیره کنی؛ کد زیر رو ببین:

sensorRepository.sensorFlow
.onEach { data ->
localCache.save(data)
}
.launchIn(viewModelScope)


توی این کد، «onEach» هر مقدار خروجی سنسور رو قبل از ارسال به مصرفکننده ذخیره میکنه و «launchIn» مطمئن میشه همهچیز توی «viewModelScope» اجرا بشه. 🎯
یعنی نه خبری از «collect» دستیه، نه «launch» اضافه؛ کدت خلوت و خواناتر میشه.
یه نکته حرفهای: «launchIn» یه «Job» برمیگردونه؛ با «cancel» کردنش میتونی هر موقع خواستی جمعآوری رو متوقف کنی. 💡
اگه این الگو رو یاد بگیری، دیگه مجبور نیستی توی هر «Fragment» یا «ViewModel» کد تکراری بنویسی و مدیریت «Coroutine» هم دقیق و اصولی میشه. 📈
تمرین کن و این دو تا رو جایگزین «collect» های اضافی کن؛ نتیجه رو توی تمیزی کدهات فوراً حس میکنی.

#Codeit #Android #Kotlin #Jetpack #KotlinFlow #Flow #Coroutine #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
🚀 جستجوی هوشمند با «debounce» در «Kotlin Flow»
بالاخره وقتشه تایپ کاربر رو بهینه مدیریت کنیم!

تا حالا شده کاربر توی سرچ باکس تند تند تایپ کنه و هر کاراکتر باعث یه درخواست جدید بشه؟
این یعنی ترافیک بی‌فایده و کندی UI!

🔥 راه‌حل ساده: اپراتور «debounce» تو «Kotlin Flow»
این قابلیت باعث میشه فقط بعد از توقف تایپ (مثلاً ۳۰۰ میلی‌ثانیه) درخواست ارسال بشه.

📱 مثال واقعی: یه اپ لیست محصولات که کاربر اسم کالا رو تایپ میکنه:

class SearchViewModel : ViewModel() {

private val _query = MutableStateFlow("")

val searchResults: StateFlow<List<Product>> = _query
.debounce(300) // صبر کن 300 میلی‌ثانیه بعد از آخرین تغییر
.filter { it.length >= 2 } // حداقل 2 کاراکتر
.distinctUntilChanged() // فقط مقدار جدید
.flatMapLatest { query ->
repository.searchProducts(query) // API call
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = emptyList()
)

fun onQueryChanged(query: String) {
_query.value = query
}
}


این کد چیکار میکنه؟
- وقتی کاربر تایپ میکنه، ۳۰۰ میلی‌ثانیه صبر میکنه
- اگر تایپ قطع بشه، درخواست API میره
- از تکرار مقادیر تکراری جلوگیری میکنه
- نتیجه رو به صورت خودکار به UI میرسونه

💡 مزیت بزرگ:
کاهش ۸۰٪ درخواست‌های اضافی + تجربه کاربری عالی
بدون نیاز به Handler یا Timer سنتی!

🌟 نکته حرفه‌ای:
مقدار debounce رو متناسب با سرعت تایپ کاربر تنظیم کن.
برای جستجوی فوری (مثل جستجوی زنده) ۳۰۰-۵۰۰ میلی‌ثانیه عالیه.

#Codeit #Android #Kotlin #Jetpack #Flow #Coroutines #CleanCode #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
🗂 «Jetpack Compose» قدم اولت رو برداشتی؟ حالا وقتشه با قلب این فریم‌ورک آشنا بشی: «Composable functions»!

🧠 هر «Composable function» یه تابع معمولی «Kotlin» هست که با افزودن «@Composable» بهش، می‌تونه رابط کاربری بسازه. بدونش هم می‌تونی کد بزنی، ولی با «@Composable» معجزه می‌کنه.

🔧 چرا بهش نیاز داری؟ چون با «Composable»ها می‌تونی UI رو به صورت تابعی و بدون دردسر مدیریت کنی. هر بار که وضعیت (state) تغییر کنه، فقط همون بخش لازم دوباره رندر می‌شه.

📱 مثال واقعی: فرض کن یک صفحه ساده داری که اسم کاربر رو نشون می‌ده. با «Composable» این کار رو خیلی راحت انجام می‌دی:

@Composable
fun Greeting(name: String) {
Text(text = "سلام $name!", fontSize = 24.sp)
}


این کد یه تابع «Composable» به اسم «Greeting» می‌سازه که یک «Text» رو با اسم ورودی نشون می‌ده. با تغییر اسم، فقط همین متن دوباره ساخته می‌شه و بقیه UI دست نمی‌خوره.

💡 نکته مهم: تو «Composable»ها خبری از «return» نیست. تو فقط می‌گی چی نشون بده، و «Compose» خودش بقیه کار رو می‌کنه.

🔗 حالا بیا این «Greeting» رو داخل یه «Activity» صدا بزنیم:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Greeting(name = "کاربر جان!")
}
}


توضیح: «setContent» یه «block» از «Composable»ها رو به عنوان ریشه UI معرفی می‌کنه. اینجا «Greeting» رو صدا زدیم تا متن خوش‌آمدگویی نمایش داده بشه.

💎 جمع‌بندی: «Composable function»ها پایه‌ترین مفاهیم «Jetpack Compose» هستن. هر UI که می‌سازی، در نهایت از این توابع تشکیل می‌شه. پس خوب یادشون بگیر.

#Codeit #Android #Kotlin #Jetpack #Compose #Composable #UI #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
3🥰1
🎯 «Jetpack Compose» قسمت ۵: «Button Composable»
یکی از پایهای‌ترین کامپوننت‌های UI در «Jetpack Compose» دکمه‌ها هستند.
بیایید ببینیم چطور می‌تونیم یک دکمه با ظاهر و رفتار دلخواه بسازیم.

🚀 مثال عملی:
فرض کنید یک دکمه «ثبت نام» می‌خواهید که با کلیک روی آن، یک پیام نمایش بدهد.

🛠️ کد ساده برای شروع:
@Composable
fun SimpleButton() {
Button(
onClick = {
println("دکمه کلیک شد!")
},
colors = ButtonDefaults.buttonColors(
containerColor = Color.Blue,
contentColor = Color.White
),
shape = RoundedCornerShape(12.dp)
) {
Text(text = "ثبت نام")
}
}

💡 توضیح:
- onClick: عملی است که بعد از کلیک اجرا می‌شه.
- colors: رنگ پس‌زمینه و متن رو مشخص می‌کنه.
- shape: گوشه‌های دکمه رو گرد می‌کنه (مثلاً ۱۲ پیکسل).

🎨 شخصی‌سازی بیشتر:
می‌تونید Modifier اضافه کنید تا اندازه، حاشیه یا ارتفاع دکمه رو تنظیم کنید:

Button(
onClick = { /* کلیک */ },
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.padding(horizontal = 16.dp)
) {
Text("ورود به حساب")
}

📌 کاربرد:
این کد یک دکمه تمام‌عرض با ارتفاع ثابت و فاصله از کناره‌ها می‌سازه.

نتیجه‌گیری:
با «Button» در «Jetpack Compose» می‌تونید دکمه‌های زیبا و واکنش‌گرا با کمترین کد بسازید.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #UI #Button #AndroidDev

🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1🥰1
🎯 قسمت ششم از سری «Jetpack Compose»: آموزش «Image Composable» 🖼️

گاهی اوقات ساده‌ترین کارها مثل نمایش یک تصویر، در برنامه‌نویسی اندروید کلی دردسر دارد. اما در «Jetpack Compose» با «Image Composable» همه چیز راحت و تمیز می‌شود.

🔹 «Image» یک کامپوننت آماده است که هر نوع تصویری را در «Compose» نمایش می‌دهد.
🔹 برای استفاده از آن فقط باید منبع تصویر (مثلاً یک «drawable resource») را مشخص کنید.
🔹 اگر تصویر از اینترنت باشد، از کتابخانه‌های «Coil» یا «Glide» همراه با «rememberAsyncImagePainter» کمک می‌گیرید.

یک مثال ساده: نمایش تصویر از پوشه «res/drawable»:

@Composable
fun ShowImage() {
Image(
painter = painterResource(id = R.drawable.sample_image),
contentDescription = "تصویر نمونه",
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
contentScale = ContentScale.Crop
)
}


📌 در این کد از «painterResource» برای بارگذاری تصویر داخلی استفاده شده.
📌 «contentDescription» برای دسترسی‌پذیری (Accessibility) ضروری است.
📌 «contentScale» نحوه تطبیق تصویر با فضا را مشخص می‌کند (مثلاً «Crop» برای برش).

💡 کاربردی: اگر تصویر پروفایل کاربر یا بنر تبلیغاتی دارید، با این روش به راحتی نمایش می‌دهید.
«Image Composable» انعطاف‌پذیر و سریع است – حتی انیمیشن و تغییر اندازه هم آسان.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #ImageComposable #AndroidDev #ComposeUI
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1