以前のエントリの「 1apkでAndroidタブレット向けとスマートフォン向けアプリを実現する方法 その3」の「FragmentとActivityの役割分担」でFragmentとActivityの関係について記載し、上の図のように Fragment が導入されたからといっても、Fragment はActivityに依存しないように機能をモジュール化できる機能であり、以下の図のように他のActivityと依存関係を持たせることは良くないため避けるべきと記載をしました。
それについて、FragmentのAPIで依存しないような機能が提供されていることが判明しました。それについて記載したいと思います。以下で解説を行うAPIは、compatibility v4ベースで行います。Fragment クラスのAPIとして以下の2つのAPIが提供されています。Androidアプリ開発者にはなじみ深いAPIだと思います。
void startActivity(Intent intent) Call Activity#startActivity(Intent) on the fragment's containing Activity. void startActivityForResult(Intent intent, int requestCode) Call Activity#startActivityForResult(Intent, int) on the fragment's containing Activity.
Fragment.java で提供される API
Fragment.java のソースコードは、(Windowsの場合)以下にあります。Linux, MAC の方はそれぞれの環境に読みかえてください。存在しない場合は、SDK Tool で Compatibility Package をダウンロードしてください。
...\android-sdk-windows\extras\android\compatibility\v4\src\java\android\support\v4\app\Fragment.java
Fragment.java の startActivity()メソッドとstartActivityForResult()メソッドをそれぞれ具体的に見ていきたいと思います。
それぞれのメソッドの抜粋が以下のようなものです。
/** * Call {@link Activity#startActivity(Intent)} on the fragment's * containing Activity. */ public void startActivity(Intent intent) { if (mActivity == null) { throw new IllegalStateException("Fragment " + this + " not attached to Activity"); } mActivity.startActivityFromFragment(this, intent, -1); }
/** * Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's * containing Activity. */ public void startActivityForResult(Intent intent, int requestCode) { if (mActivity == null) { throw new IllegalStateException("Fragment " + this + " not attached to Activity"); } mActivity.startActivityFromFragment(this, intent, requestCode); }
上記の抜粋をみると、mActivityのメソッドを呼び出していることがわかります。
それ以外はただの初期化状態の確認(nullチェック)だけです。
ここで startActivityFromFragment()メソッドという見慣れないメソッドが呼び出されています。
これは何でしょうか?それを探るために、mAcitivyt が何者かを調査します。
FragmentActivity.java で提供される API
// Activity this fragment is attached to. FragmentActivity mActivity;
すると、225行目で mActivity の宣言がありました。ここから FragmentActivity クラスということがわかりました。
続いて、Fragment.java と同じディレクトリにある FragmentActivity.java の中身を見ていきます。
FragmentActivity.java の643行目に startActivityFromFragment() メソッドがありました。
/** * Called by Fragment.startActivityForResult() to implement its behavior. */ public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { if (requestCode == -1) { super.startActivityForResult(intent, -1); return; } if ((requestCode&0xffff0000) != 0) { throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); } super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff)); }
ここでの super は何かというと、FragmentActivity.java の class 宣言で以下のように記載があり、Activity クラスということがわかりました。
つまり、startActivityFromFragment() メソッドで行っていることは、Android開発では一般的な Activity の startActivityForResult()メソッドか startActivityForResult()メソッドを リクエストコード(requestCode)の有無によって、切り替えて実行していることがわかりました。
public class FragmentActivity extends Activity { private static final String TAG = "FragmentActivity"; private static final String FRAGMENTS_TAG = "android:support:fragments";
結論
以前のエントリで Fragment から startActivity() すべきでないと書きましたが、よく分析してみると Fragment で startActivity()しても以下の図のように上位のActivity の startActivyt()メソッドが呼び出される仕組みがあるため、Fragment からでも実施して問題ありません。
Honeycomb はソースコードが公開されておらずこのような調査・分析ができませんが、Compatibility package に関してはソースコードが公開されているのでこのように調査できることは大変有益だと思います。
Fragmentは、Honeycomb と Compatibility package のそれぞれで提供されているAPIが一部異なっているものがあります。
具体的には、ActivityとFragmentActivity や getFragmentMangaer() とgetSupportFragmentManager() などです。
それでも、本ソースコードと Honeycomb 内に実装が大きく異なっているとは考えづらいため、この Compativility package のソースコードから Honeycomb の実装が一部見えてくると思います。早くICSになってソースコードが公開されることを楽しみにしています!
Android FragmentからのActivity呼び出し方法:
以前のエントリの「 1apkでAndroidタブレット向けとスマートフォン向けアプリを実現する方法 その3」の「FragmentとActivityの役割… http://t.co/jMLYSaY
Android Fragment から Activityを呼び出す正しい方法について記載 | Bescottee – http://andbrowser.com/develop...
Android Fragment から Activityを呼び出す正しい方法について記載 | Bescottee – http://andbrowser.com/develop...
これかな・・・? http://t.co/vCo3tM3K
Android Fragment から Activityを呼び出す正しい方法について記載 | Bescottee – http://andbrowser.com/develop...