LoginSignup
3
8

More than 5 years have passed since last update.

【Android】Retrofit + Rx

Last updated at Posted at 2018-11-14

Retrofit

公式ページ

RetrofitのRx化に関しては Jake神作のAdapterを使っていたらしい。。が
現在本家のretrofitにAdapterが出来てるみたいで Jake神作のはDEPRECATEDになっている。

こちらを使う:eyes:

:computer:環境構築


app/build.gradleに以下を追加

    implementation 'io.reactivex.rxjava2:rxjava:2.1.6'
    implementation 'io.reactivex.rxjava2:rxkotlin:2.1.0'
    implementation 'com.squareup.moshi:moshi:1.5.0'
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
    implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'

:pencil: 実装


簡単なサンプル

サンプルとしても多い、GithubのAPIを使ってユーザー情報を取得して見ます。

  • Userクラス (ユーザー情報を格納するデータクラス)

    import com.squareup.moshi.Json
    
    data class User(
        @Json(name = "name")
        var name: String,
        @Json(name = "login")
        var login: String,
        @Json(name = "blog")
        var blog: String,
        @Json(name = "type")
        var type: String
    )
    
  • GithubApiクラス (interfaceを定義)

    import io.reactivex.Observable
    import retrofit2.http.GET
    import retrofit2.http.Path
    
    interface GithubApi {
    
        companion object {
            const val BASE_URL = "https://api.github.com"
        }
    
        @GET("users/{username}")
        fun getUser(@Path("username") user: String): Observable<User>
    }
    
  • MainActivityクラス

    class MainActivity : AppCompatActivity() {
    
        companion object {
            val TAG = MainActivity::class.java.simpleName
        }
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val retrofit = Retrofit.Builder()
                    .baseUrl(GithubApi.BASE_URL)
                    .addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().build()))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
                    .build()
    
            val service = retrofit.create(GithubApi::class.java)
            service.getUser("Slowhand0309").subscribe({ ret ->
                Log.d(TAG, "ret $ret")
            }, { error ->
                Log.e(TAG, error.message)
            })
        }
    }
    

AndroidManifestに
<uses-permission android:name="android.permission.INTERNET"/> を追加するのを忘れずに

戻り値に関して

RetrofitのRxJava2 Adapterは戻り値として
Observable, Single, Maybe, Completable
を提供している、が、それぞれの違いがわからないので調べてみる。

  • Observable: いつも使っているので省力
  • Single
    • onNext+onComplete = onSuccess でonSuccessは一回しか呼べない
  • Maybe
    • onSuccessかonErrorかonCompleteのどれかが呼ばれる、または全く呼ばれません。
  • Completable
    • onErrorかonCompleteのどれかが呼ばれる、または全く呼ばれません。

参考URL


エラー処理に関して

200番台以外のレスポンスの場合 HttpException として onError が呼ばれる
実際のソースコード

エラー処理に関しては↓のように捌けば良さそう。

        disposable += ApiClient.createUser()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ res ->
                    Log.d(TAG, "create user success ${res.id}")
                }, { error ->
                    (error as? HttpException)?.let {
                        Log.e(TAG, "code: ${it.code()}")
                        Log.e(TAG, "message: ${it.message()}")
                        Log.e(TAG, "response: ${it.response()}")
                    }
                })

401が返ってきた場合の実際の出力

E/MainActivity: code: 401
    message: 
E/MainActivity: response: Response{protocol=h2, code=401, message=, url=https://....}

:bomb: バッドノウハウ


単純にmoshiを使うだけだと、dataクラスのnon-nullのプロパティにnullが入ってしまう!
参考URL

そこでmoshiのkotlin extensionを導入して、non-nullにnullを入れうようとしたら
例外を投げるように修正

app/build.gradleに以下を追加

implementation 'com.squareup.moshi:moshi-kotlin:1.5.0'

MainActivityのmoshiを生成している箇所をいかに変更

        val moshi = Moshi.Builder()
                    .add(KotlinJsonAdapterFactory())
                    .build()

        val retrofit = Retrofit.Builder()
                .baseUrl(GithubApi.BASE_URL)
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
                .build()

これでnon-null / null をきっちり管理してくれます:thumbsup:

:link: 関連リンク


3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8