6回にわたり続いてきた本連載も今回で最終回です。今まで解説してきた内容をふまえて、
はじめに
Kotlinは、
開発環境構築
連載第2回で紹介した開発環境の1つに、
Android Studioを起動した状態で、
KotlinでAndroid開発を始める
まずはPhone用のプロジェクトを新規作成します。<プロジェクトルート>/app/
が生成されているはずですMainActivity.
ファイルを開きます

メニューからMainActivity.
に記述されているJavaコードが自動的にKotlinコードに変換され、

次に、


最後に、 KotlinでAndroid開発を始めると、 KotlinはJavaとの相互運用性が高いです。JavaコードをKotlinで呼び出すのがすごく簡単です。 リスト2ではクリック時のアクションを関数リテラルで表現してリスナ登録しています。参考までにJavaで書き直したものをリスト3に示します。 既存の型にメソッドを生やせる拡張関数がすごく便利なことは第5回で解説しました。この拡張関数を駆使してAndroid標準のAPIを使いやすく改造してみましょう。 まずはシンプルな例としてトーストを挙げます。リスト4のようなコードを書きました。この拡張関数 もう1つ面白い例を紹介します。リスト5では、 呼び出し側のコードはどのようになるか想像できますか? すでに取得しているプリファレンス まずリスト5の拡張関数 この このような拡張関数、 それからリスト5の2つの拡張関数 最後にリスト6を見てください。 KotlinでのAndroid開発をより快適にしてくれるライブラリやツールを紹介します。 Kotter KnifeはView Injectionライブラリです。頻繁に登場する 導入は簡単です。リスト7のようにbuild. 導入後、 これを可能にしているのは各ビューのプロパティの宣言時に 次に紹介するのはJetBrainsにより開発されているライブラリ、 Android開発では通常、 まずは非常に簡単な例をご覧入れましょう。リスト9では、 Kotlinコードですので、 拡張関数 肝心の導入方法ですが、 最後に紹介するのはKotlin Extensions for Androidというツールです。モチベーションとしてはKotter Knifeと同じく 簡単な具体例を示します。リスト12は リスト13では、 Kotlin Extensions for Androidを導入するには、 Android Studioにプラグインを入れるだけで、 ボタンのクリックリスナのような、 便利なライブラリ・ 全6回に及ぶKotlin入門連載、 Kotlinでみなさまのプログラミングが少しでも快適に、 2022年8月18日発売/app/
ディレクトリを作成し、MainActivity.
ファイルを/app/
からそこへ移動して完了です。これでAndroid開発を始められます!MainActivity.
をリスト1のように編集して、public class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
"Kotlin".hello()
}
fun String.hello() {
val msg = "Hello, $this!"
Toast.makeText(this@MainActivity, msg, Toast.
LENGTH_SHORT).show()
}
}
Kotlin活用のアイデア
関数リテラルでイベントリスナ
View
クラスのメソッドsetOnClick Listener(View.
の例を考えます。ビューのクリック時のアクションを登録するこのメソッドですが、View.
というインターフェースで表現されています。このインターフェースはfun onClick(v: View): Unit
というメソッドを1つだけ持ちます。このように抽象メソッドをただ1つ持ったインターフェースを引数に取るメソッドに、(View) -> Unit
型の関数をView#setOnClickListener(View.
の引数として渡せるということです。button.setOnClickListener {
Log.d(TAG, "Clicked")
}
// Javaコード
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Clicked");
}
});
拡張関数で便利APIを作る
toast
により、Context
のサブクラス内、Activity
内でトースト表示する際にはtoast("こんにちは")
と記述するだけで済みます。このような記述を得るためだけにBaseActivity
のようなスーパークラスを導入していまいがちですが、BaseActivity
を避けられます。fun Context.toast(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}
fun SharedPreferences.edit(f: SharedPreferences.Editor.() -> Unit) {
val editor = this.edit()
editor.f()
editor.apply()
}
platformName("putLong")
fun SharedPreferences.Editor.put(pair: Pair<String, Long>) {
putLong(pair.first, pair.second)
}
platformName("putString")
fun SharedPreferences.Editor.put(pair: Pair<String, String>) {
putString(pair.first, pair.second)
}
pref
に対してリスト6のようなコードが記述できるようになります。pref edit {
put("id" to 123L)
put("name" to "たろう")
}
edit
を見てください。この拡張関数の役目は、Shared Preferences.
を実行することです。引数として受け取る関数f
の中で実際に編集が行われ、f
の呼び出しのあとにapply
を呼び出しているだけです。引数f
の型に注目してください。初めて登場する記法です。SharedPreference.
という関数型です。() -> Unit
だけであればSharedPreference.
は、f
は、SharedPreference.
なメソッドなのです!f
は単なる関数ではなく、editor.
のように呼び出しているのはそのためです。editor
がレシーバとなりf
を呼び出しています。f
の型を(SharedPreference.
として、f(editor)
と呼び出せば機能としては同じことができます。しかし呼び出し側it.
のようにレシーバをf
がSharedPreference.
の拡張メソッドであることでput("id" to 123L)
のようにレシーバを省略することが可能になります。put
についてです。この2つの関数は、Pair
を引数に取ります(説明のためにわざとらしくそうしています)。クラスPair
はその名のとおり組、Pair
の第1要素をキー、put
は同名ですが、Pair<String,String
とPair<String, Long>
で引数の型が異なります。Kotlinではこれを区別できますが、platformName
アノテーションを付けて、put
の引数を"id" to 123L
と記述しています。これはPair
リテラルです。と言うとわかりやすいですが少し違います。to
は任意の型に対する拡張関数で、Pair
インスタンスを生成します。"id" to 123L
は"id".to(123L)
ともPair("id", 123L)
とも記述できます。ライブラリ・
Kotter Knife
findViewById
によるビューのマッピング作業から解放してくれるライブラリです。Java用のButter KnifeのKotlin版と言えます。ちなみに開発者はAndroid界隈で名高いdependencies {
// (略)
compile 'com.jakewharton:kotterknife:0.1.0-SNAPSHOT'
}
repositories {
// (略)
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
MainActivity
のプロパティとして各ビュー(nameEditText
とsubmitButton)
を保持しています。onCreate
メソッド内でfindByViewId
メソッドを呼び出してビューのマッピングを行うのが通常の方法ですが、findByViewId
が登場しません。setContent View(R.
を呼び出した後すぐにsubmitButton
に対してクリックリスナを登録しています。class MainActivity : Activity() {
val nameEditText: EditText by bindView(R.id.name_edit_text)
val submitButton: Button by bindView(R.id.submit_button)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
submitButton.setOnClickListener {
val name = nameEditText.getText().toString()
Toast.makeText(this, name, Toast.LENGTH_SHORT).show()
}
}
}
by bindView(ID)
と記述したおかげです。bindView
メソッドはKotter Knifeが提供するAPIです。プロパティ宣言のあとにby
と記述しているのはKotlinのDelegated Propertyという機能を使うためです。詳細は割愛しますが、Anko
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
verticalLayout {
button("Click me!") {
onClick {
toast("Hello")
}
}
}
}
}
class MainActivity : Activity() {
override fun onCreate(savedInstanceState:
Bundle?) {
super.onCreate(savedInstanceState)
val button = createLayout()
button.setOnClickListener {
toast("Hello")
}
}
}
fun Activity.createLayout(): Button {
var button: Button? = null
verticalLayout {
// ボタンのテキストとしてリソースIDも指定できる
button = button(R.string.click_me) {
// ボタンのテキストサイズを指定
textSize = 24f
}.layoutParams {
// マージンを指定
margin = dip(20)
}
}
// ボタンを返す
return button ?: throw AssertionError()
}
createLayout
で、dependencies
に追記するだけです。とても面白いライブラリですのでぜひ使ってみてください。compile 'org.jetbrains.anko:anko:0.6.2-15'
Kotlin Extensions for Android
findViewById
の排除です。しかしKotlin Extendions for Androidはさらに一歩進めて、activity_
という名前のレイアウトファイルです。そして、MainActivity
の定義がリスト13です。<RelativeLayout xmlns:android="http://schemas.
android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/helloButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"/>
</RelativeLayout>
package com.taroid.sample
import android.app.Activity
import android.os.Bundle
import android.widget.Toast
import kotlinx.android.synthetic.activity_main.helloButton
public class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
helloButton.setOnClickListener {
Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show()
}
}
}
onCreate
内でいきなり登場するhelloButton
に対してクリックリスナを登録しています。Kotter Knifeのときと異なり、helloButton
はプロパティに宣言されていなければDelegated Propertyも使用されていません。このhelloButton
、MainActivity
内で使えるようにしています。自動生成されるビューの完全な名前を一般化するとkotlinx.
」buildscript {
// (略)
dependencies {
// (略)
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
}
}
まとめ
Context
を引数に取るような便利メソッドの定義の際には、Context
に対する拡張関数とすれば、おわりに
本誌最新号をチェック!
Software Design 2022年9月号
B5判/
定価1,342円
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識
OSSソースコードリーディングのススメ
企業のシステムを支えるOSとエコシステムの全貌
今さら聞けないSSH
MySQLで学ぶ文字コード
新生