Fragment源码分析(一) 构造

转自:http://blog.csdn.net/hello__zero/article/details/38341795?utm_source=tuicool&utm_medium=referral


Fragment是Android3.0之后提供的api,被大家广泛所熟知的主要原因还是因为随即附带的ViewPager控件。虽然我并不喜欢用它,但是它确实是一个相对不错的控件。还是我的一贯作风,我将从源码上向大家展示什么是Fragment。我们先写一个简单的代码对Fragment有个直观的认识:(为了保证我们方便调试,我们可以直接使用V4提供的源码包)

[java]  view plain  copy
  1. FragmentTransaction t = getSupportFragmentManager().beginTransaction();  
  2.         t.add(android.R.id.content, new TestFragment1());  
  3.         t.commitAllowingStateLoss();  

通过这些代码,我们就可以生成一个Fragment,并且我们能在屏幕上直观的看到这个Fragment所要说明的界面。那么一个Fragment是否就是一个控件,或者是一个window?或者是视图的一部分?当然不是。我们来看Fragment的继承树:

[java]  view plain  copy
  1. public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener  

你根本看不到任何View的影子。我在加入M公司之前参加过不少公司的面试,面试官总是斩钉截铁的告诉我Fragment就是一个片段就是用来显示大屏幕下的一部分控件。他们这么坚定的问题在于被Fragment所带来的ViewPager这种好用的控件和可以在xml配置这个功能所蛊惑,他们缺乏对LayoutInflater源码的认识。实际上,这点,你不得不对Android这部分代码的开发者致敬,因为他让代码有了无限扩展的可能。

我们先来看下FragmentActivity:

[java]  view plain  copy
  1. android.support.v4.app.FragmentActivity  
[java]  view plain  copy
  1. @Override  
  2.     protected void onCreate(Bundle savedInstanceState) {  
  3.         mFragments.attachActivity(this, mContainer, null);  
  4.         // Old versions of the platform didn't do this!  
  5.  <pre name="code" class="java">       if (getLayoutInflater().getFactory() == null) {  
  6.             getLayoutInflater().setFactory(this);  
  7.         }  
  8.           

 
我们知道Activity才是Fragment的根,Fragment作为片段是相对Activity而言,Activity对于Fragment来说本质上是个控制器,用于分发不同的状态和业务。在onCreate的前半部分,有一个很重要的设置: 

[java]  view plain  copy
  1. if (getLayoutInflater().getFactory() == null) {  
  2.      getLayoutInflater().setFactory(this);  
  3.  }  
  4.    

这个是用来干嘛的呢?~实际上,你如果了解一点LayoutInflater的源码其实并不会感到陌生,因为这个接口是为了构造你的View而存在。这就是伟大的Androidsdk开发者给你提供的扩展机会,不论你配置的东西是否继承于View,只要你实现了这个接口,你就可以按照既定的规则构造出View。这个接口的实现方法在:

[java]  view plain  copy
  1. @Override  
  2.    public View onCreateView(String name, Context context, AttributeSet attrs) {  
  3.        if (!"fragment".equals(name)) {  
  4.            return super.onCreateView(name, context, attrs);  
  5.        }  
  6.        。。。  

我们先取前半部分代码,我们很清楚的看出,实际上fragment标签是被FragmentActivity特殊处理了。不知道你们是否理解了,如果不特殊处理,那么交给默认逻辑处理的话,你的对象由于不继承View一定会导致程序崩溃。那么我们接着往下看:

[java]  view plain  copy
  1. if (fragment == null) {  
  2.             fragment = Fragment.instantiate(this, fname);  
  3.             fragment.mFromLayout = true;  
  4.             fragment.mFragmentId = id != 0 ? id : containerId;  
  5.             fragment.mContainerId = containerId;  
  6.             fragment.mTag = tag;  
  7.             fragment.mInLayout = true;  
  8.             fragment.mFragmentManager = mFragments;  
  9.             fragment.onInflate(this, attrs, fragment.mSavedFragmentState);  
  10.             mFragments.addFragment(fragment, true);  
  11.   
  12.         }  
可以看出fragment的生成是通过Fragment的静态工厂方法帮你生成。而且生成之后将纳入mFragments的管理。那么什么是 mFragments?实际上mFragments是FragmentManager对象,这是整个Framgent管理中非常重要的对象。但是,我们还是没有看到View的影子,不要着急,我们接着往下读:

[java]  view plain  copy
  1. if (fragment.mView == null) {  
  2.             throw new IllegalStateException("Fragment " + fname  
  3.                     + " did not create a view.");  
  4.         }  
  5.         if (id != 0) {  
  6.             fragment.mView.setId(id);  
  7.         }  
  8.         if (fragment.mView.getTag() == null) {  
  9.             fragment.mView.setTag(tag);  
  10.         }  
  11.         return fragment.mView;  
发现了么?实际上,最终并不返回Fragment本身,而是返回Fragment的成员mView。但是我们并没有看到对这个成员的附值呀?实际上,在mFragments将Fragment add之后,已经对View进行赋值。不过我这里先卖个关子,下一章我们谈到Fragment的状态的时候我会回头来解释这个逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值