213
Подписчики
Нет данных24 часа
+37 дней
+330 дней
Архив постов
213
در اندروید استادیو نسخه ی کوالا (Koala) ابزاری برای Screenshot Testing در jetpack compose معرفی شده و از این به بعد دیگه به لایبرری های 3rd-party برای انجام این نوع از تست ها احتیاج نیست.
https://developer.android.com/studio/preview/compose-screenshot-testing
213
flowOf("A","B","C","D","E")
.onEach { println("Wizard emits: $it") } //emitter side
.buffer()
.collect { // collector side
println("Lady collects: $it")
delay(2000)
}
اما بافر دقیقا چه کار میکنه ؟
تمام فرایندهای ایجاد یک فلو، emit کردن دیتا، اعمال اپراتور ها و collect کردن دیتا روی یک single coroutine اتفاق می افته، بافر این single coroutine رو تبدیل میکنه به دوتا کروتین، تمام لاین های قبل از متد بافر (emitter side) در یک بلاک کروتین انجام میشه و تمام لاین های بعد از متد بافر (collector side) در یک بلاک کروتین دیگه انجام میشه.
این دو تا کروتین از طریق یک channel با هم دیگه connect میشن و این چنل هنگامی که collector مشغول هست emission side رو suspend میکنه تا collector مجددا available بشه.
به این ترتیب از ارسال دیتا های جدید به collector در هنگامی که busy شده است جلوگیری شده و مشکل backpressure در flow را حل می کند.213
یکی از مشکلات پرفورمنسی دیگه ای که اگر اتفاق بیفته پیدا کردنش سخت تره بحث Backpressure در flow هست.
حالا Backpressure اصلا چیه ؟ ما در flow دو تا ساید مهم داریم یکی Producer (emitter) هست و یکی هم Consumer یا همون Collector.
تو اندروید ما معمولا collector مون رو در ui و یا یک کامپوننت Lifecycle aware پیاده میکنیم.(دلیلش هم واضحه)
حالا این جا ممکنه یه مشکلی به وجود بیاد، اونم اینکه سایدی که داره دیتا رو emit میکنه سرعتش از سایدی که داره دیتا رو collect میکنه بسیار بیش تر بشه، در این صورت در سمت collector یک Backpressure اتفاق می افته و میتونه منجر به مشکلات پرفورمنسی و لگ زدن های ui بشه.
مثلا تو اپ ما emitter یه سری سیگنال رو با تناوب بسیار بالا ارسال میکرد و collector که روی ترد main مشغول رندر این دیتا روی ui بود چون منطقا سرعت پایین تری داشت دچار Backpressure شدیدی میشد و تاثیرش در پرفورمنس اپ به وضوح مشخص میشد.
اما حالا چطور باید این مشکل رو برطرف کرد؟ یکی از روش هاش استفاده از buffer operator هست.
213
در یکی از پروژه هامون اخیرا یه باگی پیش میومد که یک متغیری برخی از value هایی که بهش اساین می کردیم رو انگار نمی پذیرفت. مثلا به طور ساده فرض کنید یک متغیری رو در Loop گذاشتیم و دایما مقداری بهش اساین میکنیم اما وقتی نتیجه رو print می کردیم برخی از مقادیر دیده نمیشد. من بعد از کلی دیباگ متوجه شدم که روی این متغیر race condition داره اتفاق می افته (تقریبا این اخرین چیزی بود که به ذهنم میتونست برسه).
این جوری متوجهش شدم که جاهایی که اون متغیر استفاده شده بود رو بررسی کردم و فهمیدم در دو تا کروتین مجزا که به صورت Long Running و تقریبا به صورت همزمان اجرا میشدند به این متغیر دسترسی گرفته میشد و مقادیرش تغییر میکرد.
حالا race condition چیه؟ وقتی به یک ریسورس از جاهای مختلفی به طور همزمان دسترسی گرفته میشه اینکه کی زودتر به این ریسورس میرسه و چه تغییری ایجاد میکنه میتونه روی نتیجه شما تاثیر بگذاره و نتیجه شما رو unstable کنه.
از چیز هایی که در دانشگاه و سیستم عامل یادم میومد فهمیدم یه سری الگوریتم بود که وقتی یک ترد یک ریسورس رو در اختیار میگرفت اون ناحیه که به ناحیه بحرانی معروف بود رو Lock میکرد تا ترد دیگه ای نتونه در این حین اون جارو تغییر بده.
بعد از یه مشورت با gpt دیدم که خودشون براش یه فانکشنالیتی در کاتلین کروتین پیاده کردن و نیاز نیست که خودم بنویسمش.
// این گلوبال تعریف میشه
val mutex = Mutex()
//این داخل بدنه کروتین هست
mutex.withLock { counter++ }
متد withLock یک متد suspend هست که ترد رو لاک نمیکنه اما در حین اجرای بلاک خودش، به کس دیگری اجازه نمیده تا بلاک رو مجددا اجرا کنه
در واقع فرض کنید که دوتا کروتین بخوان مقدار counter رو تغییر بدن اونی که زودتر میرسه counter رو لاک میکنه و کروتین دیگه suspend میشه تا کار کروتین اول تموم شه.
راستی یه چیز دیگه ای که از دانشگاه یادم میاد این بود که از استادمون پرسیدم که اگر دو تا ترد دقیقا به طور همزمان (احتمال این خیلی کمه) به یک ناحیه بحرانی برسن کدوم یکی اولیت داره که وارد ناحیه بشه و کارش رو شروع کنه؟ استاد هم گفت که به فرض اگر چنین اتفاقی بیفته یه عدم قطعیت اتفاق می افته و سیستم عامل به یکشون اجازه میده که کارش رو شروع کنه یعنی به طور مثال فرض کنید که اگر چند بار این اتفاق پشت سر هم بیفته میبیند که به طور رندوم یکیشون انتخاب میشه و کارش رو شروع میکنه.
راستی شرکت ما دنبال بکند دولوپره و دارن مصاحبه میکنن و برامون جالب بود که خیلی از کسایی که مصاحبه شدن نمیدونستن Transaction تو دیتابیس چه کار میکنه.🫠
در واقع transaction هم یه جورایی از این مفهوم استفاده میکنه. وقتی transaction کارش رو شروع میکنه ناحیه بحرانی رو قفل می کنه تا کوئری های داخلش رو به اتمام برسونه در این لول اگر transaction دیگه ای ایجاد بشه در صف قرار میگیره و صبر میکنه تا کار قبلی تموم بشه213
می دونستید که در کاتلین میتونیم anonymous objects هارو به این روش هم تعریف کنیم.
شاید استفاده ازش در زمان هایی مناسب باشه که میخواهیم مجموعه ای از دیتا های simple رو مدل و hold کنیم بدون اینکه یک TYPE جدید ایجاد کنیم. چون همونطور که میدونید اگر همین کد رو با data class پیاده کنیم کاتلین باهاش مثل یک تایپ برخورد میکنه والبته که overhead هایی رو هم بهش اضافه میکنه تا بتونیم روی مقادیر این دیتا کلاس iterate کنیم و متد های copy و equal رو روش فراخوانی کنیم.
213
گوگل داره code formatter خودش رو از ktlint به ktfmt تغییر میده. یه لینکی هم گذاشتن که چرا میخوان از ktfmt استفاده کنن اما دسترسی ای که میخواد رو من ندارم که بتونم بازش کنم.
گیتهابش رو میتونید چک کنید👇
https://github.com/facebook/ktfmt?tab=readme-ov-file
213
اقا سلام
دیروز یه اتفاقی افتاد توی کنفرانس که واقعا از دیروز تا همین الان شگفت زده هستم.
گفتم با شما به اشتراک بذارم چون میدونم شما هم علاقه مندید.
دیروز بعد از اخرین تاک همه که پا شدن رفتن Jake Wharton رو دیدم که بیکار بود رفتم پیشش با استرس سلام کردم و باهاش صحبت کردم یکم بعد گفت من باید برم اگر میخوای بیا با من، من تشکر کردم ولی نفهمیدم اون موقع، بعد که رفت یهو فهمیدم منظورش این بوده که اگر وقت داری بیا. خیلی نارحت شدم که بهش نگفتم که میخوام بیام. ولی از پشت سر دنبالش رفتم و رفت توی هتل کناری جایی که کنفرانس برگزار میشد منم رفتم توی هتل یهو دیدم واااااااای
یکیو دیدم که واقعا علاقه مند بودم ببینمش امسال توی کنفرانس
رفتم بهش گفتم خیلی شبیه رومان الیزاروف هستی گفتم خودمم 😂😂😂
دیگه از ذوق داشتم نمیدونستم چیکار بکنم
اومده بود ولی من توی خود کنفرانس و حتی توی محیطی که همه بودن ندیده بودمش فکر کنم فقط توی هتل مونده بود
213
این یه خبر خیلی مهمه
یعنی اینکه دارن روی این کار میکنن که وقتی کد های کاتلین به Front End کامپایلر k2 داده میشه و کامپایلر کد های میانی IR رو جنریت میکنه، یه سری API واسط توسعه دادن که تونسته کد های میانی رو به کد swift تبدیل کنه.
این یعنی اینکه دارن روی قابلیتی کار میکنن که از کاتلین خروجی سوییفت بگیرن، مشابه کاری که قبلاً در js کرده بودن.
213
در kotlin conf یه preview نشون دادن که kotlin playground قراره از تبدیل کد های kotlin به swift پشتیبانی کنه.
play.kotlinlang.org
213
Code can be shipped fast with less tech debt by focusing on aspects like MVP, KISS or YAGNI.
Standard processes, low hierarchy and common code understanding can help too.
I always ask myself: Can I (and the team) find, understand and delete code fast enough in the future?
#daily_tips
213
یکی از سمی ترین چیز ها در اندروید همین DataBinding بود، یهو به خودت میومدی میدیدی وسط سورس xml، لاجیک برنامه رو هندل کردی.
خداروشکر که از اون دوران گذر کردیم...
213
روی پروداکت بهتره که Todo نداشته باشیم وقبلش همشو پیاده سازی کرده باشیم
اما اگر در شرایطی هستیم که باید به همراه todo ها یک نسخه بدیم بهتره که از safe-todo استفاده کنیم تا باعث ایجاد کرش روی کد های un-implemented نشیم.
kotlin
fun SAFE_TODO(reason:String){
if (BuildConfig.DEBUG) {
TODO(reason)
}else{
Toast.makeText(context,"NOT_IMPLEMENYTED:$reason",Toast.LENGTH_SHORT).show()
}
}213
خبر های امروز همش مالتی پلتفورمه 🏆
اول اینکه گوگل در i/o به طور رسمی اعلام کرد که از کاتلین مالتی پلتفورم پشتیبانی می کنه و همچنین تصمیم داره تا لایبرری ها و تولز های بیش تری رو براش توسعه بده 👇
https://android-developers.googleblog.com/2024/05/android-support-for-kotlin-multiplatform-to-share-business-logic-across-mobile-web-server-desktop.html
دوم اینکه علاوه بر Room، viewModel، dataStore و Collections امروز paging و LifeCycle هم مالتی پلتفورم شد 👇
https://developer.android.com/jetpack/androidx/releases/lifecycle#2.8.0
https://developer.android.com/jetpack/androidx/releases/paging#version_33_2
سوم اینکه jetbrains اعلام کرده که تصمیم داره همکاری های خودش با گوگل رو در قسمت multiplatform افزایش بده.
