標籤:android viewpager fragment
Fragment是Android3.0之後提供的api,被大家廣泛所熟知的主要原因還是因為隨即附帶的ViewPager控制項。雖然我並不喜歡用它,但是它確實是一個相對不錯的控制項。還是我的一貫作風,我將從源碼上向大家展示什麼是Fragment。我們先寫一個簡單的代碼對Fragment有個直觀的認識:(為了保證我們方便調試,我們可以直接使用V4提供的源碼包)
FragmentTransaction t = getSupportFragmentManager().beginTransaction(); t.add(android.R.id.content, new TestFragment1()); t.commitAllowingStateLoss();
通過這些代碼,我們就可以產生一個Fragment,並且我們能在螢幕上直觀的看到這個Fragment所要說明的介面。那麼一個Fragment是否就是一個控制項,或者是一個window?或者是視圖的一部分?當然不是。我們來看Fragment的繼承樹:
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
你根本看不到任何View的影子。我在加入M公司之前參加過不少公司的面試,面試官總是斬釘截鐵的告訴我Fragment就是一個片段就是用來顯示大螢幕下的一部分控制項。他們這麼堅定的問題在於被Fragment所帶來的ViewPager這種好用的控制項和可以在xml配置這個功能所蠱惑,他們缺乏對LayoutInflater源碼的認識。實際上,這點,你不得不對Android這部分代碼的開發人員致敬,因為他讓代碼有了無限擴充的可能。
我們先來看下FragmentActivity:
android.support.v4.app.FragmentActivity
@Override protected void onCreate(Bundle savedInstanceState) { mFragments.attachActivity(this, mContainer, null); // Old versions of the platform didn't do this! <pre name="code" class="java"> if (getLayoutInflater().getFactory() == null) { getLayoutInflater().setFactory(this); }
我們知道Activity才是Fragment的根,Fragment作為片段是相對Activity而言,Activity對於Fragment來說本質上是個控制器,用於分發不同的狀態和業務。在onCreate的前半部分,有一個很重要的設定:
if (getLayoutInflater().getFactory() == null) { getLayoutInflater().setFactory(this); }
這個是用來幹嘛的呢?~實際上,你如果瞭解一點LayoutInflater的源碼其實並不會感到陌生,因為這個介面是為了構造你的View而存在。這就是偉大的Androidsdk開發人員給你提供的擴充機會,不論你配置的東西是否繼承於View,只要你實現了這個介面,你就可以按照既定的規則構造出View。這個介面的實現方法在:
@Override public View onCreateView(String name, Context context, AttributeSet attrs) { if (!"fragment".equals(name)) { return super.onCreateView(name, context, attrs); } 。。。
我們先取前半部分代碼,我們很清楚的看出,實際上fragment標籤是被FragmentActivity特殊處理了。不知道你們是否理解了,如果不特殊處理,那麼交給預設邏輯處理的話,你的對象由於不繼承View一定會導致程式崩潰。那麼我們接著往下看:
if (fragment == null) { fragment = Fragment.instantiate(this, fname); fragment.mFromLayout = true; fragment.mFragmentId = id != 0 ? id : containerId; fragment.mContainerId = containerId; fragment.mTag = tag; fragment.mInLayout = true; fragment.mFragmentManager = mFragments; fragment.onInflate(this, attrs, fragment.mSavedFragmentState); mFragments.addFragment(fragment, true); }可以看出fragment的產生是通過Fragment的靜態Factory 方法幫你產生。而且產生之後將納入mFragments的管理。那麼什麼是mFragments?實際上mFragments是FragmentManager對象,這是整個Framgent管理中非常重要的對象。但是,我們還是沒有看到View的影子,不要著急,我們接著往下讀:
if (fragment.mView == null) { throw new IllegalStateException("Fragment " + fname + " did not create a view."); } if (id != 0) { fragment.mView.setId(id); } if (fragment.mView.getTag() == null) { fragment.mView.setTag(tag); } return fragment.mView;發現了嗎?實際上,最終並不返回Fragment本身,而是返回Fragment的成員mView。但是我們並沒有看到對這個成員的附值呀?實際上,在mFragments將Fragment add之後,已經對View進行賦值。不過我這裡先賣個關子,下一章我們談到Fragment的狀態的時候我會回頭來解釋這個邏輯。