Sansan Builders Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

startActivityForResultがDeprecatedになった対応方法

こんにちは!Sansan事業部 プロダクト開発部のふるしんです。

私は大阪のオフィスでSansanプロダクトのAndroidアプリの開発に従事しています。

play.google.com

2020/04/29にActivityのVersion 1.2.0-alpha04が公開され、

startActivityForResult()とonActivityResult()、そしてonRequestPermissionsResult() がDeprecatedになったよ! 代わりにActivity Result APIsを使ってね!

とアナウンスがありました。

developer.android.com

そこでこの記事では、startActivityForResult()とonActivityResult()を具体的にどのようにActivity Result APIを使って置き換えるのかを解説します。

startActivityForResultはAPI level 1から存在するので、影響する方が非常に多いのではないかと想像します。

従来どおりに実装した場合

今まで通り実装したらこんな感じのイメージになります。

かなり省略してしまいましたが以下のことをしています。

  • 呼び出す側のActivityのButtonを押したら startActivityForResult でSubActivityへ遷移する
  • SubActivityでButtonを押したらIntentへvalueとして100をセットし、Activity.RESULT_OKとともにsetResultしてからfinish()する
  • MainActivity側の onActivityResult で返ってきた値をチェックしてToastを表示

呼び出す側のActivity

MainActivity.kt

binding.navigationButton.setOnClickListener {
            startActivityForResult(SubActivity.createIntent(this), REQUEST_CODE)
        }

// ...

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    when (resultCode) {
        Activity.RESULT_OK -> {
            data?.let { data ->
                val value = data.getIntExtra(SubActivity.KEY_VALUE, 0)
                Toast.makeText(this, "$value", Toast.LENGTH_LONG).show()
            }
        }
    }
}

呼び出される(Resultを返す)側のActivity

SubActivity.kt

binding.finishButton.setOnClickListener {
    val intent = Intent().apply { putExtra(KEY_VALUE, 100) }
    setResult(Activity.RESULT_OK, intent)
    finish()
}

Deprecated後はどうなる?

ここからが本題です。上記の流れをActivity Result APIを使って書き換えたらどうなるか試してみます。

詳しくは公式ドキュメントに記載されていますので、それに則って実装してみます。

developer.android.com

build.gradleに追加

まずは必要なものをbuild.gradleに追加しましょう。

androidx.activity:activity-ktxは1.0.0からAppCompat1.1.0が必要になっていますので、AppCompatのバージョンが低い方はバージョンアップが必要となります。

developer.android.com

build.gradle

implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.activity:activity-ktx:1.2.0-alpha04'

呼び出し側を変更

呼び出し側は次のように変化します。

MainActivity.kt

val startForResult =
    registerForActivityResult(StartActivityForResult()) { result: ActivityResult? ->
        if (result?.resultCode == Activity.RESULT_OK) {
            result.data?.let { data: Intent ->
                val value = data.getIntExtra(SubActivity.KEY_VALUE, 0)
                Toast.makeText(this, "$value", Toast.LENGTH_LONG).show()
            }
        }
    }
startForResult.launch(SubActivity.createIntent(this))

簡単に言うと「onActivityResultの中身がregisterForActivityResultのラムダ式に入っちゃった!」という程度の変化です。

正直なところ大きな変化があったのではないかとビクビクしていましたが、とてもシンプルになった印象です!

呼び出される側は?

呼び出される側は何も変わりません!

まとめ

今回はstartActivityForResult()とonActivityResult()だけにフォーカスしましたが、他にもActivityResultContractを継承したカスタマイズもできるようになってるので、柔軟性が増えた印象です。

余談ですが、gradleにandroidx.activity:activity-ktx:1.2.0-alpha04を追加したらDeprecatedだとstartActivityForResultに線が引かれました。

わかっちゃいましたがすごい変化だなぁと感じています。 f:id:furusin:20200520095232p:plain

最後に

Sansanでは一緒に働く仲間を募集しています!

興味が湧きましたらぜひお声がけください!

jp.corp-sansan.com

© Sansan, Inc.