【初心者向け】Kotlin&AndroidでRetrofitを使ってAPIから取得したデータをviewに表示させる

はじめに

Retrofitを使ってAndroidアプリからAPIを叩いて、viewに表示させるところまでをやろうかと思います。他にもRetrofitの記事は多いので、細かい説明は省きます。
いくつか勉強する中で、なんとなくはわかったものの、実際にアプリに組み込む時にどのような構成にしようか迷ったため、その構成も含めて書きたいと思います。

全体の構成

下記の構成で、GitHubのAPIから取得したリポジトリのデータをviewに表示させます。

└── retrofit_exercise
    ├── api
    │   └── APIClient.kt
    ├── response
    │   └── Response.kt
    ├── services
    │   ├── GitHubRepositoryService.kt
    │   └── GitHubUserService.kt(追加をする場合、説明では省略)
    │
    └── MainActivity.kt

Retrofitを使ってみる

作成したコードはGitHubにあげたので、説明いらないって人はよかったら見てみてください。

まずは準備

permissionの設定と、使うライブラリを指定します。

AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
app/build.gradle
ext {
    retrofit = '2.3.0'
}

implementation "com.squareup.retrofit2:retrofit:$retrofit"
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'

使うAPIのドキュメントを確認して、どんなデータを受けとるか決める

今回はGitHubのlist-user-repositoriesからデータをとってきます。
こちらのレスポンスの形式を確認して、それ用のdataクラスを作成します。

今回はリポジトリ名、詳細、言語、urlのみ取得することにします

Response.kt
data class Repos(val name: String, val description: String, val language: String, val url: String)

// 他のAPIから取得する場合にはここに追加をしていく

ドキュメント通りのリクエスト形式になるようにretrofitを使って記述する

同じく先ほどのドキュメントからリクエストの形式を確認します。
こんなのを作る想定です。
curl "https://api.github.com/users/{user}/repos?users=username(自分のgithubアカウント名を引数で渡す)&sort=desc(これも引数で渡す)"

interfaceの呼び出し元でBASE_URL = "https://api.github.com/" と指定をするため、@GETのパスはusers~となっています。
あとリポジトリ名とsortも呼び出し元で引数に渡すようにします。

細かいところは公式のドキュメントを確認してください。

GitHubRepositoryService.kt
// https://developer.github.com/v3/repos/#list-user-repositories
interface GitHubService {
    @GET("users/{user}/repos")
    fun fetchReposList(@Path("user") user: String, @Query("sort") sort: String): Call<List<Repos>>
}

作成したinterfaceの呼び出しを行う

ACCOUNT_NAMEを自分のアカウント名に変更してください。
サーバで作成したAPIを取得して、処理をすることが多いと思うので、base urlを指定したretrofitのインスタンスを返すメソッドを作成しました。

APIClient.kt
object APIClient {
    private const val BASE_URL = "https://api.github.com/"
    private const val ACCOUNT_NAME = "自分のgithubアカウント名"

    private fun restClient() : Retrofit {
        return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    fun fetchReposList() :Response<List<Repos>> {
        val service = restClient().create(GitHubService::class.java)
        return service.fetchReposList(ACCOUNT_NAME, "desc").execute()
    }

    // 他のAPIから取得する場合にはここに追加をしていく
}

viewに表示をさせる

ただとってきたデータを表示させるだけなので、手抜きですが取得したデータをそれぞれ表示させるtext viewを作成します。

activity_main.xml
(省略)
    <TextView
        android:id="@+id/name_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <TextView
        android:id="@+id/description_text"
        android:layout_width="wrap_content"
        android:layout_height="15dp"
        android:layout_marginTop="50dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toTopOf="@+id/name_text"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/language_text"
        android:layout_width="wrap_content"
        android:layout_height="15dp"
        android:layout_marginTop="65dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toTopOf="@+id/description_text"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/url_text"
        android:layout_width="wrap_content"
        android:layout_height="15dp"
        android:layout_marginTop="80dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toTopOf="@+id/language_text"
        app:layout_constraintTop_toTopOf="parent" />
(省略)

今回はこちらから呼び出しを行いますが、fragmentに表示させる場合にはそちらに追加をしたほうが良いと思います。

MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val handler = Handler()

        // メインスレッドでネットワーク通信を行うことができない
        thread {
            try {
                val response = APIClient.fetchReposList()
                // とりあえず1つだけ表示させてみる
                val firstRepos = response.body()!![0]

                // 別スレッドからUI操作ができないのでhandlerを使用する
                handler.post(Runnable {
                    name_text.text = firstRepos.name
                    description_text.text = firstRepos.description
                    language_text.text = firstRepos.language
                    url_text.text = firstRepos.url
                })

                Log.d("retrofit", "リポジトリのID" + response.body())
            } catch (e: Exception) {
                Log.w("retrofit", "fetchReposList :" + e)
            }
        }
    }

これでひとまず動くと思うので、APIを変更したりPOSTの場合を試してみたりとしてもらえれば良いなと思います。
APIから受け取ったデータをRxJavaを使って処理をすることが多いようなので、検証したら追記したいと思います。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.