startActivityForResultのrequestCodeを理解する

# はじめに
開発初心者の備忘録的なものです。
startActivityForResultを使って画面間のデータのやり取りをすることは多いと思うのですが、その引数の意味が気になったのでまとめました。知っておくと複数の画面から戻って来る場合に、それに応じた処理を書けるようになるので便利です。

## startActivityForResultとは？
通常のアクティビティ遷移の際に呼び出す`startActivity(Intent intent)`メソッドは、開くアクティビティに対して何かしらの情報を与えるのに対し、`startActivityForResult(Intent intent, int requestCode)`は開いたアクティビティから何かしらの情報を受け取ることを可能とする。つまりアクティビティ間での双方向の情報のやり取りが可能となる。必ず画面の遷移先から元の画面に戻って来る場合に用いられる。他のアプリに処理を委譲する場合にも使用できます。
## 簡単な実装例
本節では、戻って来た（遷移先のアクティビティがfinish()された）時に、元のアクティビティがどのようにして情報を受け取るのかについて、実装例を交えながら説明する。元のアクティビティのクラスを`FirstActivity.java`、遷移先のアクティビティのクラスを`SecondActivity.java`としている。
### Intentの生成と遷移

```java:FirstActivity.java

private static final int REQUEST_CODE = 1;

@Override
protected void onCreate(Bundle savedInstanceState){
	
	....
	
	Intent intent = new Intent(this, SecondActivity.class);
	startActivityForResult(intent, REQUEST_CODE);
}
```


1. 元のアクティビティの`onCreate()`の内部でIntentを生成する。

2. `startActivityForResult(intent,REQUEST_CODE)`を記述する。REQUEST_CODEは遷移先のアクティビティに対して一意に定まっていれば任意の整数でよい。

### 遷移先で値をセットした上で、元のアクティビティに戻る

EditTextに適当な文字列を入力し、OKボタンを押すと元のアクティビティに戻るといった挙動を示す実装を行う。

```java:SecondActivity.java
	
	@Override
	protected void onCreate(Bundle savedInstanceState){
		
		...
		
		Intent intent = new Intent();
		Button btn = (Button)findViewById(R.id.button);
		EditText edit = (EditText)findViewById(R.id.edit);
		
		btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // クリック時の処理
                intent.putExtra("INPUT_STRING", edit.getText().toString());
				setResult(RESULT_OK, intent);
				finish();
            }
        });
	}

```
1. 元のアクティビティへのintentを生成する。
2. ボタンにリスナーをつける。内部では、
	1. EditTextに入力されたテキストに`"INPUT_STRING"`というキーをつけてintentに突っ込む。
	2. `setResult(RESULT_OK)`を記述。これに関しては、後ほど説明する。
	3. アクティビティを`finish()`する。

### 元のアクティビティで値を受ける
`onActivityResult(int requestCode, int resultCode, Intent intent)`の内部に受け取りの処理を記述する。このメソッドはアクティビティのインスタンスが既に存在している場合に呼ばれ、何かしらの返り値を受け取る場合などの処理を書きます。例えば、バックボタンで戻ってきたときの処理などもここに書きます。

```java:FirstActivity.java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
	switch(requestCode){ 
		//SecondActivityから戻ってきた場合
		case(REQUEST_CODE):
			if(resultCode == RESULT_OK){
				//OKボタンを押して戻ってきたときの処理
				Log.v("Edit Text", data.getExtra("INPUT_STRING"));
			}else if(resultCode == RESULT_CANCELED){
				//キャンセルボタンを押して戻ってきたときの処理
			}else{
				//その他
			}
			break;
		default:
			break;
}
```

# 関連するメソッドの引数の意味について

さて、この記事のタイトルにもなってますが、本題となる下記2つのメソッドについて説明します。

## startActivityForResult(Intent intent, int requestCode)の引数
* intent

言わずもがな、アクティビティ遷移内容を記述したintentを渡しています。

* requestCode
 
 公式ドキュメントを読むと、
>整数の引数は、リクエストを識別する「要求コード」です。結果の Intent を受け取ると、アプリが正常に結果を識別し、その処理方法を決定することができるように、コールバックが同じ要求コードを提供します。

と書いてあります。要するに、遷移する先（というか現在のアクティビティに戻ってくる場合、どこから戻ってくるか？）を整数で指定しています。これを指定することで、複数のアクティビティとの間でのやりとりをこの要求コードで管理することができます（重要）。


## onActivityResult(int requestCode, int resultCode, Intent data)の引数
* requestCode

これは上記の通り、要求コードです。このメソッドが呼び出された時に、いったいどのアクティビティから戻ってきたのかを（一般的には）switch文などで判別します。

* resultCode

公式ドキュメントには
> 第 2 のアクティビティによって指定された結果コード。これは、操作が成功した場合の RESULT_OK か、ユーザーがバックアウトしたり、何らかの理由で失敗したりした場合の RESULT_CANCELED か、いずれか一方です。

と書いてあります。つまり、元のアクティビティに戻ってくるまえにどのような処理が行われたのかを整数で判別しています。上記の通り、バックボタンを押して戻ってきた場合は、`RESULT_CANCELED`が割り当てられます。処理が成功した場合は、そのアクティビティでsetResult(RESULT_OK)を記述したうえで`finish()`するのが一般的ですが、一応static変数にすれば適当に自分で操作ごとに整数を割り当てて使用することも可能です。

* data

IntentにputExtraで内包したデータが渡されるので、`data.getExtra(キー)`で取得できます。


# おわりに
実はこんな記事も紹介されています。RxJavaを用いてよりスマートに実装する方法です。自分はまだまだ見習いなので、コードの内部を理解した上で、より楽をするためには何かを考えていきたいです。

* [RxJavaでonActivityResultの煩わしさを解消する](http://qiita.com/droibit/items/f6b4d7d0a02a04b5eea1)