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

来源:互联网 发布:matlab 二维矩阵赋值 编辑:程序博客网 时间:2024/06/06 09:22

先说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)
原创粉丝点击