ViewPager和Fragment的一個實例坑

這里主要涉及到Fragment在ViewPager中顯示時,一個同步和異步的問題。

這樣一個場景:
你做一個播放音樂的App,在界面底部有一個控制欄可以開始\暫停音樂的播放,點擊控制欄可以進入播放詳情。假設你剛好點擊了播放,然后再進入播放詳情頁面(Activity實現(xiàn)),你希望一進去會有一個動畫效果,這個動畫在Fragment里面實現(xiàn)。里面由ViewPager+Fragment實現(xiàn),左右滑動可切換歌曲。

也許會有下面的代碼

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                    getCur_fragment().startRotate();  //開始動畫
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

要執(zhí)行動畫,那么界面必須出來,這么做,動畫肯定不會執(zhí)行,因為界面還沒出來。

那么,F(xiàn)ragment的界面時什么時候出來的呢?

ViewPager的populate()方法

        public void populate(){
        //.......
        mAdapter.setPrimaryItem(this, mCurItem, curItem != null ? curItem.object : null);
        mAdapter.finishUpdate(this);   //FragmentPageAdapter進行了重寫
        }
 @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commitNowAllowingStateLoss();
            mCurTransaction = null;
        }
    }

FragmentPageAdapter重寫了該方法,也就是去執(zhí)行Fragment棧中所有操作(mCurTransaction.add(container.getId(), fragment);),而執(zhí)行棧中的操作commitNow是一個同步任務。也就是說,此時Fragment才被attach到Activity中,F(xiàn)ragment中的View才被添加到ViewPager中。

現(xiàn)在問題在于,當監(jiān)聽器中的onPageSelected()方法執(zhí)行的時候,ViewPager的populate()方法執(zhí)行了嗎?沒有!

public void setCurrentItem(){
        if (mFirstLayout) {         //第一次布局,默認為true
            // We don't have any idea how big we are yet and shouldn't have any pages either.
            // Just set things up and let the pending layout handle things.
            mCurItem = item;
            if (dispatchSelected) {
                dispatchOnPageSelected(item);    //該方法執(zhí)行
            }
            requestLayout();  //發(fā)送一個異步的布局消息
        } else {
            populate(item);
            scrollToItem(item, smoothScroll, velocity, dispatchSelected);
        }
}

也就是說,當你調(diào)用了setCurrentItem(),監(jiān)聽器的回調(diào)方法會同步執(zhí)行,而populate()方法卻要在下一個消息中執(zhí)行。所以此時,F(xiàn)ragment的對象確實被創(chuàng)建出來了,他的生命周期方法卻還沒有執(zhí)行。

解決方法:

  1. 在創(chuàng)建Fragment的時候,通過setArgument方法設置參數(shù)
  2. 在onAttach()中拿到Activity的引用,進而調(diào)用他的方法去獲得參數(shù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容