[Android]Fragment源碼分析(一) 構造

來源:互聯網
上載者:User

標籤: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的狀態的時候我會回頭來解釋這個邏輯。




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.