我们先看下fragment的getContext方法:

    @Nullablepublic 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方法:

@Overridepublic FragmentTransaction beginTransaction() {return new BackStackRecord(this);}

可以看到我们得到的FragmentTransaction是一个BackStackRecord对象,该类继承自FragmnetTransaction,而BackStackRecord的add方法最终还是回到FragmentManagerImpl的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是由FragmentManagerImpl赋值的。

那我们的问题就变成了:它的mHost哪里来的?

我们看到fragmentManagerImpl的attachController方法:

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类型的FragmentController对象的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<E> 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;}
}

直接返回一个FragmentManagerImpl,它继承自FragmentManager。

原来fragmentManager和其mHost对象都是由FragmentActivity中的fragmentController对象得到,

到这里我们的问题变成了:FragmentController中的mHost是哪来的?

就是FragmentActivity传入的:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());LoaderManager mLoaderManager;

我们看一下HostCallbacks:

class HostCallbacks extends FragmentHostCallback<FragmentActivity> {public HostCallbacks() {super(FragmentActivity.this /*fragmentActivity*/);}
}

可以看到HostCallbacks持有一个当前的activity对象,调用FragmentHostCallback的构造函数:

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,但是还是写了。。。

喜欢点个赞!!

Fragment中getContext得到的context从哪来?相关推荐

  1. 在fragment中引用ListView

    前言:前段时间想在fragment中做出一个ListView列表,不过一直都是UI的闪退,让我一直不知道怎么办,很是苦恼,不过后来才发现了一个新的东西叫做ListFragment,所以这次主要是讲一下 ...

  2. adapter调用fragment中的方法

    adapter调用fragment中的方法 前言:昨天遇到一个技术难题,对于我来说哈.我写的demo需求是在fragment中放一个RecyclerView,然后RecyclerView显示一些简单的 ...

  3. Fragment 中使用 getLayoutInflater() 的问题

    问题: 我想在一个Fragment的ListView中显示我的搜索结果 但在这里报错: LayoutInflater inflater = getLayoutInflater(); "The ...

  4. Android --- 动态获取定位权限时: Fragment 中 onRequestPermissionsResult 方法不执行

    今天我在写百度地图 API 定位功能的时候遇到了这样一个问题,需要在打开 APP 首页的时候动态获取定位权限,然后我的代码是这样写的(在 Fragment 中) @Nullablepublic Vie ...

  5. AndroidStudio_安卓原生开发_在fragment中如何使用Toast_以及SharedPreferences---Android原生开发工作笔记149

    1.在fragment中怎么像在activity中使用Toast呢? Toast.makeText(getActivity(), "说明此设备不支持蓝牙操作", Toast.LEN ...

  6. 如何在fragment中添加ListView,并设置ListView中条目的值

    最后界面如下: 制作思路:首先在一个Activity中做出左右fragment(碎片的意思),然后再在左边的fragment中加入ListView控件,再用编程的方法给ListView控件设置条目,即 ...

  7. 在fragment中简单应用百度地图定位

    一个fragment中简单应用,就项目而言可能没有框架但是可以使用 public class app_safety_Fragment extends Fragment implements OnGet ...

  8. Android studio 微信APP之Fragment中使用ReclerView

    Android studio 微信APP之Fragment中使用ReclerView 如题,本次实验的内容就是在已经创建好的微信程序的首页处,在fragment控件中增加ReclerView控件,实现 ...

  9. Android多层嵌套Fragment中调用系统相机拍照以及裁剪的相关问题解决

    多层嵌套Fragment中调用系统相机拍照.裁剪 最近公司项目有频繁使用相机拍照的需求,然后频繁的实际使用过程中遇到很多大大小小的坑,在此记录下. (ps.关于一些拍照后图片旋转.裁剪设置返回数据为t ...

最新文章

  1. 基于用户投票的排名算法(五):威尔逊区间
  2. 高德经纬度距离计算php,计算两个经纬度之间的距离 单位(m)
  3. 山寨一把QQ移动终端聊天框,网页版效果其实也很好的!
  4. IDEA突然自动关闭然后无法启动
  5. 美印钞一万亿焉知祸福?
  6. 玩转Github —— Octotree Chrome插件
  7. spring data jpa update
  8. 元数据是什么意思_抖音飞瓜数据什么意思,飞瓜数据有什么用
  9. 6、mysql与suse查看版本信息
  10. NettyMina (转)
  11. iOS 审核被拒绝问题汇总
  12. 三菱fx2n做从站的modbus通讯_第476期丨关于三菱PLC中除法的问题;请教一个监测电流的小物件或方法...
  13. 采用SyncToy2.1软件实现两台电脑间文件的自动实时同步(亲测有效)
  14. Java 检测字符是否存在手机号或返回该手机号
  15. 谷歌浏览器误删怎么办
  16. Springboot毕设项目基于批示的督查督办管理系统c6m0djava+VUE+Mybatis+Maven+Mysql+sprnig)
  17. 国税服务器反回文件错误,电子税务局常见问题解答电子税务局异常转办(一).pdf...
  18. mac加密_如何加密Mac的Time Machine备份
  19. 基于js实现的简易记账小本
  20. uc浏览器视频缓存合并工具

热门文章

  1. Python机器学习入门笔记(1)—— Scikit-learn与特征工程
  2. 数据库身份证号加密密码加密_使用基于密码的加密保护会议室数据库
  3. word中表格出现无法自动换页问题
  4. SAXReader简单实例分析
  5. 智伴机器人tf卡下载地址_入门操作详解教你如何玩转智伴1X机器人!
  6. BUUCTF-PWN刷题记录-17
  7. python 沪江_Python基础篇 -- 字符串
  8. 解决启动filebeat时遇到Exiting: error unpacking config data: more than one namespace configured accessing错误
  9. python解包(Unpacking)
  10. idea 断点线程_在IntelliJ IDEA中多线程并发代码的调试方法详解