มาตีบวก Android Studio กัน — Final part ; Generate code patterns
Android studio ถูกสร้างขึ้นมาเพื่อทุ่นแรงนักพัฒนา Android Aplication อย่างเราๆ แน่นอนว่าการเขียน Android มี Boilerplate ค่อนข้างสูง~~~~~ แต่ตัว Android Studio เองก็มี Feature ที่ช่วยให้เราขี้เกียจได้นั้นคือ
Live template
File Template
จากตัวอย่างข้างต้นเราทำได้แค่ Gen โค้ด เป็นส่วนๆ หรือเป็น File ไป — ในการทำงานจริง เราต้องมี Code structure/ code pattern — บางครั้งการจะสร้าง Activity 1 อันเนี่ย ต้องสร้าง file 5–10 files กันเลยทีเดียว และทุกๆ อย่างมักจะเป็น patterns และมี code ซ้ำๆ กันค่อนข้างเยอะ จะมานั้ง Create ทีละ class ก็จะขยันเกินไป
แล้วเราจะสร้าง Code Auto Generate แบบหลายๆ file ได้มั้ย?
ทำได้ และทำได้มานานแล้วด้วย Android Studio ก็มี files templates มาให้อยู่แล้ว เราสามารถไปที่เมนู File → New → Activity → …
ปัญหาคือ — แต่ละทีมมี Code Pattern ที่ไม่เหมือนกันหนะสิ เราสามารถสร้าง Template ที่เหมาะกับทีมต่างๆ ได้
ในตัวอย่างนี้จะใช้ MVVM pattern
ก่อนเราจะเริ่ม Code เรามาดูกันว่าหนึ่ง Feature ต้องมี file อะไรบ้าง
- activity_{feature}.xml —View
- {feature}Activity.kt — View
- {feature}ViewModel.kt — ViewModel
- {feature}.kt — Model
มาเริ่มเขียน template กัน
1. ไปยัง Directory ของ templte
Window
{ANDROID_STUDIO_PATH}/plugins/android/lib/templates/other/
Mac
/Applications/Android Studio.app/Contents/plugins/android/lib/templates/other/
จากนั้นให้สร้าง folder สำหรับ Template ตัวนี้
2. List ของ file ที่เอาไว้บอก Android Studio ให้รู้ว่านี้คือ Templates
- template.xml — เป็น file ที่เอาไว้บอกรายละเอียดของ Template เช่น ชื่อ, minSdk เป็นต้น
- recipe.xml.ftl — เป็นตัวกำหนดว่า file ที่จะถูกสร้างให้ไปเอา Template จากไหน และจะถูกสร้างไปที่ไหน
- globals.xml.ftl — file สำหรับประกาศตัวแปรที่สำคัญต่างๆ
- root/folder — Template code จะถูกใส่ไว้ในนี้
3. มาเริ่มสร้าง template.xml
<template
revision="1"
name="MVVM Template Activity"
description="Creates a new MVVM classes">
<category value="Other"/>
<parameter id="className"
name="Functionality Name"
type="string"
constraints="class|unique|nonempty"
default="FeatureName"
help="The name of the functionality that requires MVVM"/>
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>
จากโค้ดจะมี tag ที่สำคัญหลักๆ อยู่ 2 ตัวคือ
- category ค่าของ tag นี้จะเป็นตัวบอกว่า Menu Templates ของเราจะไปที่ไหน
- parameter ค่า input ที่จำเป็น ค่านี้จะรอรับจาก User
4. recipe.xml.ftl
เป็น file ที่กำหนดตัวต้นทาง และปลายทางของ Template พร้อมทั้งกำหนดให้เปิด file ที่ต้องการได้
<?xml version="1.0"?>
<recipe>
<instantiate
from="src/app_package/Layout.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/activity_${className
?lower_case}.xml"/> <instantiate
from="src/app_package/Activity.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}Activity.kt" /> <instantiate
from="src/app_package/ViewModel.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}ViewModel.kt" /> <instantiate
from="src/app_package/Model.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}.kt" /> <open file="${srcOut}/${className}Activity.kt"/></recipe>
5.globals.xml.ftl
มาประกาศตัวแปรสำคัญกัน
<?xml version="1.0"?>
<globals>
<global id="resOut" value="${resDir}" />
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
</globals>
6.files template
เรามาสร้าง folder root/src/app_package
ที่มี file ดังนี้กัน
activity.xml.ftl — View
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="viewModel" type="${packageName}.${className}ViewModel"/>
</data>
<LinearLayout
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="${className}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
Activity.kt.ftl— View
package ${packageName}import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observerclass ${className}Activity: AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val contentView = DataBindingUtil.setContentView<Activity${className}Binding>(this, R.layout.activity_${className?lower_case})
val viewModel = this.viewModel { ${className}ViewModel() }
contentView.viewModel = viewModel
bind(viewModel)
}private fun bind(viewModel: ${className}ViewModel) {
viewModel.item.observe(this, Observer { /*TODO: add function here*/ })
}
}
ViewModel.kt.ftl — ViewModel
package ${packageName}import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.ViewModelclass ${className}ViewModel: ViewModel() {
var item = MediatorLiveData<${className}>()
}
Model.kt.ftl — Model
package ${packageName}data class ${className}(val title: String)
7. Restart Android studio
ไปที่ File → New → Other ในส่วนนี้จะมี Template ของเราเพิ่มขึ้นมา
8. เริ่มสร้าง Template กัน 🚀
- เลือก Template ที่เราเพิ่งสร้าง ใส่ชื่อ feature ลงไป → กด finish
2. ตรวจสอบ file ต่างๆ → กด Add
3. ตู้ม!!! 💥 ได้ file อย่างที่ต้องการ
4. ถ้ามี Error ลอง Rebuild เพื่อ run data binding อีกรอบ
Enjoin Coding 👩🏻💻 👨🏻💻
สรุป ✍🏻
การใช้ Feature ต่างๆ ของ Android Studio ที่ช่วยเพิ่ม Productivity ถือเป็นเรื่องที่ดี เนื่องจากเราจะได้ย่นเวลาในการสร้าง boilerplate และใส่ใจกับการสร้าง Application มากขึ้น — อย่างไรก็ตาม Templates ที่สร้างต้องยืดหยุ่นพอที่จะใช้ได้ในหลายๆ สถานการณ์ — เรามา Work smart but not Hard กัน
Thank you
— end of the story —