如何从PagerAdapter获取ViewPager当前页面的Bitmap与ID?
如何获取ViewPager当前可见页面的Bitmap和ID?
你现在遇到的问题核心是ViewPager的预加载机制——它默认会提前加载当前页面左右各1个页面(可以通过setOffscreenPageLimit修改,但不建议设为0),所以你的全局bitmap和id变量会被预加载的下一页资源覆盖,导致调用getBitmap()时拿到的不是当前显示的页面内容。另外你的代码里还有个小问题:instantiateItem里没有调用mCursor.moveToPosition(position),这会导致你取到的ID和URL可能对应错误的位置!
解决步骤:
- 替换全局变量为集合存储:用两个集合分别保存每个页面位置对应的Bitmap和ID,确保每个页面的资源都能精准对应。
- 修正Cursor位置:在
instantiateItem里一定要先把Cursor移动到目标position,再获取数据。 - 监听ViewPager页面切换:记录当前显示的页面位置,这样就能准确拿到对应位置的资源。
- 修改getBitmap和getId方法:根据当前记录的位置从集合中获取对应资源。
修改后的完整代码示例:
public class CursorPagerAdaptor extends PagerAdapter { private Cursor mCursor; private Context mContext; // 用集合存储每个position对应的Bitmap和ID private HashMap<Integer, Bitmap> positionBitmapMap = new HashMap<>(); private HashMap<Integer, Integer> positionIdMap = new HashMap<>(); // 记录当前显示的页面位置 private int currentPosition = 0; LayoutInflater layoutInflater; public CursorPagerAdaptor(Context context,Cursor cursor){ mContext = context; mCursor = cursor; layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return mCursor.getCount(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == ((RelativeLayout) object); } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { View itemView= layoutInflater.inflate(R.layout.view_pager_items, container, false); final ImageView imageView = (ImageView) itemView.findViewById(R.id.image); final ProgressBar progressBar = (ProgressBar)itemView.findViewById(R.id.progress); // 关键:先将Cursor移动到目标position mCursor.moveToPosition(position); int urlIndex = mCursor.getColumnIndex(MetaDataInfo.COLUMN_PHOTOURL); String url = mCursor.getString(urlIndex); int idIndex = mCursor.getColumnIndex(MetaDataInfo._ID); final int currentId = mCursor.getInt(idIndex); // 先把ID存入集合 positionIdMap.put(position, currentId); // 移除重复的addView逻辑 container.addView(itemView); Glide.with(mContext) .asBitmap() .load(url).apply(new RequestOptions().dontAnimate().fitCenter()) .into(new SimpleTarget<Bitmap>(640,480) { @Override public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { progressBar.setVisibility(View.GONE); imageView.setImageBitmap(resource); // 加载完成后将Bitmap存入对应position的集合 positionBitmapMap.put(position, resource); } }); return itemView; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView((RelativeLayout)object); // 页面销毁时从集合中移除对应资源,避免内存泄漏 positionBitmapMap.remove(position); positionIdMap.remove(position); } // 提供方法设置当前显示的位置(从ViewPager的监听器调用) public void setCurrentPosition(int position) { this.currentPosition = position; } public Bitmap getBitmap(){ // 根据当前位置返回对应的Bitmap return positionBitmapMap.get(currentPosition); } public int getId(){ // 根据当前位置返回对应的ID return positionIdMap.get(currentPosition) != null ? positionIdMap.get(currentPosition) : -1; } }
在你的Activity/Fragment中设置ViewPager页面监听器:
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} @Override public void onPageSelected(int position) { // 告诉Adapter当前显示的页面位置 mAdapter.setCurrentPosition(position); } @Override public void onPageScrollStateChanged(int state) {} });
额外说明:
- 这样修改后,无论ViewPager预加载多少页面,你都能通过
currentPosition精准拿到当前显示页面的Bitmap和ID。 - 在
destroyItem中移除集合里的资源,能避免内存泄漏问题。 - 之前你代码里重复调用了
container.addView(itemView),已经帮你移除了多余的那部分,避免视图重复添加的问题。
内容的提问来源于stack exchange,提问作者Muhammad Nadeem
相关产品推荐
相关产品推荐

