美文网首页
ViewPager 总结 - 1 PagerAdapter

ViewPager 总结 - 1 PagerAdapter

作者: 老柯南 | 来源:发表于2019-02-20 08:14 被阅读24次
  • 1: pageradapter 方法解释
  • 2: pageradapter 实现类用法
  • 3: FragmentPagerAdapter & FragmentStatePagerAdapter 区别
  • 4: FragmentPagerAdapter & FragmentStatePagerAdapter 总结
  • 5: FragmentPagerAdapter & FragmentStatePagerAdapter 实现类用法

pageradapter

public class ViewPagerAdapter extends PagerAdapter {
     /**
      * 获取View的总数
      *
      * @return View总数
      */
    @Override
    public int getCount() {
        return 0;
    }

    /**
     * 当ViewPager的内容有所变化时,进行调用。
     * 父类是一个空方法 ,没用过,在调用 dataSetChanged(),setAdapter(),populate()时会调用
     *
     * @param container ViewPager本身
     */
    @Override
    public void startUpdate(ViewGroup container) {
        super.startUpdate(container);
    }
    
    /**
     * 为给定的位置创建相应的View。创建View之后,需要在该方法中自行添加到container中。
     * 注意这里将view添加到container ,当时返回的还是view,而不是container; 
     * 
     * @param container ViewPager本身
     * @param position  给定的位置
     * @return 提交给ViewPager进行保存的实例对象
     */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        return super.instantiateItem(container, position);
    }
    
    /**
     * 为给定的位置移除相应的View。
     *
     * @param container ViewPager本身
     * @param position  给定的位置
     * @param object    在instantiateItem中提交给ViewPager进行保存的实例对象
     */
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
    }
    
    /**
     * ViewPager调用该方法来通知PageAdapter当前ViewPager显示的主要项,提供给用户对主要项进行操作的方法。
     *
     * 将数据展示在界面上,也可以在instantiateItem()方法中去做
     * @param container ViewPager本身
     * @param position  给定的位置
     * @param object    在instantiateItem中提交给ViewPager进行保存的实例对象
     */
    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
    }
    
    /**
     * 当ViewPager的内容变化结束时,进行调用。当该方法被调用时,必须确定所有的操作已经结束。
     *
     * @param container ViewPager本身
     */
    @Override
    public void finishUpdate(ViewGroup container) {
        super.finishUpdate(container);
    }
    
    /**
     * 确认View与实例对象是否相互对应。ViewPager内部用于获取View对应的ItemInfo。
     *
     * @param view   ViewPager显示的View内容
     * @param object 在instantiateItem中提交给ViewPager进行保存的实例对象
     * @return 是否相互对应
     */
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return false;
    }
    
    /**
     * 保存与PagerAdapter关联的任何实例状态。
     *
     * @return PagerAdapter保存状态
     */
    @Override
    public Parcelable saveState() {
        return super.saveState();
    }
    
    /**
     * 恢复与PagerAdapter关联的任何实例状态。
     *
     * @param state  PagerAdapter保存状态
     * @param loader 用于实例化还原对象的类加载器
     */
    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
        super.restoreState(state, loader);
    }
    
    /**
     * 当ViewPager试图确定某个项的位置是否已更改时调用。默认有两个可选项:POSITION_UNCHANGED和POSITION_NONE。
     * POSITION_UNCHANGED:给定项的位置未变更
     * POSITION_NONE:给定项不再用于PagerAdapter中
     * 其他值:可以根据具体的情况进行调整
     *
     * @param object 在instantiateItem中提交给ViewPager进行保存的实例对象
     * @return
     */
    @Override
    public int getItemPosition(Object object) {
        return super.getItemPosition(object);
    }
    
    /**
     * 可配合Design库中的TabLayout与ViewPager进行绑定时,提供显示的标题。
     *
     * @param position 给定的位置
     * @return 显示的标题
     */
    @Override
    public CharSequence getPageTitle(int position) {
        return super.getPageTitle(position);
    }
    
    /**
     * 获取给定位置的View的显示宽度比例,该比例是相对于ViewPager的。
     *
     * @param position 给定的位置
     * @return View显示的宽度比例
     */
    @Override
    public float getPageWidth(int position) {
        return super.getPageWidth(position);
    }

  }

简易示例(传统用法)

public class VpAdapter extends PagerAdapter {

    @Override
    public int getCount() {
        return 2;
    }

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

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {

        TextView textView = new TextView(container.getContext());
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(40.0f);
        textView.setTextColor(Color.BLACK);
        textView.setBackgroundColor(Color.RED);
        textView.setText("this is pager" + position);
        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        container.addView(textView, layoutParams);  //一定记得这个
        return textView;  //一定记得这个 ,一定是返回要展示的view,而不是container
    }

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

配合DataBinding 使用

public class VpAdapter extends PagerAdapter {
   
    @Override
    public int getCount() {
        return 2;
    }
    
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        return DataBindingUtil.inflate(container.getContext(), R.layout.item_simple, container, true);
    }
    
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ItemSimplePagerBinding dataBinding = (ItemSimplePagerBinding) object;
        container.removeView(dataBinding.getRoot());
    }
    
    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        ItemSimplePagerBinding dataBinding = (ItemSimplePagerBinding) object;
        dataBinding.tvContent.setText(getPageTitle(position));
    }
    
    @Override
    public boolean isViewFromObject(View view, Object object) {
        ItemSimplePagerBinding dataBinding = (ItemSimplePagerBinding) object;
        return dataBinding.getRoot() == view;
    }
   
}

FragmentPagerAdapter & FragmentStatePagerAdapter

FragmentPagerAdapter & FragmentStatePagerAdapter 是PagerAdapter的两个抽象子类,两个抽象类的具体子类用法相同,都是需要实现 getItem(int position)以及getCount()方法

/**
     * Return the Fragment associated with a specified position.
     */
    public abstract Fragment getItem(int position);

FragmentPagerAdapter & FragmentStatePagerAdapter 的区别:


FragmentPagerAdapter 部分源码

 @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        final long itemId = getItemId(position);

        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
                + " v=" + ((Fragment)object).getView());
        mCurTransaction.detach((Fragment)object);
    }
FragmentStatePagerAdapter 部分源码

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // If we already have this item instantiated, there is nothing
        // to do.  This can happen when we are restoring the entire pager
        // from its saved state, where the fragment manager has already
        // taken care of restoring the fragments we previously had instantiated.
        if (mFragments.size() > position) {
            Fragment f = mFragments.get(position);
            if (f != null) {
                return f;
            }
        }

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        Fragment fragment = getItem(position);
        if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
        if (mSavedState.size() > position) {
            Fragment.SavedState fss = mSavedState.get(position);
            if (fss != null) {
                fragment.setInitialSavedState(fss);
            }
        }
        while (mFragments.size() <= position) {
            mFragments.add(null);
        }
        FragmentCompat.setMenuVisibility(fragment, false);
        FragmentCompat.setUserVisibleHint(fragment, false);
        mFragments.set(position, fragment);
        mCurTransaction.add(container.getId(), fragment);

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
                + " v=" + ((Fragment)object).getView());
        while (mSavedState.size() <= position) {
            mSavedState.add(null);
        }
        mSavedState.set(position, fragment.isAdded()
                ? mFragmentManager.saveFragmentInstanceState(fragment) : null);
        mFragments.set(position, null);

        mCurTransaction.remove(fragment);
    }

具体可以翻看下源码,从instantiateItem()和 destroyItem()方法可以看出FragmentPagerAdapter , FragmentStatePagerAdapter 在实例化 和 销毁示例的逻辑上是不同的,FragmentPagerAdapter 在销毁的时候只是detach了实例,没有移除,而 FragmentStatePagerAdapter 在销毁的时候是真的移除了。

所以可以总结出:

  • FragmentPagerAdapter 在数据量少的时候使用

  • FragmentStatePagerAdapter 在数据量大的时候使用

样例

public class TeamFragmentAdapter extends FragmentPagerAdapter {

    protected List<Fragment> mFragmentList;

    protected String[] mTitles;

    public TeamFragmentAdapter(FragmentManager fm, List<Fragment> fragmentList, String[] mTitles) {
        super(fm);
        if (fragmentList == null) {
            fragmentList = new ArrayList<>();
        }
        this.mFragmentList = fragmentList;
        this.mTitles = mTitles;
    }

    public void add(Fragment fragment) {
        if (isEmpty()) {
            mFragmentList = new ArrayList<>();

        }
        mFragmentList.add(fragment);
    }

    public boolean isEmpty() {
        return mFragmentList == null;

    }

    @Override
    public Fragment getItem(int position) {
        return isEmpty() ? null : mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return isEmpty() ? 0 : mFragmentList.size();
    }


    @Override
    public CharSequence getPageTitle(int position) {
        return mTitles[position];
    }
}

相关文章

网友评论

      本文标题:ViewPager 总结 - 1 PagerAdapter

      本文链接:https://www.haomeiwen.com/subject/uojfyqtx.html