نکات کاربردی در استفاده از scope functions در اندروید

مقدمه

از مزیت هایی که زبان کاتلین خصوصا برای اندروید دولوپر‌ها داشت چشیدن طعم فانکشنال کد زدن و باز شدن دنیایی از فیچر ها در جلوی روی آنها بود.
از اونجایی که خیلی از اندروید دولوپرها از جاوا مهاجرت کردند سمت کاتلین هنوز کدبیس هایی رو میشه دید که با اینکه سینتکس کاتلین دارند اما هنوز با ذهنیت جاوایی کد زده شدند و این در حالی است که با آشنا شدن با توانایی‌های زبان کاتلین نه فقط سینتکس بلکه تفکر و ذهنیت هم میتونه به سمت کاتلین شیفت پیدا کنه.

این مقاله چی هست؟

این مقاله با هدف آشنایی اولیه با scope functions و آشنایی با نکات کاربردی نوشته شده و سعی داریم ببینیم با استفاده از آنها چطور میتونیم بیشتر با کاتلین در اندروید کار کنیم.

داکیومنت رسمی کاتلین اطلاعات کاملی از این توابع داره و همچنین مقالات مختلف موجود باعث میشه از بازنویسی الکی این اطلاعات صرفنظر کنم.


تعریف کلی

کتابخانه استانداد کاتلین توابعی رو در خود دارد که تنها کارشان اجرای یک بلاک کد در چارچوب context یک شی است.وقتی آنها را روی یک شی در قالب لامبدا صدا میزنید این توابع محدوده‌ای موقت رو میسازند که میتوانید درون آن بدون نیاز داشتن اسم شی با آن کار کنید و ......

خب این یک قسمت ترجمه عادی از داکیومنت خود کاتلین بود. اما توابع scope تو تعریف خودمونی و ساده اینه که کلا 5 تا متد هستند که روی هر آبجکتی میتونند اعمال بشوند و وقتی در یک قالب لامبدا صدا بشوند میتونیم روی اون آبجکت بدون نیاز به صدا زدن اسمش یکسری کارها انجام بدیم.

این فانکشن‌ها عبارتند از:

  • let
  • apply
  • also
  • run
  • with

این توابع دو حالت دارند یا خود آبجکت رو برمیگردونند در آخر و یا خود لمبدا رو, که آبجکت در اولی بعنوان this و در دومی بعنوان it هستش.

در ادامه با هرکدوم آشنا میشیم

یک) let

وقتی روی یک آبجکت صدا بشه داخل لمبدا میتونید به context اون شی بعنوان it دسترسی پیدا کنید, استفاده‌های خیلی زیادی از این تابع میشه یک استفاده مهمش در null checkingبرای وقتی هست که روی یک آبجکت زنجیزه‌ای از متدها رو میخوایم صدا بزنیم

if (fragmentManager != null) {
fragmentManager!!.beginTransaction().add(##).addToBackStack(##).commit()
doSomething()
}
// or
fragmentManager?.beginTransaction()?.add(##)?.addToBackStack(##).commit()

حالا استفاده از let رو در این سناریو میبینیم:

fragmentManager?.let{
    it.beginTransaction().add(##).addToBackStack(##).commit()
    doSomething()
    doSomethingElse()
}

در حقیقت it اشاره به آبجکت fm داره که درون بلاک let بهش دسترسی داریم و کد درون let.? تنها وقتی اجرا میشه که fm از ابتدا null نباشه.let خود لمبدا رو برمیگردونه.
اینطوری بدون نوشتن if راحت میتونیم null check انجام بدیم!!!

دو) apply

تفاوتش با let این هست که بجای it از this استفاده میشه و خود آبجکت رو برمیگردونه. نکتش اینه که بدون صدا زدن this میتونیم متدهای خود آبجکت رو داخل لمبدا صدا بزنیم و اونا رو بقولی apply کنیم روی آبجکت

val recyclerView = findViewById(##)
recyclerView.layoutManager = ##
recyclerView.itemAnimator = ##
recyclerView.adapter = ###

خیلی از وقتها پیش اومده که آبجکتی رو بسازیم و مثل بالا مجبور باشیم عمل کنیم. اما راه بهتری که کاتلین در اختیار ما میزاره استفاده از apply هست که همون موقع که آبجکت رو داریم برقرار میکنیم همزمان یکسری کار دیگر هم درش انجام بدیم مثل زیر:

val recyclerView = findViewById(##).apply{
       layoutManager = ##
       itemAnimator = ##
       adapter = ##
       }

سه) also

این برای وقتی خوبه که روی یک آبجکت داریم کاری میکنیم یا تغییری میدیم و بعدش میخوایم بگیم همچنین(also) یک کار دیگه هم بکن.

val result = service.add(#)
doSomethingWithResult(result)

مثال بالا service.add یه کاری رو انجام میده و بعدش بهمون یک چیزی هم میده (مثلا!!) که با استفاده از also هم میشه نوشت:

service.add(#).also { 
    doSomethingWithResult(it)
}
or
service.add(#).also{ result ->
    doSomethingWithResult(result)
}

چهار) run

این هم مثل let هست و همونطوری عمل میکنه با این تفاوت که this(خود کانتکست آبجکت) رو برمیگردونه

val date: Int = Calendar.getInstance().run {
    set(Valendar.YEAR, 2030)
    get(Calendar.DAY_OF_YEAR) //return value of run
    }

پنج) with

این خیلی مثل apply هست با این تفاوت که معمولا یک نمونش برای وقتی هست که property های یک آبجکت رو میخوایم عوض کنیم

var person = Person(&quotHessam&quot, &quotEmami&quot)
person.name1 = &quotNo Name&quot
person.name2 = &quotNo Name&quot
person.** = ....

که میشه نوشت:

var person = Person(&quotHessam&quot, &quotEmami&quot)  
with(person)     {
         name1 = &quotNo Name&quot
         name2 = &quotNo Name&quot
         **          = ...
         }




موفق باشید!