KotlinでRetrofit2を使ってみました(2018/9/8全面的に書き直し)。
プロジェクト
プロジェクトはGitHubに上げてあります。
github.com
やったこと
- Gradleに追記
- Manifestに追記
- 受け取るためのデータクラス作成
- Retrofitを使う
Gradleに追記
Module.appに以下2行を追加します。
implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
追記後全文。
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 27 defaultConfig { applicationId "com.wrongwrong.retrofittest" minSdkVersion 15 targetSdkVersion 27 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { //for Retrofit2 implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }
Manifestに追記
ネットワークを使うのでパーミッションを書きます。
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
追記後全文。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wrongwrong.retrofittest"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
受け取るためのデータクラス作成
今回はGitHubAPIのreposを取得します。取得するデータ一覧はこちら。
今回はデータの変数名をAPIデータと合わせていますが、実際はキャメルケースで書いてもちゃんと動きます。
package com.wrongwrong.retrofittest import java.io.Serializable data class Owner( var login: String, var id: Long, var node_id: String, var avatar_url: String, var gravatar_id: String, var url: String, var html_url: String, var followers_url: String, var following_url: String, var gists_url: String, var starred_url: String, var subscriptions_url: String, var organizations_url: String, var repos_url: String, var events_url: String, var received_events_url: String, var type: String, var site_admin: Boolean ): Serializable data class Permissions( var admin: Boolean, var push: Boolean, var pull: Boolean ): Serializable data class License( var key: String, var name: String, var spdx_id: String, var url: String, var name_id: String ): Serializable data class Repo( var id: Long, var node_id: String, var name: String, var full_name: String, var owner: Owner, var private: Boolean, var html_url: String, var description: String?, var fork: Boolean, var url: String, var archive_url: String, var assignees_url: String, var blobs_url: String, var branches_url: String, var collaborators_url: String, var comments_url: String, var commits_url: String, var compare_url: String, var contents_url: String, var contributors_url: String, var deployments_url: String, var downloads_url: String, var events_url: String, var forks_url: String, var git_commits_url: String, var git_refs_url: String, var git_tags_url: String, var git_url: String, var issue_comment_url: String, var issue_events_url: String, var issues_url: String, var keys_url: String, var labels_url: String, var languages_url: String, var merges_url: String, var milestones_url: String, var notifications_url: String, var pulls_url: String, var releases_url: String, var ssh_url: String, var stargazers_url: String, var statuses_url: String, var subscribers_url: String, var subscription_url: String, var tags_url: String, var teams_url: String, var trees_url: String, var clone_url: String, var mirror_url: String, var hooks_url: String, var svn_url: String, var homepage: String, var language: String?, var forks_count: Int, var stargazers_count: Int, var watchers_count: Int, var size: Int, var default_branch: String, var open_issues_count: Int, var topics: List<String>, var has_issues: Boolean, var has_projects: Boolean, var has_wiki: Boolean, var has_pages: Boolean, var has_downloads: Boolean, var archived: Boolean, var pushed_at: String, var created_at: String, var updated_at: String, var permissions: Permissions, var allow_rebase_merge: Boolean, var allow_squash_merge: Boolean, var allow_merge_commit: Boolean, var subscribers_count: Int, var network_count: Int, var license: License ): Serializable
Retrofitを使う
今回はonCreate内でhttps://api.github.com/users/{id}/repos
にアクセスしてデータを取得し、0番目のリポジトリのフルネームをLogに出力します。
インターフェース内には、GET, POST, PUT, DELETEなど、Rest APIにおけるCRUD処理が全て書けます。今回はデータを取得していますが、POST処理などでデータが返ってこない場合は戻り値をCall<Unit>
*1とします。
retrofitとserviceはクラス内変数として宣言していますが、これらの初期化は処理コストが重いため、実際はグローバルに用意して使うのが良いようです。少なくともそのまま関数に書くのは悪い使い方です。
package com.wrongwrong.retrofittest import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import com.google.gson.GsonBuilder import retrofit2.Call import retrofit2.Callback import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.GET import retrofit2.http.Path import java.io.IOException class MainActivity : AppCompatActivity() { interface IGetRepos{ @GET("{id}/repos") fun getRepos(@Path("id") userID : String) : Call<List<Repo>> } private val retrofit: Retrofit = Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(GsonBuilder().serializeNulls().create())) .baseUrl("https://api.github.com/users/") .build() private val service: IGetRepos = retrofit.create(IGetRepos::class.java) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val call = service.getRepos("k163377") call.enqueue(object : Callback<List<Repo>> { override fun onResponse(call: Call<List<Repo>>?, response: Response<List<Repo>>?) { try{ var arr: List<Repo>? = response!!.body() Log.d("onResponse", arr!![0].full_name) }catch (e: IOException){ Log.d("onResponse", "IOException") } } override fun onFailure(call: Call<List<Repo>>?, t: Throwable?) { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } }) } }
参考URL
mainActivityの大部分はこちらから写経させて頂きました。 | Retrofit2Demo/Example01.java at master · ikidou/Retrofit2Demo · GitHub |
もっと詳しい解説です。 | Android Retrofit2 with Kotlin - Qiita |
AndroidでRxJavaと組み合わせた例です。 | KotlinでRetrofitとRxを使ってAPIクライアントをサクッと実装する - Qiita |