學(xué)習(xí)Android已經(jīng)四個(gè)月了,一直都沒有寫總結(jié)或者新的的習(xí)慣,有時(shí)候?qū)W習(xí)到了一些新鮮的知識(shí)也沒有及時(shí)的記錄下來,為了改變自己,今天就從剛學(xué)的片段管理知識(shí)講起吧。有說錯(cuò)什么的,有大神看到也請(qǐng)指出,畢竟還是只小菜雞。
首先從Fragment的生命周期說起,F(xiàn)ragment依賴于Activity,只有在Activity執(zhí)行onCreate創(chuàng)建之后Fragment才執(zhí)行onAttach、onCreate、onCreatView、onActivityCreated等方法,這些知識(shí)網(wǎng)上可以快速的找到,分享鏈接http://www.cnblogs.com/purediy/p/3276545.html,這篇文章已經(jīng)很好的闡述了Fragment和Activity的聯(lián)系,這里我就不多說了。我想說的是Fragment的兩個(gè)比較重要的方法:onCreatView()和onDestoryView(),前者負(fù)責(zé)創(chuàng)建一個(gè)view顯示片段內(nèi)容,后者從字面上理解看似是銷毀了view,其實(shí)view卻并沒有被銷毀,view的引用還在,成員變量也還在,這跟Activity的onDestory是有區(qū)別的,既然引用還在,那么在Fragment重新onCreatView的時(shí)候就不需要再重新創(chuàng)建一個(gè)新的view了,成員變量也不需要重新賦值,但是如果我們直接判斷if(view!=null)就return view的話,那么就會(huì)報(bào)下面這個(gè)異常:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
這個(gè)異常告訴我們,子視圖已經(jīng)被關(guān)聯(lián)在一個(gè)父容器里面了,我們要先對(duì)父容器調(diào)用removeView()移除掉這個(gè)view才行才行,怎么做呢?很簡(jiǎn)單,我們只需要在onDestoryView()中添加上一句代碼:
@Override
public void onDestroyView() {
super.onDestroyView();
((ViewGroup)view.getParent()).removeView(view);
}
這樣我們就不需要對(duì)已有的view和成員變量重新賦值,達(dá)到了一個(gè)小小優(yōu)化的目的。
在這里我引用了網(wǎng)友分享的知識(shí),上鏈接:http://www.cnblogs.com/jack-1900/p/3874228.html
緊接著另外一個(gè)問題就是Fragment切換的問題,我在開發(fā)項(xiàng)目過程中感覺到Fragment切換有時(shí)會(huì)伴隨著卡頓現(xiàn)象,在網(wǎng)上查找資料后,按照各路大神的指點(diǎn)和經(jīng)驗(yàn),首先判斷是Fragment在onCreatView初始化中做了比較長(zhǎng)的耗時(shí)操作,于是我按照上面的優(yōu)化方法,先優(yōu)化了查找控件等一些初始化事件,并在Fragment的onCreatView執(zhí)行開始時(shí)到onResume結(jié)束記錄了總執(zhí)行耗時(shí),得到的都是100ms以上的結(jié)果,因此我想可能是片段切換的方式存在問題。
我使用的Fragment切換的方法參照的是ApiDemo的FragmentStackFragmentSupport等,Demo里面使用到的切換方法有add(),repalce(),使用回退棧來保存上一個(gè)片段狀態(tài)或者返回棧中的片段狀態(tài)(不知道這樣描訴有沒有錯(cuò),或者有沒有說清楚。。。具體代碼大家可以看ApiDemo),例如:
Fragment newFragment = FragmentStackSupport.CountingFragment.newInstance(mStackLevel);
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();----添加片段
FragmentManager fm = getChildFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack(fm.getBackStackEntryAt(0).getId(),
FragmentManager.POP_BACK_STACK_INCLUSIVE);------回退到棧中某個(gè)狀態(tài)
}
Fragment newFragment = FragmentStackSupport.CountingFragment.newInstance(mStackLevel);
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, newFragment);------切換片段
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);------往棧中添加狀態(tài)
ft.commit();
按照Demo的這些方法我們可以對(duì)片段進(jìn)行管理,但是切換片段我們只使用add()方法網(wǎng)上層添加片段的話,會(huì)出現(xiàn)重影的問題,使用replace()替換的話就會(huì)出現(xiàn)現(xiàn)在我想要說的片段卡頓問題,不知道是不是replace()這個(gè)方法一定會(huì)出現(xiàn)大約100多ms的耗時(shí)操作(還不能確定大家都是不是這樣)。
以上的推論只是我個(gè)人的見解,具體原因因?yàn)樵创a看不到,我也不是很肯定,不過參考了網(wǎng)上的大神,還是讓我找到了一個(gè)替代replace()的片段切換方式,那就是hide()和show();當(dāng)我們使用到的片段常用不需要銷毀時(shí),我們可以使用這個(gè)方法來做,上代碼:
FragmentTransaction bt = fm.beginTransaction();
if(homeFragment.isAdded()){
bt.show(homeFragment);-----如果該片段已經(jīng)被添加,則顯示即可;
}else{
bt.add(R.id.frame_layout, homeFragment);------如果該片段未被添加,則添加
}
bt.commit();
FragmentTransaction bt = fm.beginTransaction();-----在已經(jīng)add的homeFragment上添加Fragment
bt.hide(homeFragment);---------先隱藏當(dāng)前Fragment
if(myFragment.isAdded()){
bt.show(myFragment);
}else{
bt.add(R.id.frame_layout, myFragment);--------按照同樣的方法顯示一個(gè)片段
}
bt.commit();
通過isAdded()、show(Fragment)、add(layoutId,Fragment)這三個(gè)方法就可以取代replace()這個(gè)方法啦,耗時(shí)的操作也可以避免了。
這是引用網(wǎng)友知識(shí)的原址:http://www.yrom.net/blog/2013/03/10/fragment-switch-not-restart/#
大家要是看不明白我的可以去看原作寫的。
就先記錄到這了,這些片段替換的操作都是我們手動(dòng)可控制的,如果是tabhost的話那就不太清楚了,下一個(gè)需要去研究的問題就是tabhost切換Fragment時(shí),片段的生命周期問題。到時(shí)候再看看研究的如何。睡覺去。。。。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。