【Kotlin】BS若手組でAndroidアプリ作ってみた

【Kotlin】BS若手組でAndroidアプリ作ってみた

【Kotlin】BS若手組でAndroidアプリ作ってみた みなさんお久しぶりです。約1年半ぶりの登場になりましたがっきーです。最近困ったことが起きています。
そう、Java11のリリースによる有償化です。
モバイルアプリはもちろん、家電製品にまで搭載されているJavaですが、今回のJava有償化に伴う影響はかなり深刻です。
バージョンアップをしないという手もありますが、セキュリティ上不安が残ります。
「でも有償版へバージョンアップはしたくない!」というジレンマを抱える方は多いのではないでしょうか。
そこで、今回はJavaに代わる新たな言語Kotlinの紹介をBS事業部若手組が作成したToDoリストのAndroidアプリ開発を通して説明します!

挑戦者はコチラ!


下の動画はがっきー作のToDoリストのデモです!生暖かい目でどうぞ。。

実際にKotlinに触れてみての所感

Android経験者であればKotlinのほうがJavaよりもソースコードが簡素化できることの恩恵を実感できます。
たとえAndroid未経験者でもAndroidアプリをKotlinで開発することは苦に感じません。 JavaからKotlinへ移行するには少ない学習コストで実現できるでしょう。

Kotlinの便利ポイント

ここからはKotlinの特徴やJavaとの違い、便利な点をポイントを絞って紹介します。

1.Ankoについて

がっきー
Ankoはメリット沢山!
KotlinはAndroidの画面をデザインするために、DSLとしてAnkoライブラリを提供しています。
通常AndroidでのUI定義はXMLで行いますが、Ankoによりソースコード内に簡潔に記述できるようになります。
Ankoを使う利点としては以下が挙げられます。

  • ソースコード内に記述できるので、型安全が保障される
  • XMLを使わないのでCPU時間を短縮できる
  • フラグメントを関数化すればコードの再利用ができる
  • こんな便利機能使わない手はありません。ちなみに、ライブラリの導入にはgradleプロジェクトに1、2行追加するだけです。

    2.Kotlinにおける関数

    ちあき
    Javaよりもシンプルに記述可能!null安全が保障されてるのも良いです。
    Kotlinを扱うにあたり、Javaとの違いを感じることができる点として関数が挙げられます。Kotlinでは、関数の引数に初期値を与えることができます。これを利用することで、コードを簡略化できます。
    例えば、各タスクが件名・詳細を持つToDoリストで、それぞれに入力値が無かった場合には、
    件名に”件名を入力しましょう”
    詳細に”やることを入力しましょう”
    と表示させたい場合、Javaでコードを書くと、こんな感じになるかと思います。
        public static void registTask(String title, String detail) {  
             // 引数がnullだった場合、変数の初期値を設定する  
             if(title == null || title == "") {  
                 title = "件名を入力しましょう";  
             }  
             if(detail == null || detail == ""){  
                detail="やることを入力しましょう";  
             }  
             // 処理内容  
             System.out.println(title + ":" + detail);  
         }  
    

    この場合、メソッドを呼ぶ時に➀や➁のように引数を渡せば、意図通りに初期値を設定して出力してくれます。
        registTask("今日やること", "Javaでコード書く");    // ➀
        registTask("", null);    // ➁  
    

    出力結果:
        今日やること:Javaでコード書く    // ➀  
        件名を入力しましょう:やることを入力しましょう    // ➁  
    

    しかし、➂のように引数を渡さなかった場合、エラーが出てコンパイルが通りません。
        registTask();    // ➂  
    

    エラーメッセージ:
        registTask(String, String) は引数 (String) に適用できません 
    

    Javaでは、引数の初期値を設定する場合でも、結局空文字やnullといった引数が必要です。 では、Kotlinで同じ動作をするようにコードを書いてみましょう。
        fun registTask( 
             title    :String = "件名を入力しましょう",   
             detail    :String = "やることを入力しましょう" 
             ) :String {   
             // 処理内容  
             return "${title}:${detail}" 
             }  
    

    これで、関数のコール時に引数があった場合はその引数を、なかった場合は引数の初期値を使って処理をすることができます。下記の➃と➄は、両方ともエラーにならずコンパイルできます。
        registTask("今日やること","Kotlinでコード書く")     // ➃  
        registTask()    // ➄  
    

    出力結果:
        今日やること:Kotlinでコード書く     // ➃  
        件名を入力しましょう:やることを入力しましょう    // ➄    
    

    ところで、例えば下記のような、引数の多い関数の場合はどうでしょうか。
        fun registDetailedTask( 
            title    :String = "件名を入力しましょう",   
            detail    :String = "やることを入力しましょう", 
            place    :String = "場所を入力しましょう", 
            date    :String = "日時を入力しましょう", 
            mail    :String = "通知先を入力しましょう") { 
            // 処理内容 
            println("${title}:${detail}, 場所:${place}, 日時:${date}, 通知先:${mail}") 
        } 
    

    「件名と場所には引数の値を、それ以外には初期値の値を設定したい」といった場合は以下のように書くことができます。
        registDetailedTask("明日やること", "新宿中央公園")    // ➅ 
        registDetailedTask(place = "新宿中央公園", title = "明日行く場所")    // ➆ 
    

    出力結果:
        明日行く場所:新宿中央公園, 場所:場所を入力しましょう, 日時:日時を入力しましょう, 通知先:通知先を入力しましょう    // ➅ 
        明日行く場所:やることを入力しましょう, 場所:新宿中央公園, 日時:日時を入力しましょう, 通知先:通知先を入力しましょう    // ➆ 
    

    このようにKotlinの特徴として、Javaよりもシンプルに記述でき、null安全が保障されている点が挙げられます。

    3.Realmとは

    おに
    単純なデータ構造だから性能劣化が起こりにくいです。
    モバイルアプリの開発におけるデータベースの代表としてSQLiteが挙げられます。しかし、今回のアプリの開発においては、Realmというデータベースを使用しました。
    RealmとはSQLiteの置き換えとして開発されたオープンソースライブラリであり、モバイル向けデータベースの1つです。
    SQLiteとの大きな違いとしては、SQLを記述せずにデータベースの作成、データの格納・取得、変更、削除を行うことができる点になります。
    図で示します。例えば以下のようなテーブルをDBに保存するとします。
    Id Name
    1 ソーダ



    <SQLiteの場合>

    Drinkクラスオブジェクト

    Id Name
    1 ソーダ
    sqlite矢印1

    SQL

    sqlite矢印2
    ドリンクテーブル▲データ受け渡しの図 -SQLiteの場合-


    SQLiteの場合、上記のような形でデータの受け渡しが行われます。オブジェクトにて変数に格納した値をSQL文内に渡し、
    そのSQLを実行することでデータベースに格納されます。 またデータを取得する際には、あらかじめオブジェクト内に変数を用意し、その変数に対して格納する処理が必要になります。


    <Realmの場合>

    Drinkクラスオブジェクト

    Id Name
    1 ソーダ
    sqlite矢印1
    ドリンクテーブル▲データ受け渡しの図 -Realmの場合-


    Realmであれば、オブジェクト内にデータ操作を行う記述をすることで、データの受け渡しが可能になります。SQLiteと異なり、SQLを使用せずにデータを渡すことができます。
    ちなみに、RealmのようなオープンソースソフトウェアのことをNoSQLと言います。例えば、Drinksテーブルを作成し、そのテーブルに対してInsertしようとする場合、以下のコードとなります。
    まず、テーブルを以下処理で作成します。 前提として、realmプロジェクトをインポートしているとします。
        open class Drinks : RealmObject(){
        var name : String? = null
        var stock : Int -O
        }
    

    上記処理によって「Drink」テーブルが作成され、「name」カラムと「stock」カラムが作成されたことになります。 次に作成した「Drink」テーブルに対して、「ソーダ」レコードを追加します。
        realm.beginTransaction()
        realm.create.Object().apply{
        stock-5
        realm.commitTransaction()
    

    Realm.beginTransaction()メソッドでトランザクションを開始し、追加しています。ただし、もしも例外が発生し、データが正常に追加されない場合を考えると、
    上記処理の中にはcancelTransactionメソッドは実装さえれていないため、リスクヘッジされていない処理となっています。
    そのため、トランザクションをキャンセルする処理が必要になります。キャンセル処理を実装する一例としては以下になります。
        realm.executeTransaction{
        stock-5
    

    上記処理内には明示的にcancelTransactionは記述されていませんが、executeメソッドを使うことで、cancelTransactionを自動的に呼び出してくれます。
    また、executeメソッドを使うメリットとしてはbeginTransactionとcommitTransactionも合わせて呼び出してくれるため、beginメソッドとcommitメソッドを分ける必要性がない場合は、Executeを使う方が良いと思います。
    最後にレコードが追加されているかを確認するために、以下処理を実行します。
        var drinks = realm.where=
        .contents("name" , "Y
        .findAll()
    

    .findAll()を使うことで、「name」カラムのレコード内に「ソーダ」が追加されているかを確認しています。
    今回の場合1レコードのみですが、findAllメソッドの戻り値はList配列であるため、複数レコードの取得も可能です。
    このように、SQLの記述なしにテーブルのCreateやレコード追加が可能なため、SQL知識の習得をせずともデータのやり取りが可能になります。
    ただしSQLiteと比較した場合、複雑なデータ構造は苦手なため、単純なデータの取り扱いに向いている形になります。
    また、データ構造が単純であることで、データが肥大化したとしても、性能劣化が起こりにくいというのも特徴です。
    SQLiteのようなRDBMSとRealmのようなNoSQLを使い分けることにより、性能劣化が起こりにくいアプリケーションを制作できると思うので、ぜひ試してみてください。

    4.ListViewとAdapterとは?

    かっしー
    簡単にアダプタを利用できるのもKotlinを使用するメリットですね。
    Androidアプリ開発で欠かせないものの中でListViewが挙げられます。おさらいになるかと思いますが、ListViewとは一体どんなものでしょうか。コチラの図を見てください。

    リストビュー図1▲リスト表示されているタスク


    例えば、このように「スマホの画面で上から順にタスクを表示させたい」とします。これをリスト表示といいます。
    このリスト表示をさせるためのクラスとして用意されているのが、ListViewクラスです。
    ListViewクラスを実装することで、画面に、上図のようにリスト表示ができます。
    ListViewの実装自体は、AndroidStudioのデザイン画面から、パレットで「ListView」で検索して出てきた「ListView」を画面上にドラッグ&ドロップすることで画面に追加できます。
    下記は「ListView」をドラッグ&ドロップして画面に配置してリストを8個に追加したものです。

    リストビュードラッグドロップ▲「ListView」を画面上にドラッグ&ドロップ


    後は、この画面に紐づくActivityクラス側で、ListViewに対する処理を実装することでListViewを実際に動かすことができます。
    例えば、実際にこのListViewにデータを表示したい場合を考えてみます。Realmデータベースからタスク一覧のデータを取ってきて、取ってきたデータをListViewに表示したい場合にはどうすればいいのでしょうか。
    残念なことに、ListViewから直接Realmデータベースにはアクセスできません。
    そこで、アダプタの登場です。アダプタとは、簡単にいうと仲介役で、直接接続できない二つのものの間に入って繋げられるようにする役割があります。
    ListViewのアダプタにはListAdapterインターフェイスが用意されています。さらに、ListAdapterを実装しているRealmデータベースに接続するための専用のRealmBaseAdapterクラスを利用することで、簡単にデータにアクセスできます。

    リストビューアダプタ▲アダプタを利用したデータアクセス


    使い方としては、用途に合わせたRealmBaseAdapterを継承した独自のクラスを作成して、ListView.adpter = “ReamBaseAdpterを継承した独自クラスのインスタンスとして、ListViewのアダプタに、インスタンスを指定することでListViewへRealmのデータをリスト表示できるようになります。
    このListViewのアダプタへの指定は通常、setAdapterメソッドを利用しますが、Kotlinではadapterプロパティが利用できるため、
    上記のようにListViewのadapterプロパティにアダプタクラスのインスタンスをセットすることで、インスタンス化したアダプタを利用できるようになります。
    このように簡単にアダプタを利用できるのもKotlinを使用するメリットです。
    ちなみにここまでのRealmの導入からアダプタクラスの作成と指定までで一度ビルドを行なったところ、下記エラーにぶちあたってしまいました。
        Error:error: 'match_constraint' is incompatible with attribute android:layout_height (attr) dimension|enum [fill_parent=4294967295, match_parent=4294967295, wrap_content=4294967294].
    

    「match_constraint」という制約を設定していましたが、それが「incompatible」(非対応)ということで、制約系のエラーが出ていました。
    そこで、もう一度デザインプレビューの制約の設定を確認してみると、本来横幅の値を「50」と設定するところを「100」と設定していたためで、もし似たようなエラーが出てしまった場合には、制約の設定を確認して矛盾がないかを確認してみるといいかもしれません。

    リストビュー制約エラー▲横幅の設定値ミス


    こういった細かい設定ミスでアプリが動かないことは本当によくあります。しかし、こういったことを一つ一つ解決していくことで自分の作りたいアプリを完成させることができるんです!

    結論

    今回はAndroidアプリ開発を通してKotlinの特徴やJavaとの違いを紹介してきました。
    最後にKotlinを触ってみてどうだったか聞いてみましょう。
    おに
    楽しかったです!Javaで作るときとKotlinで作るときのお作法の違いが分かったので、勉強になりました。

    かっしー
    最新技術に触れることができて良かったです!

    ちあき
    Javaと勝手が違い戸惑いましたが、良い経験になりました。

    がっきー
    Kotlinの学習コストの少なさはもちろんですが、RealmというSQLiteに代わるデータベースの登場や、AnkoといったKotlin向けライブラリの存在など、これからのAndroid開発にはKotlinがアツくなっていくのではないでしょうか。ぜひみなさんもKotlinの導入を検討してみてはいかがでしょうか。

    システムサポート BS事業部では、スマートフォンアプリ開発(iPhone/Android)の実績もございます。
    以下に開発事例(お客さまインタビュー記事)を紹介しておりますので、ぜひご覧ください!


    もしかして興味あるかも?

    がっきー
    Follow がっきー:

    株式会社システムサポート BS事業部 2017年入社。3年目になり後輩のフォローに奮闘中。座右の銘は【継続は力なり】だが、同意語の【涓滴(けんてき)岩を穿つ】のほうがカッコいいと揺れている。