もやもやエンジニア

IT系のネタで思ったことや技術系のネタを備忘録的に綴っていきます。フロント率高め。

Android StudioとKotlinでAndroidアプリを作る

Kotlinとは

導入

  • Android Studioは同じJetBrains製品のInteliJベースで作られているだけあって、プラグインを入れるだけで簡単に導入可能。Preferences -> pluginから以下の2つをインストールして再起動するだけです。なお自分の環境はAndroid Studio 1.4、compileSdkVersionは23、minSdkVersionは16にしてます。
    • Kotlin
    • Kotlin Extensions For Android

プロジェクトを作ってJavaのコードをKotlinに変換する

  • 適当にBlankActivityだけ追加したプロジェクトを作ります。そうするとこんなActivityが出来ますね。
package me.rei_m.kotlinsample;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
  • プロジェクトツリーにappがフォーカスされている状態でメニューバーからcodeを選ぶと一番下にConvert Java File to Kotlin Fileが追加されていているのでこれを選択します。すると、Kotlinへのコンバートが開始されます。
  • コンバートが完了するとMainActivityはこのように生まれ変わり、拡張子も.ktになります。ハイライト効かないのでみづらいですね。。。早速、valが見えているあたり、Scalaに近い雰囲気を感じます。
package me.rei_m.kotlinsample

import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.View
import android.view.Menu
import android.view.MenuItem

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar = findViewById(R.id.toolbar) as Toolbar
        setSupportActionBar(toolbar)

        val fab = findViewById(R.id.fab) as FloatingActionButton
        fab.setOnClickListener(object : View.OnClickListener {
            override fun onClick(view: View) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show()
            }
        })
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        val id = item.itemId

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true
        }

        return super.onOptionsItemSelected(item)
    }
}
  • 次にメニューのTools -> Kotlin -> Configure Kotlin Projectを選択してそのままOKを押します。

f:id:Rei19:20151017201814p:plain

  • するとbuild.gradleにKotlinでビルドするための設定が追加されるので、この状態でビルドをかけて実行します。

f:id:Rei19:20151017204542p:plain

  • 動きました!
  • 次にKotlin Extensionを使うための設定を追加します。build.gradleを開いてdependentciesにextensionsを追加します。
buildscript {
    ext.kotlin_version = '0.14.451'
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" <- これを追加
    }
}
  • そしてMainActivity.ktを開いてimportを追加します。syntheticから後ろはxmlの名前です。
import kotlinx.android.synthetic.activity_main.*
import kotlinx.android.synthetic.content_main.*
  • これで何ができるようになるかというとfindViewByIdを使わなくてもViewのコンポーネントを参照できるようになります。content_main.xmlTextViewのテキストをActivityから書き換えてみましょう。参照するためにはIDが必要なのでxmlを開いて適当にTextViewにidを追加します。ここではhelloとしています。
  • MainActivity.ktに戻り、findViewByIdを使っているところを書き換えてみましょう。
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // val toolbar = findViewById(R.id.toolbar) as Toolbar
        // setSupportActionBar(toolbar)
        setSupportActionBar(this.toolbar)

        // val fab = findViewById(R.id.fab) as FloatingActionButton
        // fab.setOnClickListener(object : View.OnClickListener {
        this.fab.setOnClickListener(object : View.OnClickListener {
            override fun onClick(view: View) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show()
            }
        })

        // TextViewを書き換える処理を追加
        this.hello.text = "Hello Kotlin !!"
    }
  • 今までfindViewByIdを使っていたところはimportしたことでthisから参照できるようになりました。わかりやすくthisを書いてますが、もちろん無くても動きます。これでビルドして動かしてみましょう。TextViewの表示が変わったはずです。

f:id:Rei19:20151017210329p:plain

  • まだReferenceを読んでいる途中ですが、Javaで書くよりだいぶ簡潔に書ける印象です。しばらく触ってみて既存の資産の使い方など確かめながら何か作ろうかと思います。

追記

  • 早速書き始めたらいきなりExtensionが原因でこけた。。。下のようにViewに追加するとクラスが見つからないと言われて死にます。
    <AppCompatButton
        android:id="@+id/open_hogehoge"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="なんか開く" />
  • AppCompatButtonをフルパスで指定したらビルド通りました。Support library系のコンポーネント使うときは注意しないといけないですねー
    <android.support.v7.widget.AppCompatButton
        android:id="@+id/open_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Open sample of listView" />