Activity間の遷移とデータのやりとり

#概要
Activity間でデータをやりとりしながら遷移するためには、AndroidOSのActivityManagerに**Intent**を渡すことで実現します。
Intentを受け取ったActivityManagerは、設定された定義に従ってActivityを生成します。

#親Activity→子Activity
まずは単純に親Activity(遷移元)から子Activity(遷移先)への遷移です。

###親Activity

```kotlin:ParentActivity.kt
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_parent)
        parentButton = findViewById(R.id.parentButton)
        parentButton.setOnClickListener {
            val intent = Intent(this, ChildActivity::class.java).run {
                putExtra("PARENT_KEY", "親からのデータです！")
            }
            startActivity(intent)
        }
    }
```

ボタンに下記リスナーをセットしています。

1. **Intent**に遷移先のクラスを設定して初期化します。
2. **putExtra()**を使って、IntentにKey-Valueの構造でデータをセットします。
3. Intentを渡して**startActivity(Intent intent)**を呼び出します。

###子Activity

```kotlin:ChildActivity
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_child)
        val stringExtra = intent.getStringExtra("PARENT_KEY")
    }
```

親Activityから渡ってきたデータを取り出します。

- **intent.getStringExtra()**で指定したKeyを使って、データを取り出します。
    - それぞれ型に応じたメソッドを使い、今回は文字列なのでgetStringExtra()です。

#親Activity→子Activity→親Activity
実際には親から子への一方通行ではなく、親子で行き来があるかと思います。
よって親Activityから子Activityに遷移し、Backボタンで親Activityに戻る遷移です。

###親Activity

```kotlin:ParentActivity.kt
    companion object {
        const val REQUEST_CODE_CHILD = 0
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_parent)
        
        parentButton = findViewById(R.id.parentButton)
        parentButton.setOnClickListener {
            val intent = Intent(this, ChildActivity::class.java).run {
                putExtra("PARENT_KEY", "親からのデータです！")
            }
            startActivityForResult(intent, REQUEST_CODE_CHILD)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        val childData = data?.getStringExtra("CHILD_KEY")
        Log.d("ParentActivity", "requestCode: $requestCode, resultCode: $resultCode, data: $childData")
    }
```

startActivity(Intent intent)ではなく、**startActivityForResult(Intent intent, int requestCode)**メソッドを呼んでいます。
使い方はほぼ同じですが、第二引数に開発者が定義する**requestCode**が入ります。
これは子Activityが複数ありえる場合に、**どこから戻ってきたのか判別するための情報**となります。
この例では一つしかありえないため第二引数は省略することも可能ですが、定義しておいたほうが後の開発のためになります。

onActivityResult()の説明の前に、子Activityの説明に移ります。

###子Activity

```kotlin:ChildActivity
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_child)
        val stringExtra = intent.getStringExtra("PARENT_KEY")

        val intent = Intent().run {
            putExtra("CHILD_KEY", "子からのデータです！")
        }

        childOKButton = findViewById(R.id.childOKButton)
        childOKButton.setOnClickListener {
            setResult(Activity.RESULT_OK, intent)
        }

        childCanceledButton = findViewById(R.id.childCanceledButton)
        childCanceledButton.setOnClickListener {
            setResult(Activity.RESULT_CANCELED, intent)
        }
    }
```
ボタンを2つ作成し、各々のリスナーで**setResult(int resultCode, Intent data)**メソッドを呼んでいます。
これによって親に返すためのデータを定義しています。
**resultCode**は一般的には**RESULT_OK**か***RESULT_CANCELED**のどちらかです。
resultCodeを使うことで子Activityがどのように終了したかで、親Activityの挙動を変えることができます。

また、Intentにはより具体的なデータを持たせることができます。
省略も可能です。

###親Activity.onActivityResult()
ここで親Activityに定義されていた**onActivityResult()**に戻ります。
Backボタンが押されたことによりActivityManagerは親Activityの**onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)**メソッドを呼び出します。
引数からそれぞれrequestCode, resultCode, Intentが渡ってきます。

####親に再び戻ってきた際のログ
仕込んだログから、ボタンを押したとき、押さなかったときの各引数の値が以下のようになっているのがわかります。

```
OKボタンの場合
D/ParentActivity: requestCode: 0, resultCode: -1, data: 子からのデータです！

Canceledボタンの場合
D/ParentActivity: requestCode: 0, resultCode: 0, data: 子からのデータです！

どちらも押さなかった場合
D/ParentActivity: requestCode: 0, resultCode: 0, data: null
```

#参考情報
[Android Programming: The Big Nerd Ranch Guide (3rd Edition) (Big Nerd Ranch Guides)](https://amzn.to/2K8OlO7)