Fragment的懶加載(轉)

1.什么是fragment懶加載以及為什么要使用fragment懶加載。

先看下Demo實現(xiàn)的效果吧迈着。大家對這種效果一定不陌生竭望,知乎,掘金等app都用到了這種效果裕菠。

image

<figcaption></figcaption>

這里探索的懶加載是當viewpager 結合tablayout時,多個fragment在進行數(shù)據(jù)加載的時候咬清,當且僅當fragment對用戶可見的時候,才進行數(shù)據(jù)加載奴潘,這里的數(shù)據(jù)加載可以是網(wǎng)絡請求旧烧,數(shù)據(jù)庫請求,是需要消耗資源的萤彩,如果不使用懶加載粪滤,對于那些用戶未打開的頁面,由于viewpager的加載機制雀扶,即使用戶未打開的fragment也有可能進行數(shù)據(jù)加載杖小,造成資源白白的浪費,因此為了良好的用戶體驗肆汹,懶加載是有必要的。

2.fragment懶加載的實現(xiàn)方式以及封裝予权。

fragment懶加載實現(xiàn)的關鍵在于其的setUserVisibleHint(isVisibleToUser: Boolean)方法昂勉,該方法在fragment對用戶由可見變?yōu)椴豢梢娨约坝刹豢梢娮優(yōu)榭梢姇r都會回調。我們創(chuàng)建抽象AbstractLazyInitFrag扫腺,對其進行封裝岗照。首先我們引入isVisibleToUser變量,負責保存當前fragment對用戶的可見狀態(tài)笆环。同時還有幾個值得注意的地方:

  1. setUserVisibleHint(isVisibleToUser: Boolean)方法的回調時機并沒有與fragment的生命周期有確切的關聯(lián)攒至,比如說,回調時機有可能在onCreateView方法之后躁劣,也可能在onCreateView方法之前迫吐。因此,必須引入一個標志位isPrepareView判斷view是否創(chuàng)建完成账忘,不然志膀,很容易會造成空指針異常。我們初始化該變量為false,在onViewCreated中鳖擒,也就是view創(chuàng)建完成后溉浙,將其賦值為true。代碼中是這樣:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        isPrepareView = true
    }
復制代碼
  1. 數(shù)據(jù)初始化只應該加載一次蒋荚,因此戳稽,引入第二個標志位,isInitData,初始為false,在數(shù)據(jù)加載完成之后期升,將其賦值為true广鳍。至此,我們的懶加載方法考慮了所有條件吓妆。也就是當isVisibleToUsertrue赊时,isInitDatafalseisPrepareViewtrue時,進行數(shù)據(jù)加載行拢,并且加載后為了防止重復調用祖秒,將isInitData賦值為true。代碼如下:
private fun lazyInitData() {
        if (!isInitData && isVisibleToUser && isPrepareView) {
            isInitData = true
            initData()
        }
    }
復制代碼

其中initData()為抽象方法舟奠,由子類實現(xiàn)竭缝,在這里操作數(shù)據(jù)加載的邏輯。

  1. 該方法的調用時機沼瘫。首先是 setUserVisibleHint(isVisibleToUser: Boolean)方法中是必須調用的抬纸。代碼如下:
/*當fragment由可見變?yōu)椴豢梢姾筒豢梢娮優(yōu)榭梢姇r回調*/
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        this.isVisibleToUser = isVisibleToUser //標志位保存fragment對用戶的可見狀態(tài)
        lazyInitData()
    }
復制代碼

其次,很容易忽略的一點耿戚。對于上圖中第一個fragment湿故,如果setUserVisibleHint(isVisibleToUser: Boolean)方法在onCreateView之前調用的話,如果懶加載方法只在setUserVisibleHint(isVisibleToUser: Boolean)中調用,那么該fragment將只能在被主動切換一次之后才能加載數(shù)據(jù)阿趁,這肯定是不可能的,因此坛猪,我們需要在view創(chuàng)建完成之后脖阵,也進行一次調用。思來想去墅茉,在onActivityCreated方法中是最合適的命黔。我們在繼承的時候,在onViewCreated方法中進行一些初始化就行了,這樣不會引起沖突就斤。代碼如下:

/*fragment生命周期中onViewCreated之后的方法 在這里調用一次懶加載 避免第一次可見不加載數(shù)據(jù)*/
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        lazyInitData()
    }

3.完整代碼:

public abstract class BaseLazyFragment extends Fragment {
    private Context mContext;
    private View mRootView;
    private boolean theFragmentVisible;//判斷當前fragment是否可見
    private boolean isPrepared;//通過此標記位防止空指針
    private boolean isInitData=false;//此標記位是只能初始化一次數(shù)據(jù)

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext=getActivity();
    }


    //該方法會在不同的Fragment切換時才會調用
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        if (isVisibleToUser){//isVisibleToUser用于判斷當前Fragment是否可見
            onVisibleDo();
        }else{
            onUnVisibleDo();
        }
        super.setUserVisibleHint(isVisibleToUser);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mRootView==null){
            mRootView=LayoutInflater.from(mContext).inflate(getLayoutId(),null);
        }
        return mRootView;
    }


    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        //設置布局可見悍募,且數(shù)據(jù)準備歐克
        theFragmentVisible=true;
        isPrepared=true;
        //如果setUserVisibleHint()在onCreateView()之前調用。
        // 那么該fragment將只能在被主動切換一次之后才能加載數(shù)據(jù)洋机,這肯定是不可能的搜立,因此,我們需要在view創(chuàng)建完成之后槐秧,也進行一次調用
        lazyLoad();
    }

    @Override
    public boolean getUserVisibleHint() {
        return isVisible();
    }


    private void lazyLoad(){
        if (isPrepared && theFragmentVisible && !isInitData){
            loadData();
            isInitData=true;
        }
    }
    //頁面不可見:
    private void onUnVisibleDo(){
        theFragmentVisible=false;

    }

    //頁面可見:
    private void onVisibleDo(){
        theFragmentVisible=true;
        lazyLoad();
    }
    
    //獲取子布局id
    public abstract int getLayoutId();
    //加載數(shù)據(jù)
    public abstract void loadData();
}

4.原文出處:

原文出處

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市忧设,隨后出現(xiàn)的幾起案子刁标,更是在濱河造成了極大的恐慌,老刑警劉巖址晕,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膀懈,死亡現(xiàn)場離奇詭異,居然都是意外死亡谨垃,警方通過查閱死者的電腦和手機启搂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刘陶,“玉大人胳赌,你說我怎么就攤上這事〕赘簦” “怎么了疑苫?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纷责。 經(jīng)常有香客問我捍掺,道長,這世上最難降的妖魔是什么再膳? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任挺勿,我火速辦了婚禮,結果婚禮上喂柒,老公的妹妹穿的比我還像新娘不瓶。我一直安慰自己禾嫉,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布湃番。 她就那樣靜靜地躺著夭织,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吠撮。 梳的紋絲不亂的頭發(fā)上尊惰,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音泥兰,去河邊找鬼弄屡。 笑死,一個胖子當著我的面吹牛鞋诗,可吹牛的內容都是我干的膀捷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼削彬,長吁一口氣:“原來是場噩夢啊……” “哼全庸!你這毒婦竟也來了?” 一聲冷哼從身側響起融痛,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤壶笼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后雁刷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體覆劈,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年沛励,在試婚紗的時候發(fā)現(xiàn)自己被綠了责语。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡目派,死狀恐怖坤候,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情企蹭,我是刑警寧澤铐拐,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站练对,受9級特大地震影響遍蟋,放射性物質發(fā)生泄漏。R本人自食惡果不足惜螟凭,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一虚青、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧螺男,春花似錦棒厘、人聲如沸纵穿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谓媒。三九已至,卻和暖如春何乎,著一層夾襖步出監(jiān)牢的瞬間句惯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工支救, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抢野,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓各墨,卻偏偏與公主長得像指孤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贬堵,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容