记录ViewPage+Fragment嵌套ViewPage+Fragment滑动时内部嵌套卡顿的问题和实现Fragment的懒加载

先说ViewPage+Fragment嵌套ViewPage+Fragment滑动时内部嵌套卡顿和白屏的问题:具体导致原因没有深入去追究,只记录两种实现方案:
- **第一种就是将内部的Fragment替换掉,写一个抽象的Base类,Base类中的布局就一个容器,见代码:

Base类

public abstract class BasePage {

    public Activity mActivity;

    public View mRootView;//布局对象

    public TextView tvTitle;//标题对象

    public FrameLayout flContent;//内容

    public BasePage(Activity mActivity) {
        this.mActivity = mActivity;
        init();
        initData();
    }


    private void init() {
        mRootView = View.inflate(mActivity, R.layout.base_pager, null);
        flContent = (FrameLayout) mRootView.findViewById(R.id.fl_content);
        flContent.addView(initView());
    }

    /**
     * 初始化布局
     */
    public abstract View initView();

    /**
     * 初始化数据
     */
    public abstract void initData();
}

让子类实现该抽象类,并将布局返回即可,见代码:

public class ExtendsMyFragment extends BasePage {
    private MyViewPage viewPager;
    private TabLayout tabLayout;
    private List<BasePage> list;
    private BasePage fragment1, fragment2, fragment3, fragment4;
    private FragmentManager manager;
    private List<String> titles;

    public ExtendsMyFragment(Activity activity) {
        super(activity);
    }

    private void addFragment() {
        list = new ArrayList<>();
        fragment1 = new MytoFragment(mActivity);
        fragment2 = new MytoFragment(mActivity);
        fragment3 = new MytoFragment(mActivity);
        fragment4 = new MytoFragment(mActivity);
        list.add(fragment1);
        list.add(fragment2);
        list.add(fragment3);
        list.add(fragment4);
    }

    @Override
    public View initView() {
        View view = LayoutInflater.from(mActivity).inflate(R.layout.extends_fragemnt, null, false);
        viewPager = (MyViewPage) view.findViewById(R.id.viewpage);
        tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
        return view;
    }

    @Override
    public void initData() {
        addFragment();
        titles = new ArrayList<>();
        titles.add("菜单1");
        titles.add("菜单2");
        titles.add("菜单3");
        titles.add("菜单4");
        viewPager.setAdapter(new MyAdapter());
        tabLayout.setupWithViewPager(viewPager);
    }

    //注意,此时已经不是Fragment,所以不用继承FragmentPagerAdapter而是继承PagerAdapter 
    class MyAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {

            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            BasePage pager = list.get(position);
            container.addView(pager.mRootView);
//            pager.initData();//初始化数据。。。。不要放在此处初始化数据,否则会预加载下一个页面
            return pager.mRootView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return titles.get(position);
        }
    }
}

然后MainActivity中的代码和ExtendsMyFragment 中的代码基本一样就不贴了,只是这样虽然实现了嵌套滑动,但总体步骤还是略显繁琐,效果图如下:
这里写图片描述

下面介绍第二种实现方式废话不多说,直接上代码:

public class MainActivity extends AppCompatActivity {
    private ViewPager viewPager;
    private TabLayout tabLayout;
    private List<Fragment> list;
    private MyFragment2 fragment2, fragment3, fragment4;
    private ExtendsMyFragment2 extendsMyFragment;
    private String[] titles = {"页面1", "页面2", "页面3", "页面4"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        addFragment();
        viewPager = (ViewPager) findViewById(R.id.viewpage);
        tabLayout = (TabLayout) findViewById(R.id.tablayout);
        //注意下面这行代码
        viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
        tabLayout.setupWithViewPager(viewPager);
    }

    private void addFragment() {
        list = new ArrayList<>();
        extendsMyFragment = new ExtendsMyFragment2();
        fragment2 = new MyFragment2();
        fragment3 = new MyFragment2();
        fragment4 = new MyFragment2();
        //下面Bundle相关的都是用来跟fragment传递参数的
        Bundle bundle1 = new Bundle();
        Bundle bundle2 = new Bundle();
        Bundle bundle3 = new Bundle();
        Bundle bundle4 = new Bundle();
        bundle1.putString("name", "extendsMyFragment");
        bundle2.putString("name", "fragment2");
        bundle3.putString("name", "fragment3");
        bundle4.putString("name", "fragment4");
        extendsMyFragment.setArguments(bundle1);
        fragment2.setArguments(bundle2);
        fragment3.setArguments(bundle3);
        fragment4.setArguments(bundle4);
        list.add(extendsMyFragment);
        list.add(fragment2);
        list.add(fragment3);
        list.add(fragment4);
    }

        class MyAdapter extends FragmentPagerAdapter {

        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return list.get(position);
        }

        @Override
        public int getCount() {
            return list.size();
        }

        //重写这个方法,将设置每个Tab的标题
        @Override
        public CharSequence getPageTitle(int position) {
            return titles[position];
        }
    }
}

Fragment中的代码:ExtendsMyFragment2 和MyFragment2 相比就多了一个嵌套的代码其他都一样,所以直接看ExtendsMyFragment2 中的代码。

public class ExtendsMyFragment2 extends Fragment {
    private ViewPager viewPager;
    private TabLayout tabLayout;
    private List<Fragment> list;
    private MyFragment2 fragment1, fragment2, fragment3, fragment4;
    private List<String> titles;


    private void addFragment() {
        list = new ArrayList<>();
        fragment1 = new MyFragment2();
        fragment2 = new MyFragment2();
        fragment3 = new MyFragment2();
        fragment4 = new MyFragment2();
        Bundle bundle1 = new Bundle();
        Bundle bundle2 = new Bundle();
        Bundle bundle3 = new Bundle();
        Bundle bundle4 = new Bundle();
        bundle1.putString("name", "fragment1");
        bundle1.putString("tag", "fragment1");
        bundle2.putString("name", "fragment2");
        bundle2.putString("tag", "fragment2");
        bundle3.putString("name", "fragment3");
        bundle3.putString("tag", "fragment3");
        bundle4.putString("name", "fragment4");
        bundle4.putString("tag", "fragment4");
        fragment1.setArguments(bundle1);
        fragment2.setArguments(bundle2);
        fragment3.setArguments(bundle3);
        fragment4.setArguments(bundle4);
        list.add(fragment1);
        list.add(fragment2);
        list.add(fragment3);
        list.add(fragment4);
        titles = new ArrayList<>();
        titles.add("菜单1");
        titles.add("菜单2");
        titles.add("菜单3");
        titles.add("菜单4");
    }

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

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.extends_fragemnt, container, false);
        viewPager = (ViewPager) view.findViewById(R.id.viewpage);
        tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
        //注意这里。如果这里不用getChildFragmentManager会卡顿白屏
        viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
        tabLayout.setupWithViewPager(viewPager);
        return view;
    }

    class MyAdapter extends FragmentPagerAdapter {

        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return list.get(position);
        }

        @Override
        public int getCount() {
            return list.size();
        }

        //重写这个方法,将设置每个Tab的标题
        @Override
        public CharSequence getPageTitle(int position) {
            return titles.get(position);
        }
    }
}

就改这一句就可以了。想看源码的可以参照这位大神的博客,我的第二个方案也是仿照他的例子。黑暗中的一盏明灯的博客

下面介绍一下ViewPage+Fragment的懒加载

大家应该都知道ViewPage会默认缓存当前页及相邻的一个页面来提高流畅度,这样就会加大流量的消耗。如果想实现懒加载也有2种方式。第一种通过ViewPage来实现,让他不缓存相邻的页面;第二种通过Fragment来实现。
**下面主要说第二种:**
即重写Fragment的setUserVisibleHint方法,将网络请求的方法放入该方法中即可,是不是特别简单。参考链接是[傲寒遥的博客](http://www.jianshu.com/p/038229effa43)

猜你喜欢

转载自blog.csdn.net/qq_34500783/article/details/78701928