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

Kotlin • Android

🚀 آموزش ساده، کاربردی و پروژه‌محور
💡 مخصوص توسعه‌دهندگان موبایل
Download Telegram
🎯 Destructuring Declarations در «Kotlin» یکی از اون قابلیت‌هاییه که کد رو خواناتر و مختصرتر می‌کنه. بیایید ببینیم چطور کار می‌کنه و کجا به کار میاد.

🔹 داستراکچرینگ یعنی می‌تونید یک شیء رو به چند متغیر جداگانه بشکنید بدون اینکه دستی به تک تک فیلدها دسترسی داشته باشید. این کار مخصوصاً با «Data Class»ها عالی جواب میده.

📦 مثال واقعی: فرض کنید یک «User» دارید با فیلدهای name و age. معمولاً می‌نویسید val name = user.name ولی با داستراکچرینگ یک خطی انجامش میدید.

🧩 کد مثال رو ببینید:

data class User(val name: String, val age: Int)

fun main() {
val user = User("Ali", 28)
val (userName, userAge) = user
println("$userName is $userAge years old")
}


کد بالا مقدار name و age رو مستقیماً به userName و userAge نسبت میده. نیازی به دسترسی تکی نیست.

🔄 نکته مهم: ترتیب متغیرها با ترتیب فیلدهای constructor یکی هست. اگر فقط بخشی رو می‌خواید، از _ استفاده کنید مثلاً val (name, _) = user.

💡 کاربرد عملی: در «Jetpack Compose» برای دریافت «State»های مختلف از «ViewModel» یا در حلقه‌های روی لیست‌ها خیلی به کار میاد.

📌 نتیجه: داستراکچرینگ باعث میشه کد کمتر و خواناتر داشته باشید. از امروز توی پروژه‌هاتون استفاده کنید.

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

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
📦 عملگرها در «Kotlin» فقط برای اعداد نیستند!
میتونی به کلاس‌های خودت یاد بدی که با علامت + یا == رفتار خاصی داشته باشن. به این میگن «Operator Overloading» 🤯

چرا به کار میاد؟
وقتی با مفاهیمی مثل مختصات، ماتریس یا تاریخ کار می‌کنی، استفاده از عملگرها کد رو خواناتر و طبیعی‌تر می‌کنه. دیگه نیازی به نوشتن point1.add(point2) نیست؛ کافیه بنویسی point1 + point2

💡 مثال عملی:
فرض کن یک کلاس Point داری که مختصات x و y رو ذخیره می‌کنه. می‌خوای دو نقطه رو با + جمع بزنی و نقطه جدیدی بدست بیاری.

data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
}

fun main() {
val p1 = Point(2, 3)
val p2 = Point(4, 5)
val result = p1 + p2 // فراخوانی plus
println(result) // Point(x=6, y=8)
}


📝 توضیح:
با کلیدواژه operator به «Kotlin» می‌فهمونی که تابع plus برای عملگر + استفاده بشه. حالا هر جا p1 + p2 بنویسی، معادل p1.plus(p2) اجرا می‌شه.

🎯 کاربرد واقعی:
این قابلیت تو کتابخونه‌هایی مثل «Jetpack Compose» برای مدیریت مقادیر «Dp» یا «Offset» استفاده می‌شه. مثلاً offset1 + offset2 دو مختصات رو جمع می‌زنه.

🔑 نکته:
می‌تونی عملگرهای دیگه مثل -، *، []، == و in رو هم overload کنی. فقط کافیه تابع operator مناسب رو بنویسی.

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

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
🚀 تو کاتلین یه قابلیت باحال به اسم «Infix Functions» داری که میتونه کدت رو روان‌تر و خواناتر کنه.
بدون اینکه نقطه‌ای قبل از تابع بزاری، مستقیم می‌تونی صداش کنی. انگار داری با یه عملگر داخلی کار می‌کنی.

💡 کی به کارت میاد؟
وقتی می‌خوای یه عملیات ساده رو روی یه شیء انجام بدی و کدت شبیه به جملات طبیعی بشه. مثلاً توی دیتابیس یا DSLهای سفارشی.

📌 چطور تعریفش می‌کنی؟
فقط کافیه تابع رو با کلمه کلیدی infix مشخص کنی، حتماً یه پارامتر داشته باشه (بدون مقدار پیش‌فرض) و یه member function یا extension function باشه.

👇 یه مثال عملی ببین:

data class Player(val name: String, val score: Int)

infix fun Player.addScore(points: Int): Player {
return this.copy(score = this.score + points)
}

fun main() {
val player = Player("Ali", 100)
val updatedPlayer = player addScore 50 // بدون نقطه و پرانتز!
println(updatedPlayer) // Player(name=Ali, score=150)
}


اینجا تابع addScore رو با infix تعریف کردیم. حالا به‌جای player.addScore(50) می‌نویسم player addScore 50. کد روان‌تر و شبیه به انگلیسی ساده شده.

⚠️ نکات مهم:
- فقط یه پارامتر می‌گیره.
- پارامتر نباید vararg باشه.
- حتماً باید member یا extension باشه.

💡 کجا بیشتر می‌بینی؟
توی «Kotlin Standard Library» کلی ازش استفاده شده: map, filter, to (مثلاً "key" to "value").

📌 تسک نهایی:
برای یه کلاس Matrix یه تابع infix بنویس که دو ماتریس رو جمع بزنه. اینجوری کدت خواناتر و جذاب‌تر می‌شه.

خلاصه:
«Infix Functions» یه ابزار ساده ولی قدرتمنده برای خوندایی‌تر کردن کدهات. فقط یادت باشه ازش در جاهای درست استفاده کنی.

#Codeit #Android #Kotlin #InfixFunctions #CleanCode #DSL #ProgrammingTips
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
📝 قراردادهای کدنویسی کاتلین
کد خواناتر = تیم بهتر = پروژه موفق‌تر 🚀

«Kotlin» کلی قرارداد رسمی داره که توی «Coding Conventions» اومده.
بیایید ۳ تا از مهم‌هاش رو با هم مرور کنیم:

نحوه نام‌گذاری
- کلاس‌ها و آبجکت‌ها: «PascalCase»
- توابع و متغیرها: «camelCase»
- ثابت‌ها: «SCREAMINGSNAKECASE»

ترجیح «val» به «var»
هرجا مقدار تغییر نمی‌کنه، از «val» استفاده کن. کد ایمان‌تر و خواناتر می‌شه.

فاصله‌گذاری و «Braces»
آکولاد باز را در انتهای خط بگذار، نه خط جدا.

📌 حالا یه مثال کاربردی از یک کلاس ساده:

class User(private val name: String, private val age: Int) {

fun isAdult(): Boolean = age >= 18

fun greeting(): String {
return "Hello, my name is $name"
}
}


این کد از قراردادهای نام‌گذاری پیروی می‌کنه، از «val» به‌جای «var» استفاده کرده و «Braces» رو درست گذاشته.

🔥 نتیجه: رعایت این قراردادها باعث می‌شه کدت مثل آب روان باشه و توی پروژه‌های تیمی هیچ‌کس سردرگم نشه.

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

━━━━━━━━━━━━━━━
@CodeitMobile
🔥2
🔄 کی کد رو ریفکتور کنیم؟
رفکتورینگ مثل مرتب‌کردن کمد لباس می‌مونه؛ اگه مرتب نکنی، پیدا کردن یه تیشرت ساده هم ساعتها طول می‌کشه.
تو پروژه‌های اندروید با «Kotlin» و «Jetpack Compose» کدها سریع پیچیده می‌شن.
اما هر تغییر کوچیکی رو نباید ریفکتور کرد. باید بدونیم کی واقعاً لازمه.

📌 نشونه‌هایی که وقت ریفکتور رسیده:

1️⃣ بوی بد کد: متدهای بلند، نام‌های نامفهوم، یا تکرار یک «ViewModel» مشابه در چند کلاس.
2️⃣ تست‌نشدن: وقتی اضافه کردن یه فیچر ساده، تست قبلی رو میشکونه، یعنی ساختار کد نیاز به بازبینی داره.
3️⃣ یادگیری تیم: اگر اعضای جدید مدام سردرگم می‌شن، پس معماری شفاف نیست.
4️⃣ تغییر تکنولوژی: مثلاً از «LiveData» به «StateFlow» کوچ می‌کنید – عالی، ولی بدون ریفکتور ممکنه کد دوگانه بشه.

چه وقت ریفکتور نکنیم؟
- وقتی ددلاین نزدیکه و ریسک خرابی بالاست.
- وقتی کد کار می‌کنه و هیچ باگی نداره (اصل «If it ain't broke, don't fix it»).
- وقتی تیم در میانه یه فیچر بزرگ هست.

🛠 یک قانون عملی:
در هر اسپرینت ۲۰٪ وقت رو به «ریفکتور» اختصاص بدین.
مثلاً توی «Jetpack Compose» اگر دیدید یه composable بیش از ۸۰ خط شده، بی‌خیال نشید.
یک تابع «extract» بزنید و بخش‌های تکراری رو به composable‌های جدا تبدیل کنید.

💡 نتیجه:
رفکتورینگ هوشمندانه باعث میشه سرعت توسعه آینده چند برابر بشه.
از کدی که گربه‌شو ازش خبر نداره فرار کنید 🐈

#Codeit #Android #Kotlin #Jetpack #Refactoring #CleanCode #MobileDev #SoftwareEngineering
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1🥰1
🔹 الگوی «Delegation» در «Kotlin» یکی از قدرتمندترین ابزارهای طراحی است که به شما اجازه میدهه بدون ارث‌بری مستقیم، قابلیت‌های یک کلاس رو به کلاس دیگه واگذار کنی!

🔹 «Delegation» یعنی به جای اینکه کلاس A همه متدهای کلاس B رو پیاده‌سازی کنه، اون‌ها رو به یک شیء از کلاس B بسپاره.

🔹 «Kotlin» با کلیدواژه «by» این کار رو خیلی راحت کرده. کافیه توی تعریف کلاس از «by» استفاده کنی تا پیاده‌سازی متدها به طور خودکار از شیء delegat گرفته بشه.

🔹 مزیت اصلی: کاهش وابستگی به «Inheritance» و افزایش ترکیب‌پذیری کد. دیگه لازم نیست با سلسله‌مراتب پیچیده ارث‌بری کلنجار بری.

🔹 کاربرد واقعی: مثلاً فرض کن یک «Interface» به نام «Logger» داری که متد «log» رو تعریف می‌کنه. می‌تونی دو پیاده‌سازی مختلف براش بنویسی: یکی برای چاپ در کنسول و یکی برای ذخیره در فایل. بعد با «Delegation» کلاس اصلی رو به یکی از این پیاده‌سازی‌ها وصل کنی.

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

interface Logger {
fun log(message: String)
}

class ConsoleLogger : Logger {
override fun log(message: String) {
println("Console: $message")
}
}

class FileLogger : Logger {
override fun log(message: String) {
// ذخیره در فایل
}
}

class UserService(logger: Logger) : Logger by logger {
fun createUser(name: String) {
log("Creating user $name")
// منطق ساخت کاربر
}
}


🔹 اینجا «UserService» واسط «Logger» رو از طریق شیء ورودی (مثلاً «ConsoleLogger») پیاده‌سازی می‌کنه. هر وقت توی «UserService» متد «log» صدا زده بشه، به طور خودکار به «ConsoleLogger» برون‌سپاری میشه.

🔹 با این روش می‌تونی رفتار «UserService» رو بدون تغییر کد اصلی، عوض کنی. مثلاً یه «FileLogger» بدی بهش تا لاگ‌ها توی فایل ذخیره بشه.

🔹 نکته: «Delegation» مخصوصاً در الگوهای طراحی مثل «Strategy»، «Decorator» و حتی «Dependency Injection» کاربردی داره. یادش بگیر تا کدت خیلی تمیزتر و تست‌پذیرتر بشه.

🔹 برای پیشرفته‌ترها: ترکیب «Delegation» با «Property Delegates» تو «Kotlin» (مثل «lazy»، «observable») یه دنیا امکانات در اختیارت میذاره.

#Codeit #Android #Kotlin #Jetpack #DelegationPattern #CleanCode #SoftwareDesign #OOP

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

━━━━━━━━━━━━━━━
@CodeitMobile
2
🎯 وقتی بحث «Property Delegation» در «Kotlin» می‌شه، خیلی‌ها فقط یاد lazy می‌افتن! اما این قابلیت خیلی عمیق‌تر از این حرفast. 😎

📌 «Property Delegation» یعنی چرخه get و set یک property رو به یک کلاس جداگانه بسپاریم. به این کلاس می‌گن «Delegate». خود «Kotlin» چندتا delegate آماده داره: lazy، observable، vetoable و notNull. اما می‌تونیم delegate شخصی‌سازیشده هم بنویسیم.

🧠 کاربرد واقعی: وقتی می‌خوایم یه property رو به صورت lazy مقداردهی کنیم (مثل وابستگی‌های سنگین)، یا تغییراتش رو رصد کنیم (مثل ذخیره خودکار در «SharedPreferences»)، یا اعتبارسنجی قبل از مقداردهی انجام بدیم. اینجا دیگه نیازی به تکرار کد توی هر کلاس نیست.

💡 مثال: یه delegate سفارشی بسازیم که مقدار property رو در «SharedPreferences» ذخیره کنه. کد زیر رو ببین:

import android.content.SharedPreferences
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

class PrefStringDelegate(
private val prefs: SharedPreferences,
private val key: String,
private val default: String = ""
) : ReadWriteProperty<Any?, String> {

override fun getValue(thisRef: Any?, property: KProperty<*>): String {
return prefs.getString(key, default) ?: default
}

override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
prefs.edit().putString(key, value).apply()
}
}

این delegate رو می‌تونیم برای هر property از نوع String استفاده کنیم. مقدارش خودکار از «SharedPreferences» خوند و نوشته میشه. دیگه نیازی به edit() تکراری نداری.

🚀 نکته کلیدی: با پیاده‌سازی اینترفیس ReadWriteProperty (یا ReadOnlyProperty برای valها) هر propertyای می‌تونه رفتار دلخواه داشته باشه. این تکنیک برای «Dependency Injection»، «Validation» و «Caching» هم عالیه.

حالا برو و delegate‌های خودت رو بساز! با این کار کدت تمیزتر، قابل‌بازبینی و تست‌پذیرتر میشه.

#Codeit #Android #Kotlin #Jetpack #PropertyDelegation #AdvancedKotlin #CleanCode

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

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
الگوی Builder با «Kotlin DSL» رو قورت بده! 🚀

الگوی Builder یکی از پرکاربردترین الگوهای طراحی واسه ساختن آبجکت‌های پیچیده ست. توی جاوا کلی boilerplate داشت، ولی توی «Kotlin» با «DSL» می‌تونیم خیلی تمیزتر و خواناتر پیاده‌اش کنیم. 🎯

مثلاً فرض کن یه کلاس «Config» داری با کلی پارامتر optional. بدون «Builder» مجبوری overload یا constructor با arguments زیاد بنویسی. با «DSL» می‌تونی مثل یه زبان اختصاصی براش کد بزنی.

حالا بیا یه مثال ببینیم:

class Config private constructor(
val host: String,
val port: Int,
val debug: Boolean
) {
class Builder {
var host: String = "localhost"
var port: Int = 8080
var debug: Boolean = false

fun build(): Config = Config(host, port, debug)
}

companion object {
fun build(block: Builder.() -> Unit): Config =
Builder().apply(block).build()
}
}


این کد بهت اجازه می‌ده با یه «DSL block» تنظیمات رو بنویسی:

val config = Config.build {
host = "api.example.com"
port = 443
debug = true
}


خودت ببین چقدر خواناتر شد! دیگه نیازی به زنجیره‌ای از متدهای set نیست. «Kotlin DSL» قدرت kotlin رو توی type-safe builderها نشون می‌ده. 💪

نتیجه: هر جا که تعداد پارامترها زیاده، از «DSL builder» استفاده کن تا کدت هم مختصر بمونه هم readable. حرفه‌ای‌ها اینطوری کد می‌زنن. 😎

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

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
🔴 وقتی کد جاوا رو در پروژه «Kotlin» استفاده میکنی، چطور از «Null Safety» مطمئن بشی؟

🔵 جواب: با «Nullability Annotations» در سمت جاوا، و «Type System» قدرتمند «Kotlin» میشه مرز Null رو دقیق مشخص کرد.

🔹 «Java» به صورت پیش‌فرض «Nullable» و «Non‑Null» رو تشخیص نمیده.
🔹 «Kotlin» برای «Interop» با جاوا از «Platform Types» استفاده میکنه که هم خطرناکه هم غیرقابل پیش‌بینی.
🔹 راه حل: استفاده از «JSR 305»، «Android Annotation Support» یا «JetBrains Annotations» مثل @Nullable و @NonNull.

🔸 مثال عملی:
فرض کن یک کلاس جاوا داری که یک اسم رو برمی‌گردونه:

// Java
public class User {
private String name;

public @Nullable String getName() {
return name;
}
}


حالا در سمت «Kotlin» به صورت خودکار نوع String? شناسایی میشه و مجبور به مدیریت «Null» هستی.

// Kotlin
fun printName(user: User) {
val name: String? = user.name
println(name?.uppercase() ?: "نام ندارد")
}


🔹 اگر @NonNull استفاده کنی، «Kotlin» نوع رو String در نظر می‌گیره و نیازی به بررسی «Null» نیست.

// Java
public class User {
private String name = "default";

public @NonNull String getName() {
return name;
}
}


// Kotlin
fun printName(user: User) {
println(user.name.uppercase()) // مستقیم! بدون null check
}


🔸 نکته: در «Kotlin» با استفاده از «Annotation»های «IntelliJ IDEA» یا «Android» (مثل androidx.annotation.Nullable)، می‌تونی حتی توابع جاوا رو هم «Null‑Safe» کنی.

🚀 خروجی نهایی: با افزودن «@Nullable / @NonNull» به متدها و پارامترهای جاوا، کد «Kotlin» هم تمیزتر و هم ایمن‌تر میشه.

🔹 بعد از اضافه کردن این «Annotation»ها، حتماً «Recompile» کن و از «IDE» استفاده کن تا خطاهای احتمالی رو ببینی.

📌 برای پروژه‌های ترکیبی، این یکی از مهم‌ترین تکنیک‌های حفظ «Null Safety» است.

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

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
🎯 SAM Conversions در «Kotlin» یکی از قابلیت‌های کلیدی برای تعامل با «Java» است.
اگر یک «interface» فقط یک متد انتزاعی داشته باشد (مثل «Runnable» یا «OnClickListener»)، می‌توانید به‌جای نوشتن یک کلاس ناشناس، مستقیماً یک «lambda» بدهید.
«Kotlin» خودش هم از نسخه ۱.۴ از «fun interface» پشتیبانی می‌کند که دقیقاً همین رفتار را دارد.

📌 کاربرد واقعی:
در «Android» هنگام تنظیم «OnClickListener» برای یک دکمه، به‌جای کدهای طولانی از «SAM conversion» استفاده می‌کنیم.
همینطور در «Coroutines» برای «Runnable»های قدیمی.

🔧 مثال عملی:

// تعریف یک fun interface با یک متد
fun interface StringTransformer {
fun transform(input: String): String
}

// استفاده از SAM conversion با lambda
val toUpper = StringTransformer { it.uppercase() }
val result = toUpper.transform("hello")
println(result) // HELLO


توضیح کد:
با «fun interface» یک «interface» تک متدی تعریف کردیم. سپس به‌جای پیاده‌سازی با «object expression»، مستقیماً یک «lambda» به «StringTransformer» نسبت دادیم. «Kotlin» خودش «lambda» را به نمونه‌ای از «interface» تبدیل می‌کند. این کار خوانایی کد را افزایش می‌دهد.

💡 نکته کاربردی:
برای «API»هایی که از «Java» می‌آیند (مثل «View.OnClickListener»)، «SAM conversion» به صورت خودکار کار می‌کند. اما اگر «interface» خودتان را در «Kotlin» تعریف می‌کنید، حتماً از «fun interface» استفاده کنید تا این قابلیت را داشته باشید.

---

#Codeit #Android #Kotlin #Jetpack #SAM #FunctionalInterface #Lambda #CleanCode
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
🚀 تایپ‌الیاس‌ها در «Kotlin»؛ یه ابزار قدرتمند برای تمیزتر کردن کدهای حرفه‌اتون!

وقتی با تایپ‌های پیچیده مثل توابع با پارامترهای زیاد یا جنریک‌های چندلایه سر و کار دارید، کد خیلی شلوغ می‌شه. «Type Aliases» به شما اجازه می‌دن یک اسم ساده به جای اون تایپ‌های حجیم بذارید.

🔹 کاربرد واقعی: فرض کنید توی یه پروژه «Android» مجبورید از تابعی استفاده کنید که یه «Map» از «String» به «List<Result<Int>>» برمی‌گردونه. هر بار نوشتن این تایپ هم دردسر داره هم خوانایی رو کم می‌کنه.

🔸 با «Type Alias» می‌تونید یه اسم مثل «ResultMap» براش تعریف کنید.

typealias ResultMap = Map<String, List<Result<Int>>>

fun fetchData(): ResultMap {
// پیاده‌سازی تابع
return emptyMap()
}


حالا هر جا نیاز به این تایپ دارید، فقط از «ResultMap» استفاده می‌کنید؛ کد خواناتر و نگهداری‌ش ساده‌تر می‌شه.

🔑 نکته حرفه‌ای: از «Type Alias» برای نام‌گذاری توابع callback هم استفاده کنید:

typealias ProgressCallback = (percent: Int) -> Unit

fun downloadFile(url: String, onProgress: ProgressCallback) {
// ...
}


📌 این کار باعث می‌شه که امضای توابع دیگه شلوغ نباشه و تیم راحت‌تر کد رو بخونه.

👨‍💻 یه نکته پیشرفته: «Type Alias» در زمان کامپایل حذف می‌شه و جایگزین واقعی خودش رو می‌گیره، پس هیچ هزینه اجرایی نداره!

🎯 یادتون باشه از «Type Alias» برای کاهش پیچیدگی و افزایش خوانایی استفاده کنید، نه برای مخفی کردن منطق.

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

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
🔒 ایموتبیلیتی (Immutability)؛ سپر امن در کدهای هم‌روند (Concurrent)
وقتی چند تابع یا «Coroutine» هم‌زمان به یک آبجکت دسترسی دارند، تغییر ناگهانی اون باعث باگ‌های سخت می‌شه. راه‌حل؟ استفاده از استراتژی‌های «Immutability».

راهکار اول: همیشه از «val» به جای «var» استفاده کن
«val» فقط یک بار مقداردهی میشه و دیگه تغییر نمی‌کنه. این ساده‌ترین قدم برای جلوگیری از تغییرات ناخواسته‌ست.

راهکار دوم: «data class» و متد «copy()»
وقتی نیاز به تغییر یک مقدار داری، به‌جای دستکاری مستقیم، یک کپی با تغییرات مورد نظر بساز:

data class User(val name: String, val age: Int)

fun main() {
val user = User("Ali", 25)
val updatedUser = user.copy(age = 26) // immutable update
println(user) // User(name=Ali, age=25)
println(updatedUser) // User(name=Ali, age=26)
}


راهکار سوم: مجموعه‌های فقط‌خواندنی (Read‑Only Collections)
از «listOf», «mapOf», «setOf» استفاده کن تا از تغییرات سهوی جلوگیری بشه. اگه نیاز به تغییر داری، مستقیماً یک «MutableList» بساز و بعد از اتمام کار، اون رو به «List» تبدیل کن.

val items = listOf("A", "B", "C") // immutable
// items.add("D") // کامپایل نمیشه


راهکار چهارم: «sealed class» یا «sealed interface»
برای موقعیت‌هایی که مجموعه حالات ثابتی داری (مثل وضعیت‌های مختلف رابط کاربری)، از «sealed» استفاده کن. این کار تغییرات غیرمجاز را در زمان کامپایل مسدود می‌کنه.

💡 نتیجه عملی:
در «ViewModel» و «Jetpack Compose» همیشه «State» رو به صورت immutable نگه دار و با «copy()» یا «StateFlow» وضعیت جدید رو منتشر کن. این کار از نوسانات UI و باگ‌های هم‌روند جلوگیری می‌کنه.

#Codeit #Android #Kotlin #Jetpack #Immutability #CleanCode #Concurrency #StateManagement
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1
🧠 چطور مثل یک «Senior Developer» فکر کنیم؟

بیشتر ما فکر می‌کنیم سینیور کسی است که کدهای پیچیده می‌نویسه 📝
اما حقیقت اینه: سینیورها ساده‌ترین راه‌حل رو انتخاب می‌کنن، نه پیچیده‌ترینشون.

🔍 تفاوت اصلی در نگاه به مسئله‌ست:
جونیور به کد نگاه می‌کنه، سینیور به محصول و تیم 🧑‍💻👥

سه عادت کلیدی که ذهنیت سینیور رو می‌سازه:

1️⃣ سوال قبل از کد زدن
قبل از نوشتن یک خط کد، از خودت بپرس:
«آیا این راه‌حل قابلیت نگهداری داره؟ آیا تیم می‌تونه ادامه بده؟»

2️⃣ غلبه بر «NIH Syndrome»
سینیورها از کتابخونه‌های آماده استفاده می‌کنن، نه اینکه همه چیز رو از صفر بنویسن 📚
«Jetpack Compose» و «Kotlin Coroutines» رو به‌جا به کار ببر.

3️⃣ مدیریت «Technical Debt»
بدهی فنی رو نادیده نگیر، ولی برای هر بدهی تأثیر روی بیزینس رو بسنج ⚖️

💡 نکته طلایی:
هر تصمیم فنی باید جواب این سوال رو بده: «این کار چقدر ارزش برای کاربر و تیم می‌سازه؟»

با این طرز فکر، حتی با دو سال تجربه هم می‌تونی مثل یک سینیور رفتار کنی 🚀

#Codeit #Android #Kotlin #Jetpack #SeniorMindset #DeveloperGrowth #CleanCode #SoftwareEngineering
🌐 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
توی دنیای برنامه‌نویسی، خیلی‌ها کد می‌زنن، اما فقط تعداد کمی می‌تونن ایده‌هاشون رو شفاف به بقیه منتقل کنن. 🎯

ارتباط مؤثر یعنی بتونی یه مفهوم پیچیده رو طوری توضیح بدی که حتی یه تازه‌وارد هم بفهمه. این مهارت تو جلسات تیمی، مصاحبه‌های شغلی و حتی نوشتن مستندات به کارت میاد. 🗣️

اولین قدم: مخاطبت رو بشناس. اگه با یه مدیر صحبت می‌کنی، روی «Result» تمرکز کن، نه روی جزئیات فنی. اگه با یه توسعه‌دهنده‌ی دیگه‌ای، می‌تونی از «Abstraction» و «Design Pattern» حرف بزنی. 🧩

دومین قدم: از مثال‌های دنیای واقعی استفاده کن. به‌جای گفتن «این ماژول با «Clean Architecture» جدا شده»، بگو «مثل یه رستوران که آشپزخونه‌ش از سالن جدا شده، این ماژول‌ها هم وابستگی ندارن و هرکی می‌تونه مستقل کار کنه.» 🍽️

سومین قدم: از قیاس‌ها و تصویرسازی غافل نشو. مغز انسان با داستان‌ها و تصاویر بهتر ارتباط برقرار می‌کنه. مثلاً بگو «این «ViewModel» مثل یه کیف پوله که اطلاعات رو تا وقتی صفحه بسته نشده، نگه می‌داره.» 🎒

چهارمین قدم: ساده بگو، اما ساده‌انگارانه نه. اصطلاحات فنی رو با « » مشخص کن و اگه لازم شد، توضیح مختصری بده. مثلاً: ««Lazy Initialization» یعنی تا وقتی واقعاً بهش نیاز نداری، اون شئ رو نساز.» 🛠️

نکته مهم: وقتی یه تکنولوژی رو توضیح میدی، حتماً بگو چرا به کار میاد، نه فقط چیه. ««StateFlow» برای مدیریت وضعیت در «Jetpack Compose» عالیه چون همیشه آخرین مقدار رو داره و از مصرف حافظه جلوگیری می‌کنه.»

تمرین کن: هر روز یه مفهوم «Android» یا «Kotlin» رو برای یه دوست غیرفنی توضیح بده. کم‌کم می‌بینی چقدر ارتباطت بهتر میشه. 📈

یادت باشه: بهترین کد دنیا رو اگه نتونی توضیح بدی، بی‌فایده‌ست. ارتباط شفاف، کلید موفقیت توی هر تیم فنی‌ست. 💬

#Codeit #Android #Kotlin #Jetpack #CleanCode #SoftSkills #TechCommunication #DeveloperMindset
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1🥰1