Retrofitを使ったサーバー通信、HTTPリクエスト【Android/Kotlin】



Retrofitを使った説明サイトはたくさんあるが、デザインパターンを埋め込んで説明しているものが多く、肝心のRetrofitの役割がどこからどこまでなのかイメージし辛く分かりづらかった。

そこで今回、Retrofitを動かすために必要な最小限のコードで、Androidのサンプルプロジェクトを作ってみた。
最小限のサンプルではあるが、動作を理解する上ではとてもわかりやすくなったのでこの記事で紹介してく。





Retrofitを使ったサーバー通信の完成イメージ




Retrofitとは、APIから取得するJSONデータを、オブジェクトにしてアクセスできるようにするまでを面倒見てくれるHTTP clientだ
APIから拾ったデータを下の図のようにViewへ表示させることを目標に、Retrofitを使っていく。



いきなりだが全コードを先に記しておく。



以外に短くて、拍子抜けしたかもしれない。
それではこのコードの内容を、順を追って解説していくことにしよう。





APIの準備


まず自前のサーバー上に、次のような簡単な内容のJSONファイルを置いてみた。


このJSONファイルのURLは次のものとする。
» http://apppppp.com/jojo.json

いきなりGithubやQiitaのAPIのように大規模なものを使ってしまうと、Retrofitの理解にかける労力をそぐ恐れがある。

本格的なものではなく、シンプルで単純なもののほうが理解を早める。
それに、自分で作ったものなのでAPIの仕様を変更できるし興味もわく。
そういうことで、自前でテストデータをサーバー上に設置することをオススメする。





Retrofitの実装 (implementation)


Retrofitを使えるようにするため、新規プロジェクトのbuild.gradle (Module: app)に次のように追加する。


これは、retrofit2最新版と、GSON、そしてRetrofit用のGSONコンバーターを指定しているのだ。





データクラスの作成


JSONファイルの内容と合わせて、次のようなデータクラスを定義した。ただし、JSONのキーの名前とプロパティの名前は同じにすること。
data class JoJo(val name: String = "", val stand: String = "")


インタフェースの作成


次にインタフェースを作成する。
interface JoJoService {
    @GET("jojo.json")
    fun fetchJoJo(): Call<JoJo>
}

ドメイン以下のパスをGETアノテーションの引数に渡す。つまりこの場合だと、ドメイン直下にファイルを置いたのでjojo.jsonを渡せば良い。

fetchJoJoメソッドは、APIリクエストを行う。定義をするだけで、実装はやる必要はない。

なんと素晴らしいことに、Retrofixが実装をやってくれるのだ!
ところで、fetchJoJoメソッドで返されるCallオブジェクトは、 import retrofit2.Call でインポートしているものだ。一度どんなものか、仕様を見ておくと良いだろう。




MainActivity


最後にMainActivityクラスを見ていこう。

ここでは、Retrofitオブジェクトを次のようにして生成する。
val retrofit = Retrofit.Builder()
    .baseUrl("https://apppppp.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

注意してほしいのは addConverterFactory(GsonConverterFactory.create()) だ。
今回GSONを使用するので、このファクトリメソッドを設定しないとJSONをオブジェクトに変換できない。以下のようなエラーが出たら、ここを疑ってほしい。

java.lang.IllegalArgumentException: Unable to create converter for class com.apppppp.retrofitsample.JoJo
            for method JoJoService.fetchJoJo


それでは、先程のRetrofitオブジェクトを実際に使っていこう。メインスレッドでは実行できないので、thread内で実行していく。

retrofit.create(JoJoService::class.java)では、先ほど作ったインタフェースのクラスオブジェクトを渡している。

val handler = Handler()

thread { // Retrofitはメインスレッドで処理できない
    try {
        val service:JoJoService = retrofit.create(JoJoService::class.java)
        val jojo = service.fetchJoJo().execute().body() ?: throw IllegalStateException("bodyがnullだよ!")

		....

    } catch (e: Exception) {
        Log.d("mopi", "debug $e")
    }
}


スレッド内から、UIを更新したい場合はこのように記述する。
handler.post(Runnable {
    // メインスレッドで処理
    val nameTextView = findViewById<TextView>(R.id.name)
    val standTextView = findViewById<TextView>(R.id.stand)

    nameTextView.text = jojo.name
    standTextView.text = jojo.stand
})


以上でRetrofitを使ったサンプルコードの出来上がりだ。

おっと、忘れていた!次の記述がマニフェストに無いと、インターネットアクセス出来ないので注意しよう!
<uses-permission android:name="android.permission.INTERNET" />


Kotlinプログラミング

Kotlinは、Javaとの相互運用を可能にし、Android OSでGoogleがフルサポートする静的型プログラミング言語です。この言語は、Javaだけでは十全ではない(Javaだけでは実装に手間がかかりすぎる)、軽量かつ豊かな表現形式や、他言語ではすでに実装されている最新の機能を盛り込んでいます。

KindleAmazon

基本からしっかり身につくAndroidアプリ開発入門

圧倒的な多数のユーザーが使っているヤフーのアプリ。その制作の最前線にいる黒帯エンジニアが、ユーザーが使いやすいアプリの大切な基本をしっかりと解説します。

KindleAmazon


あなたにおすすめ