最近人気のKotlinでViewPagerアプリを作ってみた

こんにちは。今年の夏からAndroidエンジニアとしてpairsのAndroid版を開発しているインターンの仙波です。
本日は最近Androidの新しい言語として人気を集めている「Kotlin」について書こうと思います。

Kotlinでサンプルアプリ

エウレカでは、入社する前にちょっとした課題が出されます。Androidの職種で入社した私の場合、「Dribbble」というデザインサイトのAPIを利用して簡単なアプリを作成するという課題でした。
 
そこで、今回はその課題をJavaからKotlinに変換したアプリを作成しました。
作成したプロジェクトはGitHubに公開しているので、よろしければご覧になってみてください。
 
https://github.com/TakuSemba/DribbbleSampleApp
demo
 
このようなアプリをいつも作成しております。

最近では、電車で寝る人(私)のために、場所を登録する目覚ましアプリをリリースしました。

https://play.google.com/store/apps/details?id=com.takusemba.mapme
MapMe
 
それでは、早速Kotlinについて書きたいと思います。
 

そもそもKotlinとは?

Kotlinとは、IntelliJや各種IDEでおなじみのJetBrains社が中心となって開発を進めているJVM上で動作する言語です。
JVM上で動作する言語は他にClojure、Groovy、Scalaなどもありますが、Kotlinは自由度も高く、文法もシンプルで簡単なプロジェクトやアプリ開発に適した言語です。

導入方法

では、どうやってKotilinでの開発を始めるのか。非常に簡単でKotlinはJetBrains社が開発していることもあり、IntelliJのプラグインとしてKotilinは提供されています。
AndroidStudioを使用している方もIntelliJと同様にしてKotlinのプラグインをインストールするだけでKotlinの開発を始めることができます。

参考 URL

Getting Started with IntelliJ IDEA
Getting started with Android and Kotlin
 
KotlinのPlaygroundもWeb上に存在しているので、Kotlinに触れてみたい方は下記のリンクから試してみてください。
Try Kotlin


 
それでは、Kotlinの魅力を説明していきたいと思います。
 

魅力1: コード量を削減できる

アクセサ (Getter, Setter) がいらない!

Kotlinでは、GetterやSetterのアクセサが内部で自動生成されるため、Javaのように一つ一つ書く必要がありません。
※Javaは慣例として、カプセル化を推奨しているためpublicなインスタンス変数を避けるべきとされています。

// Shot class on Java
public class Shot {
    private String title = "";

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    // Something...
}
// Shot class on Kotlin
public class Shot {
    public var title: String = ""

    // Something...
}

インスタンス変数を直接参照しにいくように見えますが、アクセサが自動生成され、変数にアクセスする場合は全てアクセサを経由することになります。

Viewの参照がすっきりすぎる

Kotlinでは、Kotlin Android ExtensionsというPluginがあり、これを使うとすっきり書くことが可能になります。
通常、JavaでViewを参照すると、以下のようになると思います。

// Java
TextView textView = findViewById(R.id.text_view);
textView.setText("Hello World");

これをKotlinに置き換えると

// Kotlin
text_view.setText("Hello World");

となり、非常に簡潔に書くことができます!

Listenerのセットが簡単

Javaでリスナーをセットすると、以下のようになると思います。

// Java
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d(TAG "button clicked !!");
    }
});

Kotlinでは、第一引数の型をレシーバとして呼び出せるシンタックスシュガーが用意されているため、五行要した記述を一行で書くことができます。
 

// Kotlin
button.setOnClickListener { Log.v(TAG, "button clicked !!") }

 

魅力2: ぬるぽを気にしなくて良い!

Javaでコーディングしているときに気をつけなければいけないのが NullPointerException (通称:ぬるぽ) だと思います。Kotlinを使用するとぬるぽの発生リスクを最大限に減らすことができます。

コンパイル時エラー

理由はKotlinコード内にぬるぽが発生する箇所をコンパイル時にエラーとして吐き出すからです。そのため、Javaと違い実行時にエラーとなってクラッシュすることがありません。(明示的にNullPointerExceptionを発生させる場合は別)

非null型とnull許容型

Kotlinではnullを保持できる変数(null許容型)とnullを保持できない変数(非null型)の二種類が存在します。

// 非null型
var a : String = "abc"
// a = null // nullは代入することができない。
val l = a.length()
// null許容型
var a : String? = "abc"
a = null
val l = a.length() // aがnullになる可能性があるためコンパイルエラー。

では、null許容型への代入はどのようにするのか。

// null許容型
var a : String? = "abc"
a = null
val l = a?.length ?: -1

このようにすると、nullでない時にはa.lengthを、nullの場合には-1を返すことになります。
 

魅力3: Javaとの互換性100%

KotlinはJVM上で動作する言語のため、Javaのコードと共存することができますし、Javaのライブラリをそのまま使用することもできます。
例として、pairsでも使われているretrofitをJavaとKotlinで適用する方法を説明します。まずはJavaからです。

// Interfaceを定義
public interface ShotApi {
    @GET("/shots/?access_token=" + ACCESS_TOKEN + "&per_page=24")
    void fetchShots(@Query("list") String type, Callback<List<Shot>> callback);
}
// エンドポイントやConverterを実装
public class RestClient {
    public static RestAdapter getRestAdapter() {
        return new RestAdapter.Builder()
                .setEndpoint("https://api.dribbble.com/v1/")
                .setConverter(new GsonConverter(new Gson()))
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
    }
}
// APIリクエスト
RestClient.getRestAdapter()
        .create(ShotApi.class)
        .fetchShots(type.getKey(), new Callback<List<Shot>>() {
            @Override
            public void success(List<Shot> shots, Response response) {
                // Do something
            }

            @Override
            public void failure(RetrofitError error) {
                Log.d(TAG, "onError: " + error.getMessage());
            }
        });
}

これをKotlinで適用すると

// Interfaceを定義
interface ShotApi {
    @GET("/shots/?access_token=$ACCESS_TOKEN&per_page=24")
    fun fetchShots(@Query("list") type: String, callback: Callback<List<Shot>>)
}
// エンドポイントやConverterを実装
object RestClient {
    val restAdapter: RestAdapter
        get() = RestAdapter
                .Builder()
                .setEndpoint("https://api.dribbble.com/v1/")
                .setConverter(GsonConverter(Gson()))
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build()
}
// APIリクエスト
RestClient.restAdapter.create<ShotApi>(ShotApi::class.java).fetchShots(type.key, object : Callback<List<Shot>> {
    override fun success(shots: List<Shot>, response: Response) {
        // Do something
    }
    override fun failure(error: RetrofitError) {
        Log.d(TAG, "onError: " + error.message)
    }
})

このように、Javaで書かれたライブラリであっても簡単にkotlin内で使用することができます。
 

魅力4: it(それ!?)

私が最初見たときに「なんだこれ??」と思ったのですが、引数が一つの時はitだけで定義することができます。

例えば以下のような感じになります。

// Kotlin
fun main(args: Array<String>) {
    val numbers = arrayOf(1, 2, 3, 4, 5)

    for (it in numbers)
        println(it * 2)
}
// 出力結果
2
4
6
8
10

 

その他の魅力

文法などがSwiftに似ているので、iOSをやっていてAndroidもそろそろやりたいと思っている方がいれば、Kotlinから勉強しはじめるとAndroid開発に入りやすいのかなと個人的には思いました。
 

最後に

Kotlinでサンプルアプリを作ってみて、簡単なアプリであればKotlinで書くのも全然ありだと思いました。しかし、まだドキュメントやコミュニティーなどが成熟していない点もあり、今すぐに全てKotlinに移行するのはまだ時期尚早かなと思っています。

今後Kotlinがどのように変化していくのか楽しみです!
 
KotlinサンプルApp
https://github.com/TakuSemba/DribbbleSampleApp
 
場所で起こす目覚まし (MapMe)
https://play.google.com/store/apps/details?id=com.takusemba.mapme

eureka Advent Calender 実施中です。Go言語関連を始めとして、大規模サービス特有の事例、Tipsを共有しています!

  • このエントリーをはてなブックマークに追加

Recommend

レイティングアルゴリズム入門

いつも初心を忘れない!デザインの質を確実に上げるための制作フロー