کاتلین برای اندروید : یک مقدمه
۲۷ اسفند ۹۶ ، ۲۰:۱۹
سجاد یوسف نیا ۲ نظر Share

کاتلین برای اندروید : یک مقدمه

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

JetBrains که از قبلا به خاطر Intellij IDEA شناخته شده هست، کاتلین رو سال 2011 معرفی کرده و در اوایل سال 2016 به نشخه ی 1.0 رسید.

در همایش I/O سال 2017، گوگل اعلام کرد که از کاتلین به عنوان زبان برنامه نویسی رسمی اندروید پشتبانی خواهد کرد. و نسخه ی آخر اندروید استودیو از کاتلین پشتیبانی میکنه.

این در حالی هست که پشتیبانی از JAVA 8 توسط گوگل به عنوان یک زبان برنامه نویسی همچنان ادامه خواهد داشت، نظرسجی های اخیر که از برنامه نویسای اندرویدی به عمل اومده نشون میده که کاتلین به زودی کل اندروید رو تصاحب میکنه.

کاتلین یک زبان برنامه نویسی از نوع استاتیک هست که بر روی JVM اجرا میشه. و قابل تبدیل به جاوااسکریپت و زبانهای native هم هست. کاتلین ویژگی های باحالی داره!

چرا از کاتلین برای اندروید استفاده می کنیم؟

چون اندروید توی مدت کوتاهی به شهرت و محبوبیت زیادی توی دنیا رسیده، توسعه دهنده ها چند جایگزین دیگه هم برای جاوا داشتن. اگرچه جاوا خیلی استفاده میشه ولی خیلی قدیمیه.

جاوا 8 بعضی از مشکلات این زبان رو تونست حل کنه و حتی نسخه های بعدیش یعنی 9 و 10 هم کامل تر شدن. با این وجود شما برای استفاده از جاوا 8 مجبورین که حداقل از نسخه ی 24 SDKی اندروید استفاده کنین، که خیلی از توسعه دهنده ها دل به این مسئله نمیدن. تقریبا هیچکس به جاوا 9 و 10 توجهی نمی کنه.

هدف کاتلین پر کردن خلأ نبود یک زبان برنامه نویسی مدرن برای پلتفرم اندروید هست. کاتلین بر اساس چند اصل شکل گرفته که به صورت زیر هستن :

1- خلاصه کردن برای کاهش مقدار متنی که نیار به نوشتنش دارین.

2- کد واضح تر، خواناتر و قابل درک تر.

3- توی کلاس ها ما از ارورهایی مثل null pointer exceptions در امان باشیم.

4- برای ساخت برنامه های سمت سرور، برنامه های اندرویدی یا کدی که روی مرورگر اجرا میشه، انعطاف پذیر باشه.

5- قابل تعامل و هماهنگی با فریمورک ها و کتابخانه های موجود باشه و مخصوصا این رابطه با جاوا به صورت 100 درصد باشه.

شروع

پروژه ی ابتدایی را از اینجا  دانلود کنید، پروژه ی اولیه را اکسترکت کنید و با اندروید استودیو 3.0 یا نسخه های بعدی اجرا کنید.

کاری که در این پروژه ی ساده انجام میدیم ساخت یک برنامه ی ساده هست که کابرها با استفاده از اون میتونند کتابها رو جستجو کنن، جلد کتابها رو ببینند، و جلد کتابها رو ببینند و کتابها رو با بقیه به اشتراک بگذارند.

که شامل فایل سورس کدهای زیر هست، به طور خلاصه وار وظیفه شون نوشته شده:

  • MainActivity.java : یک اکتیویتی که صفحه ای رو برای جستجو و نمایش کتابها نشون می ده.
  • DetailActivity.java : یک اکتیویتی که صفحه ای رو برای جلد کتاب، براساس IDای که به اون فرستاده شده نشون میده.
  • JSONAdapter.java : یک BaseAdapter سفارشی که آبجکت JSON رو به آیتم listView تبدیل میکنه.

پروژه رو Build و Run کنید تا باهاش بتونید کار کنید.

 

راه اندازی محیط 

خوشبختانه اندروید استودیو 3.0 به بعد از کاتلین پشتیبانی میکنن. وقتی هم که تیک " Include Kotlin Support " رو بزنید هر پروژه ای که بسازید میتونه از کاتلین استفاده کنه ( شما نیازی به ساخت پروژه برای این آموزش ندارید چون که قبلا به عنوان یک پروژه ی اولیه به شما داده شده )

وقتی که اولین برنامه رو باز می کنید، ممکنه که از شما خواسته بشه که پلاگین کاتلین Android Studio 3.0 رو بروزرسانی کنید. شما میتونین با استفاده از زدن command+shift+a و تایپ کردن "Plugins" و بعدش نوشتن Kotlin داخل باکس جستجو ، آخرین نسخه ی کاتلین رو چک کنید:

کار کردن با جاوا و کاتلین همزمان در یک پروژه :

یکی از باحال ترین ویژگی های کاتلین اینه که چجوری میتونه در یک پروژه با جاوا استفاده بشه. کد جاوا میتونه از کاتلین فراخوانی بشه و برعکسش هم امکان پذیره.

از این پروژه به بعد شما باید کلاس DetailActivity رو به زبان کاتلین تبدیل کنید.

داخل پنل پروژه که سمت چپ هست، روی پکیج com.raywenderlich.android.omgandroid یک کلیک کنید.

وقتی پکیج انتخاب شد، به مسیر File/New/Kotlin File/Class برید تا یک کلاس کاتلین بسازید ( بدون پکیج انتخاب شده، شما گزینه ی انتخاب کاتلین رو نمیتونید ببینید)

داخل پاپ‌آپ New Kotlin File/Class، داخل فیلد Kind ، نام کلاس رو DetailActivityKotlin وارد کنید. و OK رو کلیک کنید.

کلاس جدید شما باید به صورت زیر باشه :

package com.raywenderlich.android.omgandroid

class DetailActivityKotlin {
} 

اینجا باید به چند نکته دقت کنید:

1- همونجور که حتما متوجه شدید، توی کد بالا کلاس های کاتلین مثل جاوا با واژه‌ی کلیدی class تعریف شدند.

2- به طور پیش فرض اینجوریه که اگه میزان دسترسی یا همون visibility‌ی کلاس رو نگیم، به صورت public تعریف میشه.

3- کلاس ها و متدها به صورت پیش فرض به صورت final تعریف میشن.

به این دلیل که کاتلین ویژگی قابل تطبیق بودن و هماهنگی ( Interporable ) بودن رو داره، می تونید از فریمورک ها و کتابخونه هایی که مال جاوا هستن هم استفاده کنید. به صورت زیر بنویسید که زیرکلاس AppCompatActivity ( از اون ارث ببره ) باشه.

class DetailActivityKotlin : AppCompatActivity() {

}

اگه نیاز بود Option+Return رو برای ایمپورت کردن کلاس های مورد نیاز مثل AppCompatActivity بزنید. معمولا اندروید استودیو اگه مشکلی وجود نداشته باشه خودش statement ها رو import میکنه.

البته توجه کنین که کاتلین یه فرق کوچکی هم با جاوا داره، اینکه موقعی که ()NameOfParentClass رو داخل تعریف زیرکلاس وارد می کنید، پرانتزهای عقبی مربوط به  سازنده ی کلاس پدر هست.

حالا متد () onCreate رو override کنید. یه چیزی شبیه به پایینی بدست میاد :

import android.app.Activity
import android.os.Bundle

class DetailActivityKotlin: Activity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
  }
}

نکته : شما میتونید از قابلیت Code Generation Functionality ( تولید کد کاربردی ) برای درست کردن امضای ( یا همون پارامتر ) متد onCreate دکمه های control + O رو بگیرید. وقتی control + O رو زدید یک پاپ‌آپ رو میبینید که همه‌ی متدهای قابل override شدن رو، با توجه به کلاسی که دارین، در خودش داره.

MainActivity.java رو بیارید و داخل ()onItentClick، جای DetailActivity رو با DetailActivityKotlin عوض کنید.

شکل intent شما باید از شکل زیر :

Intent detailIntent = new Intent(this, DetailActivity.class);

به شکل زیر تبدیل بشه :

Intent detailIntent = new Intent(this, DetailActivityKotlin.class);

شما احتیاج به تعریف اکتیویتی کاتلین در AndroidManifest.xml دارید، درست شبیه کاری که برای هر اکتیویتی توی جاوا انجام میدادید. کد پایینی رو به زیر تعریف DetailActivity اضافه کنید:

<activity
    android:name=".DetailActivityKotlin"
    android:label="@string/activity_details_kotlin"
    android:parentActivityName=".MainActivity">
  <meta-data
      android:name="android.support.PARENT_ACTIVITY"
      android:value=".MainActivity"/>
</activity>

کد رو Build و Run کنید، یک کتاب رو از لیست انتخاب کنید، بعدش یک صفحه‌ی خالی با تیتر Kotlin Book Details میبینید.

چرا کاتلین زبان خوبیه؟

قبل از اینکه در مورد ویژگی‌های کاتلین به طور مفصل صحبت کنیم، برگردین به DetailActivityKotlin.kt و کدهای زیر رو جایگرین کنید:

package com.raywenderlich.android.omgandroid

import android.content.Intent
import android.os.Bundle
import android.support.v4.view.MenuItemCompat
import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.widget.ImageView
import android.support.v7.widget.ShareActionProvider
import com.squareup.picasso.Picasso

class DetailActivityKotlin : AppCompatActivity() {

  private val imageUrlBase = "http://covers.openlibrary.org/b/id/"
  private var imageURL = ""
  private var shareActionProvider: ShareActionProvider? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_detail)

    actionBar?.setDisplayHomeAsUpEnabled(true)

    val imageView = findViewById<ImageView>(R.id.img_cover)

    val coverId = this.intent.extras.getString("coverID")

    val len = coverId?.length ?: 0

    if (len > 0) {
      imageURL = imageUrlBase + coverId + "-L.jpg"
      Picasso.with(this).load(imageURL).placeholder(R.drawable.img_books_loading).into(imageView)
    }
  }

  private fun setShareIntent() {

    val shareIntent = Intent(Intent.ACTION_SEND)
    shareIntent.type = "text/plain"
    shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Book Recommendation!")
    shareIntent.putExtra(Intent.EXTRA_TEXT, imageURL)

    shareActionProvider?.setShareIntent(shareIntent)
  }

  override fun onCreateOptionsMenu(menu: Menu): Boolean {

    menuInflater.inflate(R.menu.main, menu)

    val shareItem = menu.findItem(R.id.menu_item_share)

    shareActionProvider = MenuItemCompat.getActionProvider(shareItem) as ShareActionProvider

    setShareIntent()

    return true
  }
}

توی نگاه اول، شبیه به کد جاوا به نظر میرسه، ولی کاتلین ویژگی های خاصی داره که توی بخش بعدی باهاش آشنا میشیم.

پروژه رو Build و Run کنید، یک کتاب رو انتخاب کنید تا جلدش باید، حالا نگاه کنید چی شد!

Null Safety ( اطمینان از تهی بودن )

یکی از ویژگی‌هایی آزاردهنده  توی هر زبان، برابر با تهی گذاشته شدن یا همون Null Refrence هست. یک Null Refrence موقعی اتفاق میفته که شما بعد اینکه یک متغییری رو که تعریف کردید، مقداری بهش اختصاص ندین. موقعی که برنامه اجرا میشه و سعی میکنه تا به متغییری که نمیدونه مجای حافظه باید دنبالش بگرده دسترسی پیدا کنه - چون وجود نداره - همچین اتفاقی میافته.

معمول ترین نتیجه‌ی این مسئله، توقف ناگهانی و کرش شدن هست! احتمالا با قدرت زیاد NullPointerException آشنا هستید.

یکی از بهترین ویژگی‌ها‌ی کاتلین اینه که تصمیم شدن توی این زبان اقدام به از بین بردن NullPointerException ها ( چیزی تحت عنوان void safety ) میکنه.

توی کاتلین تنها احتمالاتی که NullPointerException ایجاد بشه یکی از دلایل زیر میتونه باشه :

  • کد جاوای خارجی این کارو انچام داده باشه.
  • یک فرخوانی صریح ( Explicit ) باعث throw شدن NullPointerException شده باشه.
  • استفاده از عملگر !! موجب این کار شده باشه ( که به طور خلاصه بررسی می‌کنیم)
  • قسمتی از داده‌ها از لحاظ مقداردهی مشکل یا تناقضی داشته باشن.

انواع Non-Null و Nullable

کاتلین انواع nullable و non-null رو داره. در صورتی که شما یه متغییر رو به عنوان nullable تعریف نکنید، بعدش نمیتونید به اون یک مقدار null رو اختصاص بدین. این قضیه از طرف کامپایلر تحمیل میشه که باعث میشه احتمال کرش شدن غیر عمدی برنامه به حداقل برسه و خیلی سخت کرش بشه.

برای تعریف یک متغییر به عنوان یک nullable ، بایستی یک ? به انتهای تعریفش اضافه کنید، همونطور که اینجا میبینید shareActionProvider به شکل زیر تعریف شده :

private var shareActionProvider: ShareActionProvider? = null

فراخوانی امن

برای دسترسی داشتن به property یا متدی در یک متغییر nullable در جاوا ، اول شما بایستی یک null check ( بررسی تهی بودن ) رو انجام دهید. شما می تونید همین قضیه رو پایین ببینید:

if (shareActionProvider != null) {
  shareActionProvider.setShareIntent(shareIntent);
}

با وجود کاتلین، شما میتونید با استفاده از عملگر فراخوانی ( .? )،عبارت بالا رو ساده تر کنین، property یا متد فقط وقتی فراخونی میشه که متغییر nullable ، تهی ( null ) نباشه.

shareActionProvider?.setShareIntent(shareIntent)

توی اینجا، setShareIntent فقط موقعی فراخوانی میشه که،  shareActionProvider که یک property هست، null نباشه.

عملگر !!

همانطور که قبلتر هم گفتیم یکی از عواملی هست که ممکنه موجب NullPointerException بشه. اگه کاملا مطمئنید که یک آبجکت nullable اصلا null نیست، آزادید که به !! اجازه بدید تا به آبجکت شما دسترسی پیدا کنه.

پایین می تونید یک مثال از این عملگر رو توی ()setShareIntent ببینبید:

shareActionProvider = MenuItemCompat.getActionProvider(shareItem!!) as ShareActionProvider

عملگر Elvis 

عملگر Elvis ( :? ) شبیه عملگر شرطی سه تایی ( if, else ,else if ) توی جاوا هست، ولی به طرز متفاوتی انجام وظیفه میکنه. شما می تونید پایین، یک کدی رو برای مثال ببینید که که باهاش میتونید طول ID یک جلد رو پیدا کنید :

val len = coverId?.length ?: 0

اگه عبارت سمت چپ عملگر Elvis تهی نباشه ، نتایج عبارت برگردنده میشه. به عبارت دیگه، عبارت سمت راست return میشه.

شبیه if و else ، عملگر Elvis فقط در صورتی عبارت سمت راست رو بررسی میکنه که عبارت سمت چپ تهی باشه.

خب ممکنه که مثل من زیاد متوجه این تعریف از Elvis نشده باشید :) پایین یه جور دیگه بر اساس دکیتومنتشین خودش تعریف و مثال زده شده:

موقعی که ما یک مرجع ( یا همون متغییر خودمون ) r داریم ، میگیم که " r تهی نیستش، با خیال راحت ازش استفاده کن در غیر این صورت از داده‌ی non-null ای به اسم x استفاده کن:

val l: Int = if (b != null) b.length else -1

به جای اینکه از if به صورت کامل استفاده کنیم ، این میتونه به وسیله‌ی عملگر Elvis گفته بشه که ، که اینجوری نوشته میشه :?

val l = b?.length ?: -1

در صورتی که عبارت سمت چپ :? تهی نباشه ، عملگر elvis اونو return میکنه ، در غیر اینصورت عبارت سمت راست رو return میکنه. یادتون باشه که عبارت سمت راست در صورتی بررسی میشه که سمت چپی تهی باشه.

یادتون باشه که throw و return عبارت هایی هستن ، که توی کاتلین میتونن سمت راست عملگر elvis به کار برده بشن. این میتونه خیلی سومند باشه، برای مثال برای چک کردن آرگومان‌ها :

fun foo(node: Node): String? {
    val parent = node.getParent() ?: return null
    val name = node.getName() ?: throw IllegalArgumentException("name expected")
    // ...
}

Type Inference

علاوه بر اینا، کاتلین از قابلیت inference هم پشتیبانی میکنه، به این معنی که میتونه نوعش رو از عبارتی که تعریف یا مقداردهی شده تشخیص بده. برای مثال، نوع داده‌ی متغییرهای imageUrlBase و imageURL موقع تخصیص ، تشخیص داده میشه.

private val imageUrlBase = "http://covers.openlibrary.org/b/id/"
private var imageURL = ""

کامپایلر نوع هر متغییر رو از طریق استنتاج به دست میاره و مقدارهای بعدی رو که به متغییر اختصاص پیدا میکنه باید از همون نوع باشه.

جالب ترین قابلیت

قبلا به نوشتن مجدد پروژه‌ی جاوا توی کاتلین فکر میکردید؟ نگران نباشید! اندروید استودیو یک پلاگین داره که این کارو انجام میده.

به این دلیل که زبان برنامه نویسی کاتلین توسط توسعه دهنده ها برای توسعه دهنده ها نوشته شده ، جوری طراحی شده که کار شما رو تا حد امکان ساده کنه. پلاگین کاتلین حتی یک ابزار مفیدی داره که شما می‌تونید با استفاده از اون سورس جاوا رو تبدیل به سورس فایل کاتلین کنین.

از این ویژگی راحت کننده برای تست تبدیل کردن DetailActivity.java به کاتلین استفاده کنید.

کلاس DetailActivity.java رو باز کنید و به مسیر فایل Code/Convert java File to Kotlin File برید.

در صفحه‌ی مربوط به Convert Java toKotlin ، گزینه‌ی OK رو بزنید. این باعث جایگزین شدن فایل کاتلین به جای فایل جاوا میشه.

خودشه! شما یک کلاس جاوا رو تبدیل به کلاس کاتلین کردین :)

کلاس DetailActivity تبدیل شده رو با DetailActivityKotlin که خودتون دستی تبدیلش کردین مقایسه کنید، تا بعضی از کارها و انتخابایی که تبدیل کننده انجام داده رو ببینید.

شما میتونید MainActivty رو برحسب کدی که جدیدا تبدیل شده ریست کنید.

Intent detailIntent = new Intent(this, DetailActivity.class);

پروژه رو Build و Run کنید و به جزییاتش دقت کنید، می بینید که کد تبدیل شده به خوبی کدی که نوشته بودید کار میکنه.

پروژه‌ی نهایی

نظرات (۲)

  1. سید داود
    سلام دستتون درد نکنه. خوب بود.

    ی ذره انتقاد هم بکنم.

    میتونستید زودتر بریم سر اصل مطلب و چیزای بیشتری از کاتلین بگید. بجای مثلا توضیح کار ctrl+o.

    "معمولا اندروید استودیو اگه مشکلی وجود نداشته باشه خودش statement ها رو import میکنه." جمله درستی نیست چون اگر auto import ش enable باشه این کارو میکنه.
  2. سید داود
    جمله آخرم اشتباه بود. جمله قبلش که نوشته بودین کاملش کرده.
    • ۶ فروردين ۹۷، ۱۶:۱۷
      آها باشه ممنون، اصلاحش میکنم حتما :)

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی

تصاوير منتخب