FragmentでgetContextで得たcontextはどこから来ますか?
5982 ワード
まずfragmentのgetContextメソッドを見てみましょう.
contextはmHostのgetContextメソッドで得られていることがわかりますが、Ctrl+左ボタンでmHostはFragmentHostCallbackクラスのオブジェクトであることがわかります.次にFragmentのmHostオブジェクトがどこで値を付けているかを知るだけでいいです.
我々のfragmentは一般的にfragmentManagerのbeginTransactionメソッドでFragmentTransactionを取得してaddを追加しますが、getSupportFragmentManagerで取得したのはFragmentManagerImpl、つまりFragmentManagerの実装クラス(後述)です.FragmentManagerImplのbeginTransactionメソッドを見てみましょう.
FragmentTransactionはFragmnetTransactionから継承されたBackStackRecordオブジェクトであり、BackStackRecordのaddメソッドは最終的にFragmentManagementのaddFragmentメソッドに戻ります(これはfragmentの起動プロセスに関連し、詳しくは説明しません):
f.mHost=mHost、つまりfragmentでcontextを取得する際に使用されるFragmentHostCallbackクラスのオブジェクトmHostがFragmentManagement Implによって付与されていることがわかります.
私たちの問題は、そのmHostはどこから来たのかということになりました.
fragmentManagerImplのattachControlメソッドを参照してください.
mHostは、FragmentControllerによって呼び出される値をここに割り当てます.
fragmentControllerは誰だ?そのmHostはどこから来たのですか?
Fragmentを追加するのは、一般的にgetSupportFragmentManager()を使用します.beginTransaction()FragmentTransactionオブジェクトを取得します.FragmentActivityのgetSupportFragmentManagerメソッドを見てみましょう.
Activityは、finalタイプのFragmentControlオブジェクトのgetSupportFragmentManagerを使用してfragmentManagerを取得していることがわかります.
FragmentControllerのgetSupportFragmentManagerは、関数を構築するパラメータFragmentHostCallbackオブジェクトのgetFragmentMnaagerImlから得られます.
FragmentManagerから継承されるFragmentManagerImplを直接返します.
元のfragmentManagerとそのmHostオブジェクトは、FragmentActivityのfragmentControlオブジェクトによって取得されていました.
ここで私たちの問題は、FragmentControllerのmHostはどこから来たのかということになりました.
FragmentActivityが伝えたものです
HostCallbacksを見てみましょう
HostCallbackは、FragmentHostCallbackのコンストラクション関数を呼び出す現在のactivityオブジェクトを持っていることがわかります.
すべてが水面に捧げられた.mHostのcontextはここにある.
まとめてみます.
FragmentActivityにはfinalタイプのFragmentControllerオブジェクトがあり、FragmentControllerはHostCallbackオブジェクトmHost(mHostはcontext)を持ち、FragmentManagerもそのmHostによって作成され、FragmentControllerがattachControllerメソッドを呼び出したときにそのmHostに値を付与し(FragmentManagerのmHostとFragmentControllerのmHostは同じ)、FragmentのmHostはaddのときにFragmentManagerによって値を付与される.
実はすべてのソースはFragmentActivityが持っているFragmentControllerオブジェクトです!
足指で考えてもfragmentのgetContextメソッドで手に入れたのがその付着したActivityかもしれませんが、書きました...
いいね!
@Nullable
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
contextはmHostのgetContextメソッドで得られていることがわかりますが、Ctrl+左ボタンでmHostはFragmentHostCallbackクラスのオブジェクトであることがわかります.次にFragmentのmHostオブジェクトがどこで値を付けているかを知るだけでいいです.
我々のfragmentは一般的にfragmentManagerのbeginTransactionメソッドでFragmentTransactionを取得してaddを追加しますが、getSupportFragmentManagerで取得したのはFragmentManagerImpl、つまりFragmentManagerの実装クラス(後述)です.FragmentManagerImplのbeginTransactionメソッドを見てみましょう.
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
FragmentTransactionはFragmnetTransactionから継承されたBackStackRecordオブジェクトであり、BackStackRecordのaddメソッドは最終的にFragmentManagementのaddFragmentメソッドに戻ります(これはfragmentの起動プロセスに関連し、詳しくは説明しません):
public void addFragment(Fragment fragment, boolean moveToStateNow) {
...
if (moveToStateNow) {
moveToState(fragment);
}
void moveToState(Fragment f) {
moveToState(f, mCurState, 0, 0, false);
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
...
switch (f.mState) {
case Fragment.INITIALIZING:
...
f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
...
}
}
f.mHost=mHost、つまりfragmentでcontextを取得する際に使用されるFragmentHostCallbackクラスのオブジェクトmHostがFragmentManagement Implによって付与されていることがわかります.
私たちの問題は、そのmHostはどこから来たのかということになりました.
fragmentManagerImplのattachControlメソッドを参照してください.
public void attachController(FragmentHostCallback host,
FragmentContainer container, Fragment parent) {
if (mHost != null) throw new IllegalStateException("Already attached");
mHost = host;
mContainer = container;
mParent = parent;
}
mHostは、FragmentControllerによって呼び出される値をここに割り当てます.
public void attachHost(Fragment parent) {
mHost.mFragmentManager.attachController(
mHost, mHost /*container*/, parent);
}
fragmentControllerは誰だ?そのmHostはどこから来たのですか?
Fragmentを追加するのは、一般的にgetSupportFragmentManager()を使用します.beginTransaction()FragmentTransactionオブジェクトを取得します.FragmentActivityのgetSupportFragmentManagerメソッドを見てみましょう.
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
...
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
Activityは、finalタイプのFragmentControlオブジェクトのgetSupportFragmentManagerを使用してfragmentManagerを取得していることがわかります.
public class FragmentController {
private final FragmentHostCallback> mHost;
/**
* Returns a {@link FragmentController}.
*/
public static FragmentController createController(FragmentHostCallback> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback> callbacks) {
mHost = callbacks;
}
/**
* Returns a {@link FragmentManager} for this controller.
*/
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
...
}
FragmentControllerのgetSupportFragmentManagerは、関数を構築するパラメータFragmentHostCallbackオブジェクトのgetFragmentMnaagerImlから得られます.
public abstract class FragmentHostCallback extends FragmentContainer {
private final Activity mActivity;
final Context mContext;
private final Handler mHandler;
final int mWindowAnimations;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
...
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManager;
}
}
FragmentManagerから継承されるFragmentManagerImplを直接返します.
元のfragmentManagerとそのmHostオブジェクトは、FragmentActivityのfragmentControlオブジェクトによって取得されていました.
ここで私たちの問題は、FragmentControllerのmHostはどこから来たのかということになりました.
FragmentActivityが伝えたものです
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
LoaderManager mLoaderManager;
HostCallbacksを見てみましょう
class HostCallbacks extends FragmentHostCallback {
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
}
HostCallbackは、FragmentHostCallbackのコンストラクション関数を呼び出す現在のactivityオブジェクトを持っていることがわかります.
public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
this(context instanceof Activity ? (Activity) context : null, context, handler,
windowAnimations);
}
FragmentHostCallback(FragmentActivity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
}
FragmentHostCallback(Activity activity, Context context, Handler handler,
int windowAnimations) {
mActivity = activity;
mContext = context;
mHandler = handler;
mWindowAnimations = windowAnimations;
}
すべてが水面に捧げられた.mHostのcontextはここにある.
まとめてみます.
FragmentActivityにはfinalタイプのFragmentControllerオブジェクトがあり、FragmentControllerはHostCallbackオブジェクトmHost(mHostはcontext)を持ち、FragmentManagerもそのmHostによって作成され、FragmentControllerがattachControllerメソッドを呼び出したときにそのmHostに値を付与し(FragmentManagerのmHostとFragmentControllerのmHostは同じ)、FragmentのmHostはaddのときにFragmentManagerによって値を付与される.
実はすべてのソースはFragmentActivityが持っているFragmentControllerオブジェクトです!
足指で考えてもfragmentのgetContextメソッドで手に入れたのがその付着したActivityかもしれませんが、書きました...
いいね!