アプリ作成が中盤に差し掛かると、新規画面を作る際に以前作ったファイルと似たようなファイルをいっぱい作らないといけないとかなりがちですよね。そんなときはTemplateを作って右クリック一発で必要なファイルを作れるようにすると便利です。
ファイル構成
これはActivity + ViewModel + CustomViewの構成のTemplateの例です。追加するpackageを右クリックしてテンプレートを追加する動作で動きます。
.
├── globals.xml.ftl
├── recipe.xml.ftl
├── root
│ ├── res
│ │ └── layout
│ │ ├── activity.xml.ftl
│ │ └── view.xml.ftl
│ └── src
│ └── app_package
│ ├── Activity.kt.ftl
│ ├── ActivityModule.kt.ftl
│ ├── View.kt.ftl
│ └── ViewModel.kt.ftl
└── template.xml
ファイル中身
template.xml
作成時に入力される変数を記載します。この例ではprefixが入力される想定になります。
<?xml version="1.0"?>
<template
revision="1"
format="5"
name="Activity with ViewModel"
description="Templates for building a new Activity with">
<parameter
id="className"
name="Class Name"
constraints="unique|nonempty"
default="Main"
type="string" />
<parameter
id="resName"
name="Resource Name"
constraints="unique|nonempty"
default="main"
type="string" />
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>
globals.xml.ftl
全体で使用される変数を記載します。今回は出力先のフォルダのみを持っています。
<?xml version="1.0"?>
<globals>
<global id="resOut" value="${resDir}" />
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
</globals>
recipe.xml.ftl
globals.xml.ftl
で定義した変数と、 template.xml
で入力された値を使って、具体的に吐き出すファイルを記載します。
<?xml version="1.0"?>
<recipe>
<instantiate from="root/src/app_package/Activity.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}Activity.kt" />
<instantiate from="root/src/app_package/ActivityModule.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}ActivityModule.kt" />
<instantiate from="root/src/app_package/ViewModel.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}ViewModel.kt" />
<instantiate from="root/src/app_package/View.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}View.kt" />
<instantiate from="root/res/layout/activity.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/${resourceName}_activity.xml" />
<instantiate from="root/res/layout/view.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/${resourceName}_view.xml" />
</recipe>
実装ファイル
アプリによって変わってきますが共通化できる部分を全て記載します。一般的には決まりきった初期化処理を記載することになると思います。 ftl
では globals
や template
で定義された変数を使うことができます。
package ${escapeKotlinIdentifiers(packageName)}
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModel
import com.choilabo.todo.R
import com.choilabo.todo.databinding.${className}ActivityBinding
import com.choilabo.todo.di.ViewModelFactory
import com.choilabo.todo.di.ViewModelKey
import com.choilabo.todo.di.get
import dagger.Binds
import dagger.android.support.DaggerAppCompatActivity
import dagger.multibindings.IntoMap
import javax.inject.Inject
class ${className}Activity : DaggerAppCompatActivity() {
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val viewModel by lazy {
viewModelFactory.get<${className}ViewModel>(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<XxxActivityBinding>(
this,
R.layout.xxx_activity
).also {
it.lifecycleOwner = this
it.viewModel = viewModel
}
setSupportActionBar(binding.toolbar)
}
@dagger.Module
interface Module {
@Binds
@IntoMap
@ViewModelKey(${className}ViewModel::class)
fun binds${className}ViewModel(viewModel: ${className}ViewModel): ViewModel
}
}
まとめ
画面を作るごとにいちいちファイルを作るのは時間の無駄ですし、単純なTypo等のミスが発生しやすくなるので、適宜テンプレートを作って更新し続けると効率が良いと思います。
Github上にプロジェクトごと乗せているので興味がある人はご確認ください。
参考