ついにFragmentに入門したわけですが、早速ハマったのでメモしておきます。サポートパッケージェ・・・。
※本エントリはandroid.support.v4.app.Fragmentに関する動作について書いています。android.app.Fragmentでは以下に書いている問題は発生しません。
FragmentでstartActivityForResultが使える
Fragmentって便利ですねー。特にActivityにベッタリ書いていた様な実装をFragmentに分けて色々捗らせる事が出来る点がとても助かります。で、Activityに書いていた処理をFragmentに集約する時に問題になるのがstartActivityForResultによって処理を委譲している部分です。
FragmentではstartActivityやstartActivityForResultやonActivityResultが用意されており、FragmentからActivityを起動したり、結果を受け取る事ができます。
という事でまぁ問題なくねーと思いがちですがしかし、FragmentのstartActivityForResultには罠があるんですねーーーー!
リクエストコードは下位16bitの範囲で
まず以下のコードをFragment内で実行してみます。なんの変哲もない、アドレス帳を起動して選択結果を受け取るだけのIntentです。
private final static int REQUEST_CODE = 0x11111;
public void pick() {
Intent intent = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, REQUEST_CODE);
}
し、死んだー!
Can only use lower 16 bits for requestCode
なにーー!
そうですFragmentではstartActivityForResultの第二引数に与えるリクエストコードを下位16bit以内に収める必要があります。
つまり0x0000〜0xffffまでの間の値にしろ、という事ですね。上記コードは"0x11111"だったのでダメだったんですね。
リクエストコードは下位16bitの範囲で。
onActivityResultが呼ばれないパターン
こういう罠にはまるのは僕くらいのものな気がしますが、サポートパッケージのFragmentのstartActivityForResultではonActivityResultが呼ばれないパターンがあります。
親となるActivity側がonActivityResultをオーバーライドしている場合に起きるのですが・・・。
コードを見てみます。問題無いようなあるような・・・。
親となるActivity側
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
switch (requestCode) {
case REQUEST_CODE:
//なにもしない
break;
case MOGE:
//~処理~
break;
}
}
Fragment側@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE:
if(resultCode == Activity.RESULT_OK){
Log.d(TAG, "okkkk!");
}
else{
Log.d(TAG, "ooooops!");
}
break;
}
}
このコードの場合Fragment側のonActivityResultが呼ばれません。何故か?
super.onActivityResultを忘れているから!
そうです。親Activity側のsuper.onActivityResultを呼んでませんでした。
サポートパッケージでFragmentを使う場合はActivityではなくFragmentActivityを継承する必要があります。
このFragmentActivityのonActivityResultでFragmentに結果を渡しているのでsuper.onActivityResultを呼んであげないとFragment側にonActivityResultの呼び出しが行かないんですねー。
正しくは
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE:
//なにもしない
break;
case MOGE:
//~処理~
break;
}
}
問答無用でsuper.onActivityResult。
まとめ
コンパーチビリティの為のサポートパッケージですがなかなかどうして、大変ですねー。

0 件のコメント:
コメントを投稿