มาตีบวก Android Studio กัน — Final part ; Generate code patterns

Ta Theerasan Tonthongkam
ta tonthongkam
Published in
4 min readJul 17, 2019

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 Templates

ปัญหาคือ — แต่ละทีมมี Code Pattern ที่ไม่เหมือนกันหนะสิ เราสามารถสร้าง Template ที่เหมาะกับทีมต่างๆ ได้

ในตัวอย่างนี้จะใช้ MVVM pattern

ก่อนเราจะเริ่ม Code เรามาดูกันว่าหนึ่ง Feature ต้องมี file อะไรบ้าง

  1. activity_{feature}.xml —View
  2. {feature}Activity.kt — View
  3. {feature}ViewModel.kt — ViewModel
  4. {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 ตัวนี้

ตัวอย่าง folder ที่ถูกสร้าง

2. List ของ file ที่เอาไว้บอก Android Studio ให้รู้ว่านี้คือ Templates

  1. template.xml — เป็น file ที่เอาไว้บอกรายละเอียดของ Template เช่น ชื่อ, minSdk เป็นต้น
  2. recipe.xml.ftl — เป็นตัวกำหนดว่า file ที่จะถูกสร้างให้ไปเอา Template จากไหน และจะถูกสร้างไปที่ไหน
  3. globals.xml.ftl — file สำหรับประกาศตัวแปรที่สำคัญต่างๆ
  4. 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 ตัวคือ

  1. category ค่าของ tag นี้จะเป็นตัวบอกว่า Menu Templates ของเราจะไปที่ไหน
  2. 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.Observer
class ${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.ViewModel
class ${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 ของเราเพิ่มขึ้นมา

ก่อนและหลัง Restart

8. เริ่มสร้าง Template กัน 🚀

  1. เลือก 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 —

--

--