SpaceX REST API で試す Retrofit の coroutine 対応

Retrofit の coroutine 対応が進んでいるようです。

Jake Wharton's retrofit2-kotlin-coroutines-adapter has been the go-to solution for bridging the coroutine world with Retrofit for a little while. But now, a much-anticipated PR has finally been merged, officially bringing coroutine support to Retrofit 2.

Retrofit meets coroutines - zsmb.co

JakeWharton/retrofit2-kotlin-coroutines-adapter: A Retrofit 2 adapter for Kotlin coroutine's Deferred type.

SpaceX-API とか公開されていたのですね。

r-spacex/SpaceX-API: Open Source REST API for rocket, core, capsule, pad, and launch data

https://api.spacexdata.com/v3/rockets

対応する最小限のデータクラスを作って、試してみましょう。


data class Rocket(

    val id: Int,

    @field:Json(name = "rocket_name") 
    val name: String

)


val retrofit = Retrofit.Builder()
    .baseUrl("https://api.spacexdata.com/v3/")
    .addConverterFactory(MoshiConverterFactory.create())
    .build()

val api = retrofit.create<SpaceXApi>()

create() は reified type が使えるようになってます。

JSONのシリアライズはお好みのものを。

そして、interface を書いていきますが、

ここを戻り値に別に見てみます。

Call<List<Rocket>>

interface はこれまでと同じ記述。


interface SpaceXApi {

  @GET("rockets")
  fun getRockets(): Call<List<Rocket>>

}

受け側の3つの例。


runBlocking {
  val rockets: List<Rocket> = api.getRockets().await()
  rockets.forEach(::println)
}


runBlocking {
  val rockets: List<Rocket> = try {
    api.getRockets().await()
  } catch (e: Exception) {
    println("Network error :[")
    return@runBlocking
  }
  rockets.forEach(::println)
}


runBlocking {
  val response = api.getRockets().awaitResponse()
  if (response.code() == 200) {
    response.body()?.forEach(::println)
  }
}

結果はすべて同じ。


Rocket(id=1, name=Falcon 1)
Rocket(id=2, name=Falcon 9)
Rocket(id=3, name=Falcon Heavy)
Rocket(id=4, name=Big Falcon Rocket)

これまで非同期処理時に必要だった コールバック や enqueue の記述は必要ありません。

受け側の記述を変化させることで、Exception や レスポンスコードを拾うことができます。

suspend List<Rocket>

suspend を使うことでさらに直感的に書けます。


interface SpaceXApi {

  @GET("rockets")
  suspend fun getRockets(): List<Rocket>

}


runBlocking {
  val rockets = api.getRockets()
  rockets.forEach(::println)
}

結果。


Rocket(id=1, name=Falcon 1)
Rocket(id=2, name=Falcon 9)
Rocket(id=3, name=Falcon Heavy)
Rocket(id=4, name=Big Falcon Rocket)

List<Rocket> に対して Call や Deferred のようなラッパーは必要ありません。

suspend Response<List<Rocket>>

Response を拾います。


interface SpaceXApi {

  @GET("rockets")
  suspend fun getRockets(): Response<List<Rocket>>

}


runBlocking {
  val response = api.getRockets()
  if (response.code() == 200) {
    response.body()?.forEach(::println)
  }
}

結果。


Rocket(id=1, name=Falcon 1)
Rocket(id=2, name=Falcon 9)
Rocket(id=3, name=Falcon Heavy)
Rocket(id=4, name=Big Falcon Rocket)

最も実用的で簡潔な記述と思われます。

まとめ

Kotlin で記述するにしても、多くの記述が可能となりそうです。

RxJava他ライブラリを利用しての非同期実装を含めると様々となります。

ネット上で検索するにも自分の環境や好みに合った記述を探すのにも時間がかかることになり混乱もありそうで。

Jakeも今後はメンテしないと思われます。

Márton Braun on Twitter: "Retrofit is finally receiving the proper coroutine support it deserves! Read more about it in my latest blog post here: https://t.co/8k9EauzzUa #AndroidDev #Kotlin #Coroutines" / Twitter

ちなみに、これらの話は今現在はSNAPSHOTで進行中です。

以下でどうぞ。


repositories {
  maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}

dependencies {
  implementation "com.squareup.retrofit2:retrofit:2.5.1-SNAPSHOT"
}


Google「音声文字変換」アプリを試す



「スピード」と「精度」がどんなものなのか。

音声文字変換 - Google Play のアプリ

ホリエモンのトークで試してみます。





うん。十分使えると思います。


Homebrew を 1.9 から 新 2.0 に更新する方法

macOS用のパッケージマネージャ「Homebrew」の最新版となる「Homebrew 2.0」正式版がリリースされました。

macOS用パッケージマネージャ「Homebrew 2.0」リリース。LinuxとWSL(Windows Subsystem for Linux)にも正式対応 - Publickey

2.0.0 — Homebrew

やってみます。



ん?

なぜか上がってるけど。

そして、

brew cleanup

これだけ?


「Unresolved reference: R」と出る

謎。

androidx か?

Unresolved reference: R - Twitter検索 / Twitter

AGP3.3 - Twitter検索 / Twitter

AS最新版へ更新でケリがつく。

IDEもチャラく頻繁に切り替える時代?

JetBrains Toolbox で Android Studio の Stable/Beta/Canary が同時に管理できる?


kotlinx.android.synthetic は使わないほうがいいのか

2) Replaced kotlinx synthetic with findViewById

kotlinx.android.synthetic is no longer a recommended practice. Removing
in favour of explicit findViewById.

Sample updates: Fragment state, synth accessors (Ic472f90e) · Gerrit Code Review

Hey! Developer Advocate for Android at Google here!

I wanted to add a bit of background here. Kotlin Extensions with synthetic views was never intentionally “recommended” though that shouldn’t be taken as a recommendation to not use them. If they're working for you please feel free to continue using them in your app!

We’ve been shifting away from them (e.g. we don’t teach them in the Udacity course) because they expose a global namespace of ids that’s unrelated to the layout that’s actually inflated with no checks against invalid lookups, are Kotlin only, and don't expose nullability when views are only present in some configuration. All together, these issues cause the API to increase number of crashes for Android apps.

On the other hand, they do offer a lightweight API that can help simplify view lookups. In this space it's also worth taking a look at Data Binding which also does automatic view lookups - as well as integrates with LiveData to automatically update your views as data changes.

Today, there's a few options in this space that work:

Data Binding is the recommendation for view lookup as well as binding, but it does add a bit of overhead when compared to Android Kotlin Extensions. It's worth taking a look to see if this is a good fit for your app. Data Binding also allows you to observe LiveData to bind views automatically when data changes. Compared to Kotlin Extensions, it adds compile time checking of view lookups and type safety.

Android Kotlin Extensions is not officially recommended (which is not the same as recommendation against). It does come with the issues mentioned above, so for our code we're not using them.

Butter Knife is another solution that is extremely popular and works for both Kotlin and the Java Programming Language.

Reading through the comments here there's a lot of developers that are having great luck with Kotlin Extensions. That's great - and something we'll keep in mind as we look at ways to continue improving our APIs. If you haven't taken a look at Data Binding, definitely give it a shot.

As an aside, our internal code style guide is not intended to be directly applied outside of our codebase. For example, we use mPrefixVariables, but there's no reason that every app should follow that style.

Why kotlinx synthetic is no longer a recommended practice : androiddev

Jake他、著名な人々のコードを見ていると、「そもそも使ってない」ことは明らか。

そもそも、

「user_name」 と 「userName」

の気持ち悪さはありましたよね。

mobile - Android id naming convention: lower case with underscore vs. camel case - Stack Overflow

強制的に禁止はしてないけど、そういうことだろうと思う。

findViewById 万歳!

ButterKnife 万歳!

kotlin-examples/gradle/android-butterknife at master · JetBrains/kotlin-examples

「Google+」の終了が2019年8月から4月に繰り上げ 5250万人に影響の新たなバグ発見で - ITmedia NEWS