ViewPager Adapter FragmentStatePagerAdapter FragmentPagerAdapter 使用详解

来源:互联网 发布:android 离线数据缓存 编辑:程序博客网 时间:2024/05/21 15:05
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中 获取我们 之前保存的数据


0 0
原创粉丝点击