はじめての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 混在のコードで普通に動きました。

コメントを追加する