ViewPager+Fragment(二)装修房

上节课我们使用VF(ViewPager+Fragment)搭配使用做出了底部导航栏的效果,既然效果已经出来了为什么还需要写这篇文章呢?

1 毛坯房缺点

我们在每个Fragment中打上如下的log,然后点击导航菜单栏切换Fragment

  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        Log.i("TAG", "onCreateView: four");
        return inflater.inflate(R.layout.fragment_four, container, false);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.i("TAG", "onDestroyView: FourFragment");
    }

图1

我在这里说明下FragmentStatePagerAdapter和FragmentPagerAdapter都是Fragment适配器,这个适配器的作用是什么呢?就是缓存和预加载页面,在这个例子中一共四个页面,当我点击第三个页面的时候,调用了1的销毁方法和4的创建方法,而此时2并没有销毁,仍然在缓存中只是不可见而已,当我们切换到2的页面时候,同理,4销毁,1创建,3不改变状态只是不可见。

猛地一看,哎呦,不错啊,安卓一直都需要我去缓存数据终于懂得主动帮我缓存数据了,当我很开心的时候,发现了很严重的问题:

我点到第3个就觉得没有意思了,不往下点了,可是系统仍然会预加载第四个界面的数据!如果第四个界面很简单那还好,要是数据很多,加杂各种动画,呵呵,那你的程序在内存中的消耗将无比巨大,这对于一个追求完美的程序员来说是不能容忍的

2 懒加载

不会偷懒的程序员不是好的程序员

1 我点击哪个页面加载哪个页面的数据,下一个页面的数据我不加载

2 刚刚加载过的页面如果马上又打开,不会去重新加载数据而是使用缓存数据
package com.viewpager02.fragments;


import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * A simple {@link Fragment} subclass.
 */
public abstract class CommentFragment extends Fragment {
    /**
     * 标记已加载完成,保证懒加载只能加载一次
     */
    private boolean hasLoaded = false;
    /**
     * 标记Fragment是否已经onCreate
     */
    private boolean isCreated = false;
    /**
     * 界面对于用户是否可见
     */
    private boolean isVisibleToUser = false;
    private View view;

    public CommentFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        init(getView(inflater, getLayoutId(), container), savedInstanceState);
        return view;
    }

    private View getView(LayoutInflater inflater, int layoutId, ViewGroup container) {
        return inflater.inflate(layoutId, container, false);
    }


    public void init(View view, Bundle savedInstanceState) {
        isCreated = true;
        this.view = view;
        lazyLoad(this.view, savedInstanceState);
    }
    /**
     * 监听界面是否展示给用户,实现懒加载
     * 这个方法也是网上的一些方法用的最多的一个,我的思路也是这个,不过把整体思路完善了一下
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        Log.i("TAG", "setUserVisibleHint: ");
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser = isVisibleToUser;//注:关键步骤
        lazyLoad(view, null);
    }


    /**
     * 懒加载方法,获取数据什么的放到这边来使用,在切换到这个界面时才进行网络请求
     */
    private void lazyLoad(View view, Bundle savedInstanceState) {

        //如果该界面不对用户显示、已经加载、fragment还没有创建,
        //三种情况任意一种,不获取数据
        if (!isVisibleToUser || hasLoaded || !isCreated) {
            return;
        }
        lazyInit(view, savedInstanceState);
        hasLoaded = true;//注:关键步骤,确保数据只加载一次
    }

    /**
     * 子类必须实现的方法,这个方法里面的操作都是需要懒加载的
     */
    public abstract void lazyInit(View view, Bundle savedInstanceState);
    public abstract int getLayoutId();


    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isCreated = false;
        hasLoaded = false;
    }

}
public class OneFragment extends CommentFragment {


    @Override
    public void lazyInit(View view, Bundle savedInstanceState) {
        Log.i("TAG", "lazyInit: One!大量数据");//这里处理耗时操作请求数据
    }

    @Override
    public int getLayoutId() {
        return R.layout.fragment_one;//获取布局文件
    }
}

查看Log日志

这里写图片描述

果然如我们所料,点击一个新的Fragment才会加载一个的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值