はじめてのKotlin on Android

本日 5月18日 Google I/Oのキーノートにて、KotlinがAndoirdの開発言語 として正式サポートされ、さらに今度 Kotlinを主要開発言語として 採用していくことが発表されました。

今まで、Kotlinを使ったことがなかったので、 早速試してみました。

part0 Andoird Studioの導入

Kotlinの開発は、Android Studioで行えます。 公式ページから一式をダウンロード・展開して /usr/local あたりに設置しておきます。

/usr/local/android-studio/bin/studio.sh

から起動できます。 毎回スクリプトを呼び出すのは面倒なので

[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=AndroidStudio
Comment=AndroidStudio
Exec=/usr/local/android-studio/bin/studio.sh
Icon=/usr/local/android-studio/bin/studio.png
Terminal=false

こんな感じの AndroidStudio.desktop という名前で保存して

アイコンでメニューバーなどに登録しておきます。

part1 Kotlinサポートの追加

Kotlin用プログラインの追加は簡単でした。 まず、AndroidStudioの Welcomeウインドウで Configure > Plugins を開き、

下部の Install JetBrains plugin から Kotlin を検索すれば すぐに見つかるのでインストールします。

part2 Kotlin準備

現時点ではじめから KotlinベースでAndroidアプリ用のプロジェクト を立ち上げられるような画面は見当たりませんでした。

ただ、Kotlinは自称Javaと100%互換ということで javaのソースコードを Kotlin に変換することができます。

というわけで、まずは普通に従来通り Androidアプリプロジェクトを 立ち上げ、生成される MainActivity.java を kotlin に変換すれば いいみたいです。 javaのソースファイルを選択して 上部メニューの Code > Convert Java File to Kotlin File

で変換できます。

変換できたら

Tools > Kotlin > Configure Kotlin in Project

で依存関係の情報などをプロジェクトに追記してくれます。

ここで Gradle Scrpt の app ファイル先頭に

apply plugin: 'kotlin-android-extensions'

を追加しておいてください。 これを追加すると kotlin から Androidのリソースデータへアクセスする際に いろいろと便利な記法が可能になります。 これを記述しないままそのあたりに転がっているサンプルをコピーすると

Unresolved reference: kotlinx

と import に失敗していまうのでとりあえず書いておけばいいと思います。

part3 ことりんはろわ

準備が終わったのでとりあえずHelloWorld代わりに何か ビルドしてみます。

まずはレイアウトを用意して

import kotlinx.android.synthetic.main.activity_main.*
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main);

        mytext1.setText("hiroumauma @ Canter");
        mybutton1.setOnClickListener {
            Toast.makeText(this, "Kotlin!!", Toast.LENGTH_SHORT).show()
        };

    }
}

ソースコード中の セミコロンは本来不要ですが、C出身プログラマなので 脊髄反射で入力してしまっています…。 まぁ、こんな感じで書いてビルドすると…

おぉ〜 動きました。

ソースコードを見ればわかるようにシンプルに書くのを良しとする 言語みたいです。

Javaなら

TextWidget textWidget1 = findViewById(R.id.mytext1);

textWidget1.setText("hoge");

のようになるかと思いますが 先ほどの

kotlin-android-extensions

が効いている場合

import kotlinx.android.synthetic.main.(レイアウト).*

が使えるようになり ソースコード中に直接 mytext1 mybutton1 を書いて書き換えなどができるみたいです。

逆に Java風に

var text1 = findViewById(R.id.mytext1) as TextView;

text1.setText("test");

とするとコンパイルは通りますがうまく動きません。 Kotlin は NULL に対して厳しい姿勢をとっているので ( ´∀`)<ぬるぽ が発生しないようになっています。 そのために NULLを取りうるのかどうかなどでちょっと記述が変わります。 上記コードは

kotlin.TypeCastException: null cannot be cast to non-null type android.widget.TextView

のラインタイムエラーになります。 Javaの感覚で書くと結構アラートいっぱいになってしまいました。

まぁ初日でまだろくに文法もさらっていないので仕方ありません。 パッと見た感じではJavaのソースコードより随分好感が持てるソース の見た目をしているのでもうちょっと情報が揃ったらちゃんと 覚えたいと思います。

機械変換時のメモ

javaのソースコードが kotlin に変換できるので 勉強がてらに今まで書いた自分のコードをいくつか変換してみました。

例えば ミュージックプレーヤアプリの RootMenuクラスを変換すると 変換はできますが一部赤線が入ります。

Java の

public class RootMenu extends Fragment {

        SectionsPagerAdapter mSectionsPagerAdapter;
        ViewPager mViewPager;

     @Override
     public View onCreateView((LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.menu, container, false);

            mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
            mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
            mViewPager.setAdapter(mSectionsPagerAdapter);
             ・
             ・
             ・
}

こういう書き方の部分は

        SectionsPagerAdapter mSectionsPagerAdapter;
        ViewPager mViewPager;

ここがマズいので赤線が入ります。 曰く"初期化されてない"そうです。

    lateinit internal var mSectionsPagerAdapter: SectionsPagerAdapter
    lateinit internal var mViewPager: ViewPager

変換後 lateinit をつけてやると赤線が消えました。

こんな感じで機械変換でたいていうまく行きますが ちょこちょこと問題が発生するのでちまちま直すと…

Java / Kotlin 混在のコードで普通に動きました。