Kotlin Generation : เรื่องราวของการเปลี่ยนถ่ายยุคสมัยของชาว Android Developer
ตอนนี้เราเริ่มเขียน Kotlin อย่างจริงจังแล้ว และหลายๆคนอยากรู้จริงจริ๊งงงงง ว่าเขียน Kotlin แล้วลืม Java เลยหรือเปล่า แล้วต้องทำอย่างไรบ้าง
อย่างที่เราทราบกันดีอยู่แล้วเนอะ ว่าในงาน Google I/O เมื่อปีก่อน เขาประกาศว่าภาษา Kotlin เป็นภาษา Official นึงในการเขียน Android
ซึ่งเราก็เพิ่งรู้จักชื่อภาษา Kotlin มาประมาณปีนึง และเริ่มได้ทำความรู้จักจริงๆ ตอนมางาน Kotlin Workshop นั่นแหละ
และงาน Android Bangkok 2018 ที่ผ่านมา บรรดา speaker ก็ได้กล่าวถึงว่า มาใช้ Kotlin กันเถอะ ชีวิตจะดีขึ้น ซึ่งจริงๆเราก็เหมือนโดนป้ายยามาสักพักตั้งแต่ตอนไป workshop แล้วแหละ และเราเองก็ได้เริ่มเขียน Kotlin บน production ตั้งแต่ต้นปีนี้เลย
และในงาน Google I/O 2018 ที่ผ่านมา ก็มีหลายๆ session ที่พูดถึง Kotlin ด้วยหล่ะ
เริ่มที่ Developer Keynote ก่อนเลยจ้า …
Android Developer เริ่มมาใช้ Kotlin และมีตัวเลขที่เติบโตขึ้นทุกเดือน โดยมีเขียนแอปด้วย Kotlin ถึง 35% และ 95% บอกว่า ใช้แล้วชอบมาก และเข้าใจว่า แอปในสไลด์นี้เป็นแอปที่เขียนด้วย Kotlin นะ
อย่าง Protips ก็บอกไว้เลยว่า เริ่มต้น Android ไม่ต้องไปเรียน Java แล้ว เริ่มที่ Kotlin เลยแล้วกัน
จริงๆเจ้า Document ฝั่ง Android ก็เริ่มมีตัวอย่างที่เป็น Kotlin บ้าง
และในงาน Google I/O 18 ก็เริ่มใส่ตัวอย่างโค้ดที่เป็น Kotlin มาบ้างแล้ว
ขนาดของออกใหม่อย่าง Android Jetpack ยังมี Kotlin เป็นพื้นฐานเลยนะ
สามารถอ่านเพิ่มเติมได้ที่นี่
และในงานก็มี session การเขียน Kotlin โดยเฉพาะ ซึ่งเขาก็ได้บอกว่า มันไม่ได้ยากนะยูว เรามาเริ่มไปพร้อมๆกันนะ
ปล. ตอนแรกหาหัวข้อแจ่มๆที่จะพูดใน Code Mania 111 ไม่ได้ เปลี่ยนเรื่องบ่อยมากจนมาจบที่เรื่องนี้ คิดว่าน่าจะเป็นประโยชน์ด้วย เพราะประเด็นเรื่อง Kotlin คนก็พูดถึงกันเยอะด้วย และงาน meetup น่าจะเหมาะกับการโชว์อะไรโหดๆมากกว่าอ่ะ อีกอย่างขี้เกียจทำ demo ด้วย เพราะสองครั้งที่ผ่านมาที่เป็น speaker ต้องทำ demo ทั้งสองครั้งเลย ครั้งนี้เลยอยากจะชิวๆนิดนึง แบบเอาเรื่องที่ไม่หนักมากแล้วกันงี้
ข้อดีและข้อเสียที่ต่างกัน ระหว่าง Java และ Kotlin
เดี๋ยวหาว่าอวย เดี๋ยวหาว่าแอบมาป้ายยา เริ่มที่ข้อดีก่อนเลย
Null Safety
เคยไหม ที่ต้องมา check ว่าค่าที่ได้รับนั้น มันเป็น null ไหม อาการแบบนี้พบบ่อยใน adapter ทั้งหลาย ตอนเวลาที่เรา check ว่าเจ้า adapter ได้รับ item มากี่ตัว
@Override
public int getItemCount() {
return mItems != null ? mItems.size() : 0;
}
เขียน Kotlin ก็เหลือแค่นี่เองอ่ะ
override fun getItemCount() = mItems.size
Less code, Less bugs, Read easier
การเขียน Kotlin ทำให้เราเขียนโค้ดต่างๆสั้นขึ้น เช่น class model จะทำให้โค้ดสั้นขึ้นมาก
และเจ้า Kotlin มันจะเปลี่ยนนิสัยของเรา โค้ดอันไหนที่เราไม่จำเป็นต้องใช้มันจะขึ้นสีเทาๆแบบนี้ ให้เราลบออก นี่เป็นตัวอย่างนึง
และยังมีตัวอย่างอื่นๆอีก ติดตามชมจ้า
Similar with Swift
ด้วยความที่มี syntax อะไรหลายๆอย่างคล้ายกัน ระหว่าง Swift กับ Kotlin ทำให้ iOS Developer และ Android Developer สามารถอ่านโค้ดซึ่งกันและกันได้เข้าใจมากขึ้นนั่นเอง อันนี้ยืนยันจากคนในทีมเลยทีเดียว ตัวอย่างเช่น
Low Learning Curve
ถ้าเคยเขียน Android หรือเขียน iOS ด้วย Swift สามารถเรียนรู้ได้ไม่ยาก จากสาเหตุข้อข้างบน และก็ไม่ได้ต่างจากการเขียนแอปด้วย Java เท่าไหร่
Free Lambda
ใน session How to Kotlin? ใน Google I/O 2018 ได้กล่าวไว้ว่า
Mindset อย่างนึงที่เปลี่ยนไปสำหรับคนที่เขียน Java แล้วย้ายไป Kotlin คือ เราสามารถใช้เจ้า lambda ได้ตามใจชอบเลย
ซึ่งเราสามารถใช้เจ้านี่มากขึ้นกว่าใน Java แน่นอน
Work together with JAVA
สามารถเพิ่มเจ้า Kotlin ใน project เก่าๆได้เลย และสามารถทำงานร่วมกันได้ ไม่ต้องเสียเวลามานั่งปั้นโค้ดใหม่ใน project เดิม และนอกจากจะทำงานร่วมกันกับ Java ได้แล้ว ยังทำงานร่วมกันกับ js ได้อีกด้วยนะ ทีนี้สาย web front-end ก็น่าจะสบายขึ้น(มั้ง)
Tool Support
สาเหตุที่ทำงานด้วยกันได้ เพราะ tool ที่มีสามารถรองรับ Kotlin ได้หล่ะสิ เพราะทาง Android ก็ support ทั้งสองภาษานั่นเอง
แล้วก็ทาง Google ออกอะไรใหม่ๆมา support Kotlin ด้วยนะ
แล้วเราจะเริ่มต้นยังไงดีหล่ะ
ก่อนอื่นต้องลง Android Studio ก่อนสิ ลงเวอร์ชั่น 3.0 ขึ้นไปนะ ซึ่งเข้าใจว่า Android Developer ลงเวอร์ชั่นล่าสุดแล้วใช่ไหม
จากนั้นลง plug-in ที่ชื่อว่า Kotlin แบบนี้
ลงเสร็จ restart Android Studio ซะ ก็ใช้ได้แล้วจ้า
ลอง re-check ดู ต้องได้แบบนี้นะ
ถ้าอยากอ่านวิธีการลงแบบละเอียด จิ้มที่นี่เลย
การนำไปใช้ใน project เพิ่มเจ้านี่ลงไปใน build.gradle ของ project
buildscript {
....
dependencies {
...
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.30"
}
}
และใส่ dependency และ plug-in ของ Kotlin ลงใน build.gradle ของ module app
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
...
dependencies {
...
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.40"
...
}
...
หรือจะเพิ่มแบบนี้ก็ได้นะ
หลายๆคนคงเคยใช้แล้วเนอะ แปลง Java เป็น Kolin ได้ด้วย แบบนี้
สำหรับโปรเจกใหม่ๆ ถ้าเครื่องเราลง plug-in แล้ว ติ๊กทีเดียวได้เลย
ความแตกต่างระหว่าง Java และ Kotlin
ไม่เป็นการเสียเวลา ใส่แว่นดำแล้วเขียนโค้ดไปด้วยกันเลยจ้าาาาา
ประเภทตัวแปร หลายๆคนจะทราบว่ามี mutable และ immutable แต่ๆ มันไม่ใช่ซะทีเดียวนะ งั้นแบ่งใหม่ๆ แล้วกัน
- mutable : สามารถเปลี่ยนค่าตัวแปรได้ เช่น
var a = 1
ถ้าเราไม่อยากใส่ค่ามันไว้ก่อน สามารถใช้แบบนี้ได้lateinit var a : Int
แล้วไปใส่ค่าให้มันทีหลัง ตัวแปรชนิดนี้จะมาพร้อมget()
และset()
- read-only variable : ไม่สามารถเปลี่ยนค่าได้ จะเหมือนเจ้า final เลย อารมณ์เดียวกันกับ const เช่น
val pi = 3.14
แต่เจ้า const จริงๆ คือconst val pi = 3.14
ซึ่งตัวแปรชนิดนี้เราสามารถใส่ค่ามันได้แค่ครั้งแรกครั้งเดียว จากนั้นจะใส่ค่าทับไม่ได้ เป็นตัวแปรชนิดอ่านอย่างเดียวเนอะ แน่นอนมาพร้อม get()
และมีอีก type นึง ไม่สิ เหมือนเป็น sub-set ของ mutable type มากกว่า คือ Nullable type คือ ตัวแปรนั้น สามารถเป็น type หรือ null อย่างใดอย่างหนึ่งได้ เช่น var b: String?
Properties and Fields: Getters, Setters, const, lateinit - Kotlin Programming Language
การเขียน class Activity/Fragment ต่างๆ
ด้วยความที่ Kotlin โค้ดมันจะสั้นมาก ดังนั้นเจ้า override ที่ไม่ใช้ มันจะเป็นตัวสีเทา ดังนั้น ใส่ที่จำเป็นต้องใช้เท่านั้น จึงทำให้โค้ดสั้นมาก แบบนี้
ใน fragment เราใช้แค่ 2 อันหลักๆ คือ
onCreateView
: ไว้ใส่ตัว layout ของ fragmentonViewCreated
: ตรงนี้เราจะใส่การทำงานอะไรก็ตามแต่ใน fragment ได้เลย เย้
การใช้ Kotlin KTX
ปกติเราจะอ้างอิงแต่ละตัวใน layout ด้วย id ดังนั้น ใน Java จะใช้ findViewById
Button button = findViewById(R.id.button);
button.setOnClickListener({
@Override
public void onClick(View view) {
// Make it happen
}
});
หรือบางคนอาจจะใช้ Butterknife (ซึ่งน่าจะ obsolete ไปแล้ว)
@BindView(R.id.button) Button button;
@OnClick(R.id.button) void clickTodoSth() {
// Make it happen
}
หรือจะใช้การ binding แนว MVVM (ซึ่งเราคิดว่าน่าจะมีคนใช้ท่านี้น้อย ณ ตอนนี้นะ)
แต่สำหรับ Kotlin ใช้ KTX เนอะ ในการระบุ id ของแต่ละตัว โดยไม่ต้องใช้ค่าข้างบนเวลา แค่ import layout เข้ามาใน class เท่านั้นเอง
import kotlinx.android.synthetic.main.<layout_name>.*
button.setOnClickListener {
// Make it happen
}
ปล. เรียก id ข้าม layout ไม่ได้นะจ๊ะ เพราะมันไม่รู้จักว่าเราเรียกอะไรมากงี้
Model Class
อันนี้พูดแบบรวบๆนิดนึง ปกติเราสร้างก้อน Object ก้อนนึงมีส่วนประกอบอะไรบ้างหล่ะ ชื่อตัวแปร ประเภทตัวแปร getter setter แบบนี้
public class User {
private String name;
private int age;
public User(String n, int a) {
name = n;
age = a;
}
public int getName() {
return name;
}
public int getAge() {
return age;
}
}
แต่เจ้า Kotlin ทำให้ไฟล์ model class ของเราสั้นมาก สั้นสุดๆ แบบนี้
class User(val name: String, val age: Int)
เราไม่จำเป็นต้องไปใส่ getter/setter แบบเปลืองๆแบบนั้นเลยเนอะ
Model class with Parcelable
ที่ใส่เจ้า Parcelable ก็เพื่อรับก้อน object data จาก API มาได้อย่างครบถ้วนสมบูรณ์ ซึ่งขอแปะรวบทั้งของ Java และ Kotlin ซึ่งฝั่ง Kotlin ก็โค้ดสั้นกว่าอะเนอะ
เพิ่มเติมอ่านได้ที่นี่จ้า
Companion Object
เนื่องจากเจ้า Kotlin ไม่มี static ดังนั้นท่าปกติที่เราส่งค่าจาก activity หรือ fragment ไปยัง fragment เราจะสร้าง function นึงเพื่อรับค่ามา ซึ่งคิดว่าทุกคนน่าจะใช้ชื่อคล้ายๆกัน คือ newInstance()
public static SampleFragment newInstance(String name) {
SampleFragment fragment = new SampleFragment();
Bundle bundle = new Bundle();
bundle.putString(BUNDLE_GET_STRING, name)
fragment.setArguments(bundle);
return fragment;
}
พอเอาโค้ดเจ้าด้านบนไปก็อปแปะบนไฟล์ .kt ผลลัพธ์ที่ได้เป็นแบบนี้
companion object {
fun newInstance(name: String?): SampleFragment {
val fragment = SampleFragment()
val bundle = Bundle()
bundle.putString(BUNDLE_GET_STRING, name)
fragment.arguments = bundle
return fragment
}
}
วิธีการเรียกใช้ก็แสนจะง่าย แบบนี้
SampleFragment.newInstance("Cherprang")
ทำไมถึงประกาศ function หรือ variable ที่เป็น static ใน Java ใน companion object หล่ะ ?
เพราะว่า เราต้องการให้ class อื่นๆเรียกเจ้า newInstance ได้หล่ะสิ
แล้วมันต่างจาก function ที่เป็น pubilc ไหมง่ะ?
ต่างสิ เพราะว่าเปน fragment class ไง เราไม่สามารถเรียก function ที่เป็น public มาใช้แบบตรงๆได้แบบนี้ ถ้าเป็น class ปกติก็สามารถเรียกใช้ public function ได้เลย
ถ้าสมมุติว่าเราไม่ได้โยนค่าอะไรไปให้มันเลย จะมาแบบสั้นๆแบบนี้
//Java
public static SampleFragment newInstance() {
SampleFragment fragment = new SampleFragment();
return fragment;
}
จะได้เป็น
//Kotlin
fun newInstance() = SampleFragment()
Getter/Setter
แต่ถ้าอยากใส่ getter/setter ต้องทำยังไงดีน๊าาา?
บางอย่างจำเป็นต้องใส่อ่ะ ทำไงดี ตัวอย่างง่ายๆ สมมติว่าเราจะ save ค่าบางอย่างไว้ใน SharedPerferences เราต้องมาใส่ท่านี้ซํ้าแล้ว ซํ้าเล่า ตามจำนวนตัวแปรที่เราใช้
public boolean getIsLogin() {
return preferences.getBoolean(PREFERENCE_KEY_IS_LOGIN, false);
}
public void setIsLogin(boolean isLogin) {
editor.putBoolean(PREFERENCE_KEY_IS_LOGIN, isLogin);
editor.commit();
}
และใน Kotlin ก็ใส่แบบนี้
var isLogin: Boolean
get() = preferences.getBoolean(PREFERENCE_KEY_IS_LOGIN, false)
set(value) {
editor.putBoolean(PREFERENCE_KEY_IS_LOGIN, value)
editor.commit()
}
แรกๆเราก็ใส่ผิดนะ มีหลักการใส่ ดังนี้
ประกาศตัวแปรก่อน จากนั้นใส่คำว่า get หรือ set ลงไป มันจะขึ้นมาเป็นแบบนี้
สำหรับเจ้า set นั้น เอา value มันมาใช้ในปีกกานะเออ อย่าเอาชื่อตัวแปรไปใส่ในนั้นนะ ไม่งั้นมันจะพังไปเลย
constructor
ใน Java เราจะชินตากันกับแบบนี้
class SomethingInTheApp {
public somethingInTheApp(Context context) {
this.mContext = context;
}
...
}
และถ้าเอาไปก็อปแปะแล้วแปลงเป็น Kotlin จะเป็นแบบนี้
class SomethingInTheApp {
constructor(context: Context) {
this.mContext = context
}
...
}
แล้วมันจะขึ้นแบบนี้มา อ่ะลองซะหน่อย
ออกมาจะพบความมหัศจรรย์แบบนี้
class SomethingInTheApp(context: Context) {
...
}
และเราสามารถนำค่าที่เราประกาศ constructor ไปใช้ต่อ โดยสามารถประกาศตัวแปร local เพื่อนำมาใช้ใน class แบบนี้
// Kotlin
class SomethingInTheApp(context: Context) {
private var mContext = context
...
}
สั้นๆอีกตัวอย่างนึง สมมุติว่าเราสร้าง class Animation มาตัวนึง ใครที่อ่านบล็อกเราน่าจะจำได้ จะประมาณนี้
public class AnimationView extends LinearLayout {
...
public AnimationView(Context context) {
super(context);
...
}
public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
...
}
...
}
พอเอามาก็อปแปะจะดูน่าเกลียดมากๆ แถม error เต็มเลย ที่ถูกต้องเป็นแบบนี้
class AnimationView: LinearLayout {
constructor(context: Context) : super(context) {
initialize(context)
...
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
initialize(context)
...
}
}
โดยเราใช้เจ้า constrcutor แทนชื่อ class แล้วเจ้า super ก็จะอยู่หลัง : และถ้าเราอยากให้ทำอะไรบางอย่าง ก็ใส่ปีกกาหลัง super ได้เลย
ถ้าเรามีเจ้า consturctor แค่ตัวเดียวหล่ะ มันจะยุบเหลือแค่นี้
class AnimationView(context: Context): LinearLayout(context) {
init {
initialize(context)
...
}
}
All about class :
รู้สึกว่าประเภทของ class จะมีเพิ่มขึ้นกว่าปกติ ดังนั้น ขอยกอันที่เราใช้บ่อยๆแล้วกัน
- Open Class เหตุเกิดจากการที่เราเริ่มเขียน Kotlin แรกๆ เราทำ BaseFragment class มาตัวนึงมาให้ fragment อื่น แต่เราไม่สามารถ extends BaseFragment ตัวนี้ได้ มันจะขึ้นว่า Can not inherit from final class เพราะว่าตัว class มันเป็น private อยู่ จึงต้องใส่ open ไว้ข้างหน้า เราจึงจะสามารถใช้ BaseFragment และ override function ได้
open class BaseFragment : Fragment() { ... }
Classes and Inheritance - Kotlin Programming Language
- Sealed Class : เป็น class ที่หน้าตามันจะคล้ายๆการสร้าง enum และ sub-class ในเจ้า sealed class นี้ สามารถมีได้หลาย instance และเก็บ state ได้ เอ๊ะ ทำไมคอนเซปมันคล้ายๆ state ใน vuex หรือ redux เลยนะ ตัวอย่าง เช่น Routing ใน Fuel นั่นเอง แหะๆ
sealed class ProfileRouting: FuelRouting {
val PARAM_AUTH = "Authorization"
override val basePath: String
get() = Constant.BASE_PATH
class getProfile(val token: String): ProfileRouting() {
override val method: Method
get() = Method.GET
override val path: String
get() = "/users"
override val params: List<Pair<String, Any?>>?
get() = null
override val headers: Map<String, String>?
get() = null
}
}
Sealed Classes - Kotlin Programming Language
- Data Class : ว่าง่ายๆคือก้อน Object ดีๆนี่เอง ก้อนนี้จะบรรจุค่าต่างๆที่เราต้องใช้ เล่ากันง่ายๆมันก็คือ class model นั่นแหละ เจ้านี่มาเป็น package มาพร้อมกับ
hashCode()
,equals()
,copy()
สามารถหยิบมาใช้ได้เลยจ้า
data class User(val name: String, val age: Int)
Data Classes - Kotlin Programming Language
Listener
เอาแบบง่ายๆ คือ กดปุ่มแล้วทำอะไรสักอย่าง ถ้าแบบเดิมๆจะเป็นอย่างนี้
Button button = findViewById(R.id.button);
button.setOnClickListener( {
@Override
public void onClick(View v) {
//Make it happen
}
});
ถ้าเป็น Kotlin หล่ะ
button.setOnClickListener{
//Make it happen
}
เห็นม่ะ ดูง่ายมากๆเลย เพราะใช้เจ้า lambda ช่วยไงหล่ะ
Override Function
การเรียก Object ตัวนึงที่มีการ override ค่าข้างใน ง่ายๆเลย คือ นาฬิกาจับเวลานั่นเอง เดิมทีเราจะเรียกแบบนี้ใน Java เนอะ
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
โดยเจ้า CountDownTimer
นี้นั้นไซร้ มีการทำงาน 2 อย่างที่เราต้อง customize มัน คือ onTick()
เราให้ทำอะไรระหว่างจับเวลา และ onFinish()
เสร็จแล้วทำอะไรต่อ และถ้า covert เป็น Kotlin จะเป็นดังนี้
object : CountDownTimer(30000, 1000) {
override fun onTick(millisUntilFinished: Long) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000)
}
override fun onFinish() {
mTextField.setText("done!")
}
}.start()
จริงๆเราลองแปลงด้วย plug-in ก่อนก็ได้นะ แล้วจำเอา ถ้าเราพิมพ์มือ จะเริ่มใส่คำว่า object ก่อน แล้วตามด้วยชื่อ object ที่เราต้องการ ใส่ body เปล่า แล้วเคาะ alt + enter ให้ implement member ออกมา ก็ได้แล้วจ้าาาา
Scoping Function
ชื่อทางการของนางอาจจะงงว่าคืออะไร แต่ถ้าบอกว่ามี also, apply, let, it, run, with ก็น่าจะนึกออกว่าคืออะไร สารภาพตามตรง เราเองก็ใช้ไม่ค่อยเป็นนัก งั้นเราขออ่านบล็อกพวกนี้ก่อนแปป
สมมุติคะว่าเราใส่ค่า attribute ต่างๆ บน object ตัวนึง เช่น มีปุ่มนึงที่เปลี่ยนหน้าตาตาม business logic ก็แล้วกัน
button.text = "Press This"
button.isClickable = true
button.background = resources.getDrawable(R.drawable.green, this.theme)
ลองคิดสิว่า ถ้าข้างบนมันเยอะกว่านี้หล่ะ โอ้ยยยย ไม่อยากจะคิด
เจ้า also กับ apply จะมาช่วยในการ set attribute ได้ง่ายขึ้น ซึ่งสิ่งที่เราระบุในนั้นจะมีผลเฉพาะ object นั้นๆเท่านั้น
ท่าแรก apply อันนี้มี this แถมมาด้วย ซึ่งแทน object นั้นๆ แต่ในที่นี้ไม่ต้องใส่ก็ได้เน้อออออ ไม่เหมือนเจ้า also ที่ต้องใส่ it เพื่อแทน object นั้นๆ
button.apply {
text = "Press This"
isClickable = true
background = resources.getDrawable(R.drawable.green, this.theme)
}
แค่ท่าแรกก็ดูสวยงามน่าอ่านมากขึ้นแล้วเนอะ
ท่าสอง also จะมี it มาด้วย ซึ่ง it ก็แทน object นั้นๆ ในที่นี้คือ button นั่นเอง
button.also {
it.text = "Press This"
it.isClickable = true
it.background = resources.getDrawable(R.drawable.green, this.theme)
}
แต่จริงๆ also จะเหมาะกับการให้ object ตัวนั้นทำอะไรบางอย่างเพิ่มกับเรามากกว่าแหะ เช่น
button.apply {
text = "Cannot Press"
isClickable = false
background = resources.getDrawable(R.drawable.red, this.theme)
}.also {
Toast.makeText(context, "gogo~", Toast.LENGTH_SHORT).show()}
แล้ว run กับ let หล่ะเจ้าคะ?
จริงๆเจ้า let ก็สามารถเขียนท่าเดียวกันกับเจ้า also ได้นะ
button.let {
it.text = "Press This"
it.isClickable = true
it.background = resources.getDrawable(R.drawable.green, this.theme)
}
แล้วยังช่วยเรา check null ได้อีกด้วยนะ ตัวอย่างแบบขี้เกียจๆ อย่าง ExoPlayer เราต้องเก็บ state ของ player ก่อนที่เราจะ release player ทิ้งไป ด้วยโค้ดที่แสนจะขัดใจชุดนี้
if (player != null) {
playbackPosition = player!!.currentPosition
currentWindow = player!!.currentWindowIndex
playWhenReady = player!!.playWhenReady
player?.release()
player = null
}
ดังนั้นเราใช้ท่า let ที่แทน condition not null จะได้แบบนี้ ซึ่งทำงานได้ผลเหมือนกัน
player?.let {
playbackPosition = player!!.currentPosition
currentWindow = player!!.currentWindowIndex
playWhenReady = player!!.playWhenReady
player?.release()
player = null
}
ส่วนเจ้ารัน …
เห้ยยย คนละอันแล้ว เจ้า run แอบคล้ายๆเจ้า also ตรงใส่ไว้ข้างหลัง เพื่อนำบางอย่างจาก object นั้นๆ ไปใช้ต่อในคำสั่งอื่นๆ ประมาณนี้ นึกโค้ดไม่ออกหล่ะ
edittext.apply {
text = "username"
...
}.run {
Toast.makeText(context, edittext.text.toString(), Toast.LENGTH_SHORT).show()
}
Condition
สำหรับการใช้ condition ใน Kotlin จริงๆเราจะเขียนพวก if-else if-else-if switch-case ได้นะ แต่เราควรใช้ when นะ
ปกติทั้งใน Java และ Kotlin เขียนโค้ดแบบนี้ได้เนอะ
if (responseCode == 200_OK) {
textResponse.text = "Successful!"
} else if (case == 401_Unauthorized) {
textResponse.text = "Please log-in"
} else if (case == 404_NOT_FOUND) {
textResponse.text = "cannot load data now"
} else if (case == 500_Server_Error) {
textResponse.text = "Internal Server Error"
}
ถ้าเป็น Kotlin ใน Android Studio มันจะขึ้น suggestion ว่า ลองเขียนแบบนี้ดีไหม อะโชะ
when (responseCode) {
200_OK -> textResponse.text = "Successful!"
401_Unauthorized -> textResponse.text = "Please log-in"
404_NOT_FOUND -> textResponse.text = "cannot load data now"
500_Server_Error -> textResponse.text = "Internal Server Error"
}
โหวววววว โค้ดอย่างสั้นอ่ะ
Ternary Operator ชื่อทางการอาจจะไม่คุ้นเคย ถ้าบอกว่าเป็นการเขียนเจ้า short if จะร้องอ๋อทันที ปกติจะเขียนแบบนี้
//Java
itemSize = isTrue ? itemSize : 0;
แต่ใน Kotlin จะไม่สามารถเขียนแบบข้างบนได้นะ มันผิด syntax ต้องเขียนแบบนี้
//Kotlin
itemSize = if (isTrue) itemSize else 0
Null Safety
เนื่องจากเจ้า Kotlin มัน Null Safety ดังนั้นมันจะช่วย handle ความยุ่งยากในการ check null ต่างๆลง แต่ต้องเรียนรู้ syntax เพิ่มนิดหน่อยเพื่อให้ชีวิตง่ายขึ้น
สมมุติโค้ดตัวอย่างเป็นแบบนี้
print(company.department.employee.name)
?
คือเจ้า safe calls
ตามความเข้าใจของเรา คือ ถ้าตัวไหนมีค่าเป็น null เราก็ได้จะ null กลับมา
print(company?.department?.employee?.name)
!!
คือเจ้า not-null assertion operator
ตามความเข้าใจคือ ยืนยันว่าทั้งก้อนไม่ null นะ
ถ้าเป็น null จะเกิดอะไรขึ้นหล่ะ? ก็จะเกิด NullPointerException หรือ NPE หน่ะสิ แอปก็ crash ไปอีกกกก
print(company!!.department.employee.name)
?:
คือ elvis operator ชื่อเรียกมาจากทรงผมของเอลวิสล้วนๆ
การทำงานคือ ดูค่านั้นว่ามีค่าไหม ถ้าเป็น null ให้คืนค่า string ว่างๆตัวนึงออกมานั่นเอง
val s = str ?: ""
Null Safety - Kotlin Programming Language
Loop
มีหลายหลากแบบที่ดูสวยงามกว่า Java และคล้ายๆภาษาอื่นๆที่เราเคยเขียนมา เช่น python แบบนี้
for (i in range) {
print (i)
}
และหลักๆที่เขาใช้กัน มี forEach()
val iterator = (1..3).iterator()
// skip an element
if (iterator.hasNext()) {
iterator.next()
}
// do something with the rest of elements
iterator.forEach {
println("The element is $it")
}
ถ้าอยากได้ index มาด้วยก็ ForEachIndexed()
simpleList.forEachIndexed {
index, element -> println("index = $index, element = $element")
}
Not use many plus string, should use $
จาก session How to Kotlin? จะเห็นได้ยินเขาบอกว่า การบวก string มันเชยแล้ว ใช้ $ ดีกว่า ซึ่งมันคือการอ้างอิงค่าของตัวแปรนั้นๆ
//Java
println("a = " + a + "b = " + b + "c = " + c)
//Kotlin
println("a = $a, b = $b, c = $c")
Collection
สมมุติเราประกาศ array โง่ๆตัวนึงใน Java แบบนี้
String[] member = {"Cherprang", "Music", "Pun", "Jennis"};
ถ้าเอาไป convert ก็จะได้แบบนี้
var member = arrayOf("Cherprang", "Music", "Pun", "Jennis")
สรุปการประกาศตัวแปร array สามารถประกาศโดยใช้ arrayOf() และไม่ต้องใส่ประเภทตัวแปรไว้ใน <> นะ
และเราสามารถใช้ท่าเกือบจะคล้ายกันกับ list (listOf()) และ map (mapOf()) ได้แบบนี้
mapOf(KEY to "value")
listOf(KEY to "value")
Collections: List, Set, Map - Kotlin Programming Language
get array position
อันนี้มาแบบสั้นๆ แบบ Java จะเป็นอย่างงี้
array.get(0).count; //Java
พอเป็นใน Kotlin ก็เขียนแบบง่ายๆไปเลย จบ
array[0].count //Kotlin
สำหรับ library ที่พูดคุยกันกับ API เราจะลองใช้ Fuel ดูไหม
ขอยกไปที่บล็อกนี้แทนนะ
ไม่ใช่ Android Developer แล้วศึกษาภาษา Kotlin ได้ไหม?
ได้สิ เพราะเจ้า Kotlin ทำได้หลายอย่างเลยนอกจากเอาไปเขียนแอนดรอยด์ ดังนี้
- iOS Application
- Embedded System เช่น Raspberry Pi
- Server side เช่น Ktor, Google Cloud และอีกหลายๆตัว
- Website : js, react native, WebAssembly
และอื่นๆอีกมากมายที่ไม่รู้จะใส่ยังไงให้หมดในรูปเดียว
Resource
แน่นอนทุกคนอยากได้แหล่งความรู้ในการศึกษาสิ่งใหม่ๆ เราเลยเตรียมมาให้พร้อม
- Official Website : https://kotlinlang.org/
- อยากลองเขียนแบบยังไม่ลงอะไรที่เครื่องตัวเอง มาที่เว็บนี้เลยจ้า https://try.kotlinlang.org/
- Codelab บางอันก็เป็นภาษา Kotlin นะ ลองทำดู เราเชื่อว่าคุณทำได้ มีเพิ่มหลังงาน Google I/O 2018 เยอะเลย https://codelabs.developers.google.com/
- ในเว็บของ Android Developer ก็มีหัวข้อ Kotlin แยกออกต่างหากด้วย นี่ก็มาหลัง Google I/O 2018 https://developer.android.com/kotlin/
- ถ้าอยากเรียน Kotlin ก็สามารถเข้าไปเรียนฟรีได้ใน Udacity ได้ Kotlin ด้วย ได้ฝึกภาษาด้วย จิ้มสมัครเรียนที่ https://www.udacity.com/course/kotlin-bootcamp-for-programmers--ud9011 หรือลิงค์ตรงที่ https://classroom.udacity.com/courses/ud9011
- จริงๆบทความ Kotlin ใน medium ก็มีมากมาย ถ้าเริ่มเขียน Kotlin แล้วอยากอ่านภาษาไทย แนะนำ BlackLens เลยจ้า #ขายของ
- สงสัยอะไรไปถามในกรุ๊ป Thailand Kotlin Developer ได้นะ
- และสำหรับ Android Developer ทุกคน ควรเข้าไปดู #31DaysOfKotlin นะ
สุดท้าย เราเชื่อว่าพวกคุณทำได้!
แล้วมือใหม่คิดว่ามันยากไปไหมน๊าาาาา เอ้าาา เรามี Cheat Sheet มาให้ดูสักสองอันแล้วกัน เอามาปริ๊นแปะได้
https://fabiomsr.github.io/from-java-to-kotlin/
Reference แบบองค์รวม :
สุดท้าย จงภูมิใจที่ใช้ Kotlin นะ
ไฟล์สไลด์ย้อนหลังจ้า เป็น pdf เนอะ อาจจะมีบางหน้าแอบเกินๆไปบ้าง
ฝากร้านกันสักนิด ฝากเพจด้วยนะจ๊ะ