ViewPager+Fragment LazyLoad最優(yōu)解

ViewPager+Fragment的模式再常見不過了,以國民應(yīng)用微信為例,假設(shè)微信也是ViewPager+Fragment的實(shí)現(xiàn)方式,那表現(xiàn)形式上就是一個(gè)ViewPager管理了四個(gè)Fragment,左右滑動來回切換。但是ViewPager有一個(gè)奇葩的特性叫:預(yù)加載,比如打開微信,首先看到的是第一個(gè)Tab(微信),但事實(shí)上第二個(gè)Tab(通訊錄)已經(jīng)加載好了。當(dāng)選擇第二個(gè)Tab(通訊錄),第三個(gè)Tab(發(fā)現(xiàn))已經(jīng)加載好了,以此類推。
但上訴ViewPager+Fragment的這種組合并不完美,因?yàn)槲蚁M脩暨x擇了哪個(gè)Tab再去加載哪個(gè)Tab的數(shù)據(jù),而不要去做預(yù)加載,假如當(dāng)前頁面和預(yù)加載頁面都有大量的網(wǎng)絡(luò)請求,可能就會比較慢,有很多請求在排隊(duì)。關(guān)于這個(gè)問題,也有很偏激的做法,比如棄用ViewPager,自己手動管理Fragment,或者直接禁掉ViewPager預(yù)加載。有一種比較合適的方案是保持ViewPager預(yù)加載的特性,但是只初始化View,選擇當(dāng)前Tab的時(shí)候再進(jìn)行網(wǎng)絡(luò)請求。關(guān)于這一方案的實(shí)現(xiàn),也是眾說紛紜,千奇百怪。最后,還是選擇男神Stay的方案。
直接上代碼。

public abstract class BasePageFragment extends Fragment {

    protected boolean isViewInitiated;
    protected boolean isVisibleToUser;
    protected boolean isDataInitiated;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        isViewInitiated = true;
        prepareFetchData();
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser = isVisibleToUser;
        prepareFetchData();
    }

    public abstract void fetchData();

    public boolean prepareFetchData() {
        return prepareFetchData(false);
    }

    public boolean prepareFetchData(boolean forceUpdate) {
        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
            fetchData();
            isDataInitiated = true;
            return true;
        }
        return false;
    }

}

這是一個(gè)父類,看代碼這里只有一個(gè)setUserVisibleHint需要說下,這是一個(gè)相當(dāng)生僻的方法,我們可以用這個(gè)方法來判斷當(dāng)前UI是否可見,所以在prepareFetchData方法里我們做如下判斷:就是當(dāng)前UI可見,并且fragment已經(jīng)初始化完畢,如果網(wǎng)絡(luò)數(shù)據(jù)未加載,那么請求數(shù)據(jù),或者需要強(qiáng)制刷新頁面,那么也去請求數(shù)據(jù),So easy。子Fragment只需要繼承父類,實(shí)現(xiàn)抽象方法,在fetchData()里做網(wǎng)絡(luò)請求或者其他耗時(shí)操作即可。再在寫個(gè)子類吧。

public class PageFragment extends BasePageFragment {
    
    public static PageFragment newInstance(String title){
        PageFragment fragment = new PageFragment();
        Bundle args = new Bundle();
        args.putString("key_fragment_title", title);
        fragment.setArguments(args);
        return fragment;
    }

    private String title;
    private TextView tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        title = getArguments().getString("key_fragment_title");
        Trace.d(title + ":onCreate");
    }
    
    @Override
    public void onResume() {
        super.onResume();
        Trace.d(title + ":onResume");
    }
    
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Trace.d(title + ":onCreateView");
        tv = new TextView(getActivity());
        return tv;
    }

    @Override
    public void fetchData() {
        tv.setText(title);
        /** * 在這里請求網(wǎng)絡(luò)。 */
    }
        
}

如果你也有這樣的需求或者煩惱,保證藥到病除。

有同學(xué)說實(shí)踐過程中遇到了些問題,比如Fragment只刷新一次,這個(gè)問題只要手動調(diào)用prepareFetchData(),傳true即可強(qiáng)制刷新了。還有同學(xué)質(zhì)疑setUserVisibleHint()和onActivityCreated()的執(zhí)行先后的問題。關(guān)于這個(gè)請看下圖。

1.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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