Android开发笔记 ViewPager 嵌套 RecyclerView instantiateItem数据初始化错位问题

       在应用开发过程中,使用ViewPager嵌套RecyclerView实现整屏的横滑是很常见的需求。在为ViewPager设置adapter的时候,需要重写初始化方法,
   public Object instantiateItem(ViewGroup container, int position) {}来告诉ViewPager对应每个position展示什么View,在这个方法中将
position对应的view  add进container,返回该view即可。
            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.detail, null);
                recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
                
                ViewGroup parent = (ViewGroup) view.getParent();
                if (parent != null) {
                    parent.removeView(view);
                }
                container.addView(view);

                if (mPresenter == null) {
                    initPresenter();
                }
                mPresenter.updateRecyclerView(pagerDataList.get(position), recyclerView);
                return view;
            }
在MVP模式的项目中,告诉Presenter该position页需要请求的数据,将数据放入recyclerView即可。但是,在ViewPager初始化的时候,
instantiateItem()方法会连续执行position = 0 和 position = 1 两次,当presenter需要去网络请求position = 0数据完成后,presenter持有的
recyclerView引用已经指向了position = 1的view内的recyclerView对象,数据也会被贴到position = 1的页面里。在viewPager的滑动过程中,每次滑动
预加载下一页时instantiateItem只会执行一次,网络正常的情况下,不会出现错乱问题。
    解决办法:维护一个任务队列,在每次presenter请求数据时,将数据的标记(id)与recyclerView存入对列,数据请求回来后,判断是否有等待的任务,有等待的
任务,则任务出队,请求数据,给recyclerView贴数据。

public static class Task {
        private int id;
        private RecyclerView recyclerView;

        public int getId() {
            return id;
        }

        public RecyclerView getRecyclerView() {
            return recyclerView;
        }

        public Task (int id, RecyclerView recyclerView) {
            this.id = id;
            this.recyclerView = recyclerView;
        }
    }

presenter中定义一个队列变量,

private Queue caCheTaskQueue = new LinkedList();
每次需要请求一个也页面的数据的时候,判断队列里有没有缓存任务,并将本次任务入队

    if (caCheTaskStack.isEmpty()) {
            initRecyclerView();//请求数据并交给recyclerView初始化
        }
    caCheTaskStack.offer(new Task(currentPageId, recyclerView));//入队
在initRecyclerView()网络请求回调里,任务出队,再判断是否有任务等待。

caCheTaskStack.poll();//本次任务出队
if (!caCheTaskStack.isEmpty()) {
    Task task = caCheTaskStack.peek();//缓存任务读取
    currentPageId = task.getId();
    recyclerView = task.getRecyclerView();
    initRecyclerView();//请求数据并交给recyclerView初始化
}
















你可能感兴趣的:(java,Android,Java)