ViewPager Adapter FragmentStatePagerAdapter FragmentPagerAdapter 使用详解

ViewPager 是Android 开发中特别常用的一个View
所以我们今天来看看ViewPager

ViewPager  是support-v4中的View
<android.support.v4.view.ViewPager

    android:id="@+id/view_pager"

    android:layout_width="match_parent"

    android:layout_height="match_parent"/>



这片文章重点的讲的是ViewPager 的Adapter,
我使用 ViewPager 的Adapter 时, 一般有三种实现方式:
  1. 自己继承 PagerAdapter
  2. 继承FragmentPagerAdapter
  3. 继承FragmentStatePagerAdapter

先来说说第一种:

先来代码: 

public class ViewPagerAdapter1 extends PagerAdapter {
    public static final String TAG = ViewPagerAdapter1.class.getSimpleName();

    private List<String> mDataList;
    private LayoutInflater mLayoutInflater;

    public ViewPagerAdapter1(Context context, List<String> dataList) {
        mDataList = dataList;
        mLayoutInflater = LayoutInflater.from(context);
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        LogUtil.d(TAG, "instantiateItem position = " + position);
        // 这里 必须是 null , 不然报错
        View item = mLayoutInflater.inflate(R.layout.item_1, null);
        TextView textView = (TextView) item.findViewById(R.id.txt);
        textView.setText(mDataList.get(position));
        container.addView(item);
        return item;
    }

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

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}


如上代码 就基本实现了一个 Adapter, 

instantiateItem 方法中 加载View 并把View add到 contain(即 ViewPager)中
这里需要注意 :
View item = mLayoutInflater.inflate(R.layout.item_1, null); 中 必须是null , 不然会出问题

在destroyItem 方法中, 需要吧View 移除

isViewFromObject 中, google 推荐我们这样写,

上面的代码写的其实是有问题的, 没有能够复用View , 每次都是重新加载View这样挺好性能的
不过这个问题也好解决, 只要吧 加载过的View 保存起来即可

ok 下面说一下 FragmentPagerAdapter 与 FragmentStatePagerAdapter
代码如下: 
public class ViewPagerAdapter2 extends FragmentPagerAdapter {
    public static final String TAG = ViewPagerAdapter2.class.getSimpleName();

    private List<Fragment> mFragments = new ArrayList<>();

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

    public void addFragment(Fragment fragment) {
        mFragments.add(fragment);
    }

    public void removeFragment(Fragment fragment) {
        mFragments.remove(fragment);
    }

    public void setFragments(List<Fragment> fragments) {
        mFragments = fragments;
    }

    public List<Fragment> getFragments() {
        return mFragments;
    }

    public void clear() {
        for (Fragment fragment : mFragments) {
            if (fragment != null && fragment.isAdded()) {
                fragment.onDestroy();
            }
        }
        mFragments.clear();
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        LogUtil.d(TAG, "instantiateItem position = " + position);
        return super.instantiateItem(container, position);
    }

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

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

public class ViewPagerAdapter3 extends FragmentStatePagerAdapter {
    public static final String TAG = ViewPagerAdapter3.class.getSimpleName();

    private List<Fragment> mFragments = new ArrayList<>();

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

    public void addFragment(Fragment fragment) {
        mFragments.add(fragment);
    }

    public void removeFragment(Fragment fragment) {
        mFragments.remove(fragment);
    }

    public void setFragments(List<Fragment> fragments) {
        mFragments = fragments;
    }

    public List<Fragment> getFragments() {
        return mFragments;
    }

    public void clear() {
        for (Fragment fragment : mFragments) {
            if (fragment != null && fragment.isAdded()) {
                fragment.onDestroy();
            }
        }
        mFragments.clear();
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        LogUtil.d(TAG, "instantiateItem position = " + position);
        return super.instantiateItem(container, position);
    }

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

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

两者的代码基本没有变化,
一般只要 实现 getItem getCount 两个方法即可
他们两使用起来感觉上差异不大,  但是内部原理差异还是挺大的.


这里讲一下两者的区别:
FragmentPagerAdapter
     他会把每个Fragment 都保存下来,
     他在 destroyItem 方法中, 只是把 Fragment detach 掉了并没有销毁 Fragment

FragmentStatePagerAdapter
     只会保存Fragment的state保存下来,
     他在  destroyItem 方法中, 会把Fragment Remove 掉,
     但是会调用Fragment的 onSaveInstanceState 方法.
     然后销毁 Fragment

使用建议, 如果只有 3,4 个Fragment的话, 建议使用 FragmentPagerAdapter ,这样每个 Fragment 都被保存下来,加载起来页方便

如果Fragment 数量比较多的画, 如一下小说阅读器这类的画, 还是建议使用FragmentStatePagerAdapter, 这样就不会占用太多的内存

可以看下 Fragment的代码: 
public class MyFragment extends Fragment {
    public final static String TAG = "MyFragment";
    public final static String SaveInstanceStateEXTRA = "SaveInstanceStateEXTRA";

    String mData;

    public static MyFragment getInstances(String data) {
        MyFragment myFragment = new MyFragment();
        myFragment.mData = data;
        return myFragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        LogUtil.d(TAG, "onCreateView  mData = " + mData);
        String str = "";
        if (savedInstanceState != null) {
            str = savedInstanceState.getString("SaveInstanceStateEXTRA");
        }

        // 这里必须是null
        View item = inflater.inflate(R.layout.item_1, null);
        TextView textView = (TextView) item.findViewById(R.id.txt);
        textView.setText(mData);
        if (!TextUtils.isEmpty(str)) {
            textView.setText(str);
        }
        return item;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(SaveInstanceStateEXTRA, mData + "_save");
        LogUtil.d(TAG, "onSaveInstanceState  mData = " + mData);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtil.d(TAG, "onDestroy mData = " + mData);
    }
}

如果使用的是  FragmentStatePagerAdapter 
那么 当Fragment 在不可见(在缓存数量之外的话) 会调用 onSaveInstanceState 和 onDestroy 方法
然后当被 划回该Fragment的时候 会调用 onCreateView 方法, 其中可以在 savedInstanceState中 获取我们 之前保存的数据


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值