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

Kotlin • Android

🚀 آموزش ساده، کاربردی و پروژه‌محور
💡 مخصوص توسعه‌دهندگان موبایل
Download Telegram
🧵 «Coroutines» پیشرفته؛ قسمت سیزدهم: «Structured Concurrency»!
تا حالا شده بچهکوریوتینها از حیطهی پدر خارج بشن و برنامه رو به هم بریزن؟ 🤔
«Structured Concurrency» یعنی نظم والد-فرزندی بین «Scope»ها؛ درست مثل تیم کاری منظم. 💼
در این مدل، هر «Coroutine» فرزند فقط تا وقتی زندهست که والدش زنده باشه؛ با تمام شدن کار والد، همهچیز خودکار جمع میشه. 🔄
کاربرد واقعی؟ فرض کن صفحهی پرداخت باید همزمان موجودی، تخفیف و وضعیت درگاه رو بخونه. اگر یکی از اینها خطا بده، بهتره کل عملیات متوقف بشه نه اینکه نیمهکاره بمونه! 🛑

حالا ببینیم با «coroutineScope» چطور این رفتار رو پیاده میکنیم:

suspend fun fetchPaymentData() {
coroutineScope {
val balance = async { getBalance() }
val discount = async { getDiscount() }
val gateway = async { getGatewayStatus() }

showResult(balance.await(), discount.await(), gateway.await())
}
}


اگر «getDiscount» خطا بده، کل «Scope» کَنسل میشه؛ یعنی «balance» و «gateway» هم خودکار لغو میشن. 🧹
اینجا خبری از «Coroutine» سرگردان یا نشت حافظه نیست؛ ساختار خودش مراقب همهچیزه. 🧠
پس همیشه از «CoroutineScope»های والد استفاده کن و «GlobalScope» رو به عنوان ضدالگو به خاطر بسپار. 🔐
اینطوری کدت هم خواناتره، هم مقیاسپذیرتر. 🚀

#Codeit #Android #Kotlin #Jetpack #Coroutines #StructuredConcurrency #AdvancedKotlin #KotlinCoroutines
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
⏱️ تا حالا شده یه عملیات دیتابیس، انقدر طول بکشه که کاربر از برنامه بزنه بیرون؟
اینجاست که «Timeouts» توی «Coroutines» نجاتت میده! 🚀

توی بخش چهاردهم، قراره یاد بگیریم چطور با «withTimeout» و «withTimeoutOrNull» جلوی آویزون موندن برنامه رو بگیریم.

🔹 مشکل: یه فراخوانی شبکه ممکنه هیچوقت جواب نده و برنامه همیشه منتظر بمونه.
🔹 راهحل: یه مهلت مشخص میکنیم؛ اگه تموم نشد، ادامه میدیم یا خطا میگیریم.

💡 کاربرد واقعی: مثلاً در یه اپ خرید، اگه سرور ظرف ۵ ثانیه جواب نداد، به کاربر پیام «اتصال برقرار نشد» نشون بدیم.

اول بذارید یه نمونه کد ساده ببینیم:

fun main() = runBlocking {
val result = withTimeoutOrNull(5000L) {
fetchDataFromServer()
"Done"
}
if (result == null) {
println("درخواست لغو شد؛ دوباره تلاش کنید.")
} else {
println(result)
}
}


📌 این کد یعنی: حداکثر ۵ ثانیه صبر کن؛ اگه «fetchDataFromServer» تموم نشد، به جای خطا، «null» برگردون.
به این ترتیب هم برنامه کرش نمیکنه، هم کاربر بیپاسخ نمیمونه.

📌 اگه به خطا نیاز داری، از «withTimeout» استفاده کن؛ اگه بخوای حالت خالی رو مدیریت کنی، «withTimeoutOrNull» مناسبتره.

نکته مهم: «Timeouts» مخصوص عملیاتهای طولانی مثل شبکه، دیتابیس یا «File I/O» هست و جلوی قفل شدن «UI» رو میگیره.

تمرین کن و توی پروژههات از «withTimeoutOrNull» برای فراخوانیهای شبکه استفاده کن.

#Codeit #Android #Kotlin #Jetpack #Coroutines #Timeouts #Programming #MobileDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
🚀 «Coroutines» در اندروید رو جدی میگیری؟ پس این ۵ اصل طلایی رو از دست نده!

🧠 بهترین تمرینها فقط به درد پروژههای بزرگ نمیخورن؛ حتی همون پروژهی سادهی اولت هم میتونه از همین حالا تمیز نوشته بشه.

⚙️ اصل اول: همیشه از «Structured Concurrency» استفاده کن تا همهی کارها با هم لغو بشن.

🔥 اصل دوم: بهجای «GlobalScope» حتماً از «viewModelScope» یا «lifecycleScope» استفاده کن. اینطوری نشت حافظه دیگه به سراغت نمیاد.

🎯 اصل سوم: برای خطاها حتماً «CoroutineExceptionHandler» بذار. خطای ناگهانی نباید برنامه رو کرش کنه.

🛠️ اصل چهارم: از «Dispatchers.Main.immediate» برای دستکاری سریع UI استفاده کن تا ریسک «Race Condition» رو بیاری پایین.

📚 حالا ببینیم این اصول توی کد چطور اجرا میشن:

class MainViewModel : ViewModel() {

private val scope = viewModelScope

fun loadUsers() {
scope.launch {
val users = withContext(Dispatchers.IO) {
userRepository.fetchUsers()
}
userList.value = users
}
}
}


📖 این کد با «viewModelScope» شروع به کار میکنه؛ در نتیجه با نابودی «ViewModel»، همهی تسکها بهصورت خودکار لغو میشن. «withContext» هم فقط بخش سنگین کار رو به «Dispatchers.IO» میفرسته و نتیجه رو امن به «Main» برمیگردونه.

جمعبندی: کدی بنویس که همیشه قابل لغو، خواناتر و بدون نشت حافظه باشه.

#Codeit #Android #Kotlin #Jetpack #Coroutines #BestPractices #CleanArchitecture #ViewModel

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

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
🧭 نقشه راه یادگیری یعنی همین امروز بدانی چه چیزی یاد میگیری، چرا یاد میگیری و تا کجا باید برسی.

بدون نقشه، هر روز وسط انبوهی از دورهها و مقالهها گیج میشوی و مسیر برایت مبهم باقی میماند. 🌀

با یک نقشهی ساده، تمرکزت روی یک مسیر مشخص میماند و دیر یا زود به نتیجه میرسی. 🎯

قدم اول: هدفت را شفاف بنویس؛ مثلاً رسیدن به شغل «Android Developer».

قدم دوم: مسیر را به مرحلههای کوچک تقسیم کن؛ «Kotlin»، بعد «Jetpack Compose»، بعد «Networking».

قدم سوم: برای هر مرحله یک بازهی زمانی واقعبینانه بگذار؛ مثلاً دو هفته برای «Kotlin».

قدم چهارم: فقط یک یا دو منبع آموزشی معتبر را انتخاب کن. 📚

قدم پنجم: هر درس را با یک تمرین عملی تمام کن؛ یادگیری بدون ساختن، فراموشی است. 🛠️

قدم ششم: یک روز در هفته را به مرور درسهای قبلی اختصاص بده. 🔁

نقشهی تو لازم نیست بینهایت دقیق باشد؛ کافی است ساده باشد و هر هفته آن را بهروز کنی.

مهمترین نکته: مسیر یادگیری را برای خودت بساز، نه برای این که شبیه دیگران باشی. 🗺️

حالا فقط یک قدم به جلو برو؛ شروع امروز، از فردا بهتر است. 🚀

#Codeit #Android #Kotlin #Jetpack #LearningRoadmap #DeveloperMindset #GrowthMindset

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

━━━━━━━━━━━━━━━
@CodeitMobile
2
🔥 «Flow» یکی از مهمترین مفاهیم «Kotlin Coroutines» است که خیلیها توی یادگیریش گیر میکنند!
🤔 اگر هنوز نمیدانی «Flow» چیست و چرا در «Android» مهم شده، این پست دقیقا برای تو است.
📦 یک «suspend function» فقط یک مقدار برمیگرداند؛ اما «Flow» میتواند یک جریان از مقادیر را در طول زمان ارسال کند.
🛰️ «Flow» یک «Cold Stream» است؛ یعنی تا وقتی کسی به آن گوش ندهد، هیچ دادهای تولید نمیکند.
📍 کاربرد واقعی: دریافت موقعیت مکانی، دادهی سنسورها یا صفحهبندی خروجی «Room Database».
🧪 بیایید یک «Flow» ساده بسازیم که هر ثانیه یک عدد تولید کند؛ کد را ببینید:

val myFlow = flow {
for (i in 1..3) {
emit(i)
delay(1000)
}
}

lifecycleScope.launch {
myFlow.collect { value ->
Log.d("Flow", "Received: $value")
}
}


🧐 این کد چگونه کار میکند؟ تابع «flow» یک بلوک میگیرد و با «emit» مقدار تولید میکند؛ «delay» هم یک مکث یکثانیهای ایجاد میکند.
👂 در سمت مصرفکننده با «collect» به جریان گوش میدهیم و هر مقدار را لاگ میکنیم.
💡 چون «Flow» سرد است، تا وقتی «collect» صدا زده نشود، حتی یک عدد تولید نمیشود.
🎯 جمعبندی: «Flow» یعنی تولید چند مقدار ناهمگام در طول زمان؛ در پست بعدی سراغ «StateFlow» و «SharedFlow» میرویم. 🚀

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

━━━━━━━━━━━━━━━
@CodeitMobile
2
🚀 سری «Flow» قسمت دوم؛ وقتشه خودمون یک «Flow» بسازیم!

اول از همه بدونیم ساخت «Flow» سه راه اصلی داره:

۱️⃣ «flowOf» برای ساخت از مقادیر ثابت
۲️⃣ «asFlow» برای تبدیل «Collection» یا «Range» به «Flow»
۳️⃣ «flow builder» برای ساخت جریان داده‌های ناهمزمان

💡 مثلاً فرض کن داری لیست کارهای یک کاربر رو از «Room Database» می‌خونی؛ بهترین راه برگردوندن «Flow» هست.

بریم سراغ کد، ساده‌ترین حالت ساختن «Flow»:

val numberFlow: Flow<Int> = flowOf(1, 2, 3, 4, 5)

val rangeFlow: Flow<Int> = (1..5).asFlow()

val customFlow: Flow<String> = flow {
emit("شروع")
delay(1000)
emit("پایان")
}


توی «flow builder»، تابع «emit» مقدار تولید می‌کنه و «delay» فقط یه شبیه‌سازی از کار سنگینه.

بعداً با «Flow» حاصل می‌تونی از «StateFlow» یا «SharedFlow» هم استفاده کنی.

📌 نکته: «Flow» یه جریان «cold» هست؛ یعنی تا کسی جمعش نکنه، اجرا نمی‌شه.

🎯 پس هر وقت داده‌ای داری که به‌مرور تولید می‌شه، «Flow» بهترین انتخابه.

بگو کدوم بخش برات مبهمه تا توی پست بعدی عمیق‌تر بریم.

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

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
🔥 در قسمت سوم آموزش «Flow»، وقتشه با «collect» آشنا بشیم؛ همون نقطهای که جریان داده بالاخره مصرف میشه! 💡
توی «Kotlin»، «Flow» یک جریان دادهست و «collect» عملگر پایانیه که اون رو فعال میکنه و هر آیتم رو پردازش میکنه. ⚙️
بدون «collect»، هیچ اتفاقی نمیافته؛ درست مثل اینکه شیر آب رو باز کنی ولی ظرفی زیرش نذاری! 🚰
نکته اساسی: «collect» یک تابع «suspend» هست و باید داخل یک «CoroutineScope» مثل «ViewModel» صدا زده بشه. 🧠
اگه نیاز داری فقط جدیدترین مقدار پردازش بشه، «collectLatest» انتخاب هوشمندانهتری نسبت به «collect» است. 🎯
بذار یک مثال ساده و عملی از «collect» ببینیم:

flowOf(1, 2, 3).collect { println(it) }


این کد سه عدد رو بهصورت پشتسرهم چاپ میکنه؛ «Flow» اینجا یک جریان سرد هست. 📡
در پروژههای واقعی، معمولاً «collect» رو با «StateFlow» و داخل «ViewModel» ترکیب میکنم تا «UI» همیشه بهروز باشه. 📱
فراموش نکن با ذخیره «Job» میتونی جمعآوری رو با «cancel()» متوقف کنی. حالا برو امتحانش کن! 🚀
#Codeit #Android #Kotlin #Jetpack #Flow #Coroutines
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
🧠 چرا وقتی کد میزنیم، تمرکزمون اینقدر راحت پرت میشه؟

🚀 مشکل فقط گوشی نیست؛ ذهن ما عادت کرده سریع جواب بگیره، ولی کدنویسی یک کار عمیقه و دقیقاً به «Deep Work» نیاز داره.

📱 هر نوتیفیکیشن یعنی چند دقیقه وقت برای برگشتن به حالت قبلی؛ یعنی ساعتهای طلایی روزت داره هدر میره.

🎯 تکنیک «Pomodoro» رو امتحان کن: ۲۵ دقیقه فقط کدنویسی، ۵ دقیقه استراحت. این چرخه رو ۴ بار تکرار کن.

🔕 گوشی رو بذار روی «Do Not Disturb» و مرورگرت رو توی حالت «Focus Mode» قرار بده.

✂️ قبل از شروع، کارت رو به بخشهای خیلی کوچیک بشکن؛ مثلاً «رسیدن به یک «Response» درست» نه «تکمیل کل پروژه».

🔄 اگه حس کردی ذهنت پرت شده، از تکنیک «State Switch» استفاده کن: بلند شو، آب بخور، به یک نقطه ثابت نگاه کن و بعد برگرد سراغ کد.

💡 تمرکز مثل «Muscle» میمونه؛ هر بار که پرت میشی و دوباره برمیگردی، قویترش میکنی.

با همین ۳ قدم شروع کن: برنامهریزی کوچیک، حذف نوتیفیکیشنها و پذیرش اینکه مغزت هم خسته میشه.

🛠 اپلیکیشنهایی مثل «Forest» یا «Cold Turkey» هم کمک میکنن، ولی هیچکدوم جای اراده خودت رو نمیگیرن.

📌 یادت باشه: کیفیت کدی که با تمرکز نوشته میشه، همیشه از کد عجلهای بهتره.

#Codeit #Android #Kotlin #Jetpack #Focus #Productivity #DeveloperMindset
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥21
🚀 قسمت چهارم از سری «Flow»؛ اینبار با «map» و «filter» دادهها رو شکل میدیم!
🧠 این دو اپراتور بهت اجازه میدن دادههای در حال جریان رو تبدیل کنی یا ناخواستهها رو حذف کنی.
📱 مثال واقعی: لیست سفارشها از سرور میاد و فقط قیمتهای بالای ۱۰۰ هزار تومن مهم هستن.

بذار با یک مثال ساده ببینیم:

flowOf(50_000, 120_000, 80_000, 200_000)
.filter { it > 100_000 }
.map { "Order: $it Toman" }
.collect { println(it) }


خروجی: فقط «Order: 120000 Toman» و «Order: 200000 Toman» میمونه.
«filter» اول دادههای اضافی رو حذف میکنه، بعد «map» فرمت نهایی رو میسازه.
💡 نکته: ترتیب این دو اپراتور مهمه؛ اگر «map» اول باشه، همه آیتمها تبدیل میشن و بعد فیلتر.
در «Jetpack Compose» با «StateFlow» این ترکیب برای مدیریت وضعیت «UI» خیلی کاربردیه.
🔥 پس دفعه بعد بهجای حلقههای پیچیده، از «map» و «filter» استفاده کن.

#Codeit #Android #Kotlin #Jetpack #Flow #Coroutines #Filter #Map
🌐 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
اگه دو تا «Flow» داشته باشی که بخوای همزمان وضعیتشون رو باهم ترکیب کنی، «combine» دقیقاً همون چیزیه که بهش نیاز داری. 🔗

فرقش با «zip» اینه که «zip» فقط جفت‌های هم‌ردیف رو ترکیب می‌کنه، ولی «combine» با هر بار انتشار از هر کدوم از «Flow»ها، آخرین مقدار هر دو رو برداشته و نتیجه جدید می‌سازه. 📡

این رفتار توی اپ‌های واقعی خیلی به کار میاد؛ مثلاً فرم ورود که هم‌زمان باید username و password رو چک کنی. 🧠

فرض کن یه صفحه لاگین داری که دکمه ورود فقط وقتی فعال بشه که نام کاربری پر باشه و رمز حداقل ۶ کاراکتر داشته باشه.

با «combine» می‌تونی این دو «Flow» رو به یه «StateFlow» بولین تبدیل کنی و UI به‌صورت خودکار واکنش نشون بده.

بذار یه نمونه ساده رو ببینیم:

val username = MutableStateFlow("")
val password = MutableStateFlow("")

val isLoginEnabled = combine(username, password) { user, pass ->
user.isNotBlank() && pass.length >= 6
}.stateIn(viewModelScope, SharingStarted.Eagerly, false)


این کد هر بار که یکی از فیلدها تغییر کنه، شرط رو از روی آخرین مقادیر دوباره ارزیابی می‌کنه. نتیجه یه فرآیند Reactive کاملاً شفافه. 💡

حالا اگه بخوای چند «Flow» رو باهم ترکیب کنی، «combine» می‌تونه تا ۵ پارامتر مختلف پشتیبانی کنه. 🚀

پس به‌جای مدیریت دستی چند «Flow» جدا، بذار «combine» کار ترکیب رو برات انجام بده. اینطوری کدت کوتاه‌تر و خواناتر میشه. 🔥

اگه قسمت قبل سری رو ندیدی، حتماً از اول مرور کن که مفاهیم «Flow» و «StateFlow» کامل برات جا بیفته.

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

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
همیشه «هوش مصنوعی» رو به‌عنوان دستیار ببین نه جایگزین ذهنت 🧠
اگر هر سوال رو مستقیم از «ChatGPT» بپرسی، کم‌کم عضله فکری‌ات ضعیف می‌شه 💪⚠️

بهترین راهکار: اول خودت تحلیل کن، بعد از «AI» برای تکمیل یا تصحیح استفاده کن 📝
مثلاً توی «Android Debugging» به جای اینکه خطا رو بدی به «AI»، اول خودت «Logcat» رو بخون 🐞

نمونه عملی:
وقتی با «Crash» توی «Kotlin» مواجه می‌شی، اول «Stack Trace» رو بررسی کن، بعد از «AI» برای درک بهتر کمک بگیر 👇

// مرحله اول: خودت تحلیل کن
val errorMessage = "NullPointerException: cannot read field"
val possibleCause = "maybe the variable is not initialized"

// مرحله دوم: از AI برای تأیید یا تکمیل استفاده کن
// "AI, check my analysis: NullPointerException in Kotlin - possible cause: "


با این روش، هم یاد می‌گیری، هم وابسته نمی‌شی 🚀
نکته مهم: همیشه قبل از استفاده از «AI»، جواب خودت رو داشته باش 🎯

#Codeit #Android #Kotlin #Jetpack #AI #Productivity #DeveloperMindset
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1👍1🔥1
🔄 ترکیب دو «Flow» با عملگر «zip» — دقیقاً مثل زیپ کاپشن!

وقتی دو جریان داده دارید و می‌خواهید هر جفت مقدار رو به‌هم بچسبونید و یه خروجی جدید بسازید، «zip» بهترین انتخاب است.

🧠 فرض کنید از دو سنسور مجزا دما و رطوبت دریافت می‌کنید. «zip» جفت‌های هم‌ترتیب رو ترکیب می‌کند.

مثال عملی: ترکیب اطلاعات کاربران از دو منبع مختلف.

💻 کد ساده با «zip» در «Kotlin»:
val flowA = flowOf("دما: ۲۵°", "دما: ۲۶°", "دما: ۲۷°")
val flowB = flowOf("رطوبت: ۴۰%", "رطوبت: ۴۲%")

flowA.zip(flowB) { temp, humidity ->
"$temp — $humidity"
}.collect { combined ->
println(combined)
}
// خروجی:
// دما: ۲۵° — رطوبت: ۴۰%
// دما: ۲۶° — رطوبت: ۴۲%
// (جفت سوم چون جفت ندارد، نادیده گرفته می‌شود)

📌 نکته: اگر تعداد جفت‌ها نامساوی باشد، جفت‌های اضافی حذف می‌شوند.

«zip» برای ترکیب دقیق دو جریان موازی عالی است.

🎯 این عملگر رو در سناریوهای real-time فراموش نکنید.

#Codeit #Android #Kotlin #Jetpack #Flow #KotlinFlows #ReactiveProgramming
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2
🚀 جستجوی هوشمند با «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
در دنیای پر دادهٔ امروز، پردازش تکراری‌ها فقط مصرف منابع و کند شدن اپ رو به دنبال داره. 🚀

آیا می‌دونستی «Flow» می‌تونه مقادیر تکراری متوالی رو قبل از رسیدن به «collector» حذف کنه؟ 🧠

با استفاده از «distinctUntilChanged»، فقط زمانی مقدار جدید به مصرف‌کننده می‌رسه که باهاش متفاوت باشه. این یعنی پردازش هوشمند و بی‌دغدغه. 🎯

کاربرد عملیش کجاست؟ مثلاً «StateFlow» در «ViewModel» که فقط تغییرات واقعی رو به UI بفرسته. از نمایش دوبارهٔ لیست با همون داده جلوگیری کن.

حالا یه مثال ساده:

val numberFlow = flowOf(1, 1, 2, 2, 3, 3, 1, 2, 2)
.distinctUntilChanged()

numberFlow.collect { value ->
println("Received: $value")
}


در این کد، فقط مقادیر «1» و «2» و «3» و «1» و «2» خروجی داده می‌شن. تکرارهای متوالی مثل «1,1» یا «2,2» نادیده گرفته می‌شن. یعنی حذف هوشمند داده‌های تکراری بدون از دست دادن توالی منطقی. 🧹

یادت باشه: «distinctUntilChanged» رو با مقایسهٔ عمیق «distinctUntilChangedBy» اشتباه نگیری. اولی برابر ساده (با «equals») و دومی بر اساس «selector» دلخواه عمل می‌کنه. 🛠️

پس توی پروژه‌های حرفه‌ای، از این اپراتور برای بهینه‌سازی «Recomposition» در «Jetpack Compose» و کاهش بار پردازشی استفاده کن. 🚀

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

━━━━━━━━━━━━━━━
@CodeitMobile
2👍1
This media is not supported in your browser
VIEW IN TELEGRAM
🔥 در کاتلین، ما استانداردهای آموزش رو جابه‌جا می‌کنیم!
برنامه‌نویسی اندروید فقط یادگیری چند خط کد ساده نیست؛ اجرا کردن ایده‌های بزرگ با کدهای تمیز، سریع و بهینه‌ست. Kotlin ​تا این مسیر رو برات هموار کنیم.
ما توی کدایت با قدرت، تخصص و به صورت کاملاً عمیق روی آموزش کاتلین — از مفاهیم اولیه تا پیچیده‌ترین سطوح پیشرفته — تمرکز کردیم. هدف ما اینه که به جای یادگیری سطحی، به تسلط واقعی و بازارکاری برسی.
💡 چرا محتوای آموزشی کدایت؟
⚡️ مسیر سناریومحور: یادگیری مفاهیم در قالب پروژه‌ها و نیازهای واقعی بازار
⚡️ معماری‌های مدرن اندروید
⚡️ Guide to Clean Code: Clean Code (Best Practices)
اگر می‌خوای توی دنیای کاتلین یک لول بالاتر از بقیه قرار بگیری، جای درستی اومدی. ما پرقدرت کنارت هستیم! 💪

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

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1🥰1👏1
سلام رفیق شغلی! 🚀

همیشه از مصاحبه‌های فنی استرس داری؟ 🤔

این حس برای همه آشناست؛ اما نگران نباش، راهکار داره. 📝

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

دوم: پروژه‌ها رو عمیق بلد باش. تو مصاحبه ازت می‌پرسن چرا از «ViewModel» استفاده کردی یا چطور مشکل «همگام‌سازی» رو حل کردی. 🛠️

سوم: الگوریتم و ساختمان داده رو با تمرین مداوم روی «LeetCode» یا «HackerRank» قورت بده. هر روز ۱-۲ تا مسئله کافیه. 🧩

چهارم: انگلیسی رو تقویت کن. بیشتر مصاحبه‌های خوب به انگلیسی انجام می‌شن. با خودت توی آینه تمرین کن. 🗣️

پنجم: «SDLC» و «Agile» رو توضیح بده تا نشون بدی کار تیمی بلدی. 🌐

مهم‌ترین نکته: به جای حفظ کردن، درک عمیق داشته باش. وقتی مفاهیم رو بفهمی، اعتمادبه‌نفس خودتو نشون میدی. 🌟

حالا وقت اقدامه! یه مصاحبه تمرینی با یکی از دوستات ترتیب بده و استرس رو تبدیل به انرژی مثبت کن. 🔥

#Codeit #Android #Kotlin #Jetpack #InterviewPrep #TechCareer #Mindset #JobSearch
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1🥰1
بچهها، وقتشه با دو تا از کاربردیترین اپراتورهای «Flow» آشنا بشیم؛ «catch» و «retry»! ⚡️

تا حالا شده «Flow» وسط کار خطا بده و کل برنامه کرش کنه؟ 😱 دقیقاً همین مشکل رو امروز حل میکنیم.

اپراتور «catch» خطاهای بالادست رو میگیره و نمیذاره برنامه از کار بیفته. اپراتور «retry» هم بعد از خطا، دوباره «Flow» رو اجرا میکنه. 🔄

فرض کن داری از سرور داده میگیری و ناگهان اینترنت قطع میشه. اینجا بهجای کرش کردن، با «retry» چند بار دیگه تلاش میکنیم تا اتصال برگرده. 🛡️

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

var attemptCount = 0

val dataFlow = flow {
attemptCount++
emit("تلاش: $attemptCount")
if (attemptCount < 3) throw IOException("خطای موقت")
emit("موفق شد ")
}.retryWhen { _, attempt ->
attempt < 3
}.catch { e ->
emit("خطا: ${e.message}")
}


کد بالا تا وقتی خطای موقت برطرف نشده، دوباره اجرا میشه. بعد از موفقیت، «Flow» مقدار نهایی رو صادر میکنه و اگه واقعاً وصل نشد، «catch» جلوی کرش رو میگیره. 🚀

نکته مهم: «catch» فقط خطاهای بالادست خودش رو میگیره، پس باید همیشه قبل از «collect» قرار بگیره. «retry» رو هم همیشه قبل از «catch» بذار. 📌

حالا میتونی «Flow»های مقاوم و بدون کرش بنویسی. این دو اپراتور رو هیچوقت فراموش نکن! 💪

#Codeit #Android #Kotlin #Jetpack #Flow #Coroutines

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

━━━━━━━━━━━━━━━
@CodeitMobile
3🔥1
🚀 «Flow» بخش یازدهم: اپراتور «flowOn» ⚡️
📌 وقتی یک «Flow» جمع‌آوری می‌کنی، همه عملیات‌ها توی یک «Context» اجرا می‌شن. اگه کار سنگین باشه، رابط کاربری از کار می‌افته!
🛠️ «flowOn» بهت اجازه می‌ده قسمت بالای زنجیره رو به یک «Dispatcher» دیگه بفرستی؛ مثلاً «Dispatchers.Default».
🎯 یعنی فقط اپراتورهای قبل از «flowOn» روی اون رشته می‌افتن؛ بعد از اون و «collect» روی رشته اصلی می‌مونن.
📡 مثال واقعی: خوندن از دیتابیس یا شبکه، بعد نمایش نتیجه در «TextView».
👇 کد زیر رو ببین:

val heavyFlow = flow {
repeat(3) {
delay(500)
emit("Item $it")
}
}.map { item ->
item.uppercase()
}.flowOn(Dispatchers.Default)

lifecycleScope.launch {
heavyFlow.collect { result ->
textView.text = result
}
}


📖 اینجا کار سنگین «map» و خود «flow» روی «Dispatchers.Default» اجرا می‌شه، ولی «collect» روی «Main» مونده.
💰 اگه «flowOn» نداشته باشیم، کل کار روی «Main» انجام می‌شه و برنامه لگ می‌زنه.
⚠️ نکته: ترتیب «flowOn» مهمه؛ هر کدوم فقط روی بالایی‌های خودش اثر داره.
💪 حالا خودت امتحان کن و ببین چقدر اجرا بهینه‌تر شده!

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

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