2

我有一个非常简单的 PagerAdapter,由于某种原因,当它滚动到位置 2 时,它会删除位置 0 和 1 的视图。

具体来说,当我第一次运行应用程序时,有 3 个视图。我滚动到位置 2,位置 1 的视图将消失。视图 0 仍然存在。如果我滚动到视图 0 并返回到视图 2 并再次返回到视图 0,视图 0 会突然消失。我再次这样做,我实际上可以看到视图 0 被实例化并立即被销毁。

这里发生了什么?

主要活动

public class MainActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final MyPagerAdapter adapter = new MyPagerAdapter(this);
        final ViewPager myPager = (ViewPager) findViewById(R.id.mypanelpager);
        myPager.setAdapter(adapter);
        myPager.setCurrentItem(1);
}


public class MyPagerAdapter extends PagerAdapter {

private Context ctx;
Calendar c = Calendar.getInstance();
int month = c.get(Calendar.MONTH);
int year = c.get(Calendar.YEAR);
ViewGroup collection;

public MyPagerAdapter (Context ctx){
    this.ctx = ctx ;
}


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

public Object instantiateItem(ViewGroup container, int position ){
    this.collection = (ViewPager)container;
    NewMonth monthObject = new NewMonth(ctx, month+position-1,2012);
    View monthLayout = monthObject.newParentLayout;
    collection.addView(monthLayout);
    return monthLayout;
    return addViewAt(position);
    }


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


 @Override
     public Parcelable saveState() {
     return null;
     }


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

3 回答 3

4

您必须维护内存中的所有选项卡,将 OffscreenPageLimit 指定为 N-1,在您的情况下,将其放在 onCreate 方法中:

myPager.setOffscreenPageLimit(2);
于 2013-03-02T17:09:54.400 回答
1

来自源的结帐populate()功能ViewPager- 它有明确的检查然后删除 currentIndex+1 和 currentIndex-1 项目。删除是根据视图大小完成的,它似乎完全是内部 ViewPager 逻辑。ViewPager 源位于

<android sdk folder>\extras\android\support\v4\src\java\android\support\v4\view\ViewPager.jav‌​a

.

您可能会调试ViewPager以知道这确实发生了,但在您遇到 ViewPager 的一些严重问题之前,我不会建议您这样做。原因是什么:如果您深入研究 ViewPager 代码,它可能会导致您基于其内部结构而不是其公共接口和文档在其上编写一些骇人听闻的代码(甚至不是故意的)。因此,数据封装的主要思想将被破坏,这绝对是不好的(遗憾的是,有时我们需要在 Android 中这样做,因为缺乏文档/不明确的命名/android 内部问题等,请查看Steve McConnell 的 Code Complete了解更多信息有关良好封装等的详细信息)。

于 2012-09-22T02:28:31.780 回答
0

这里的关键是位置与索引不同。如果他们给您一个职位,则不能保证您的收藏没有删除其他职位。

示例:假设您在位置 2。destroyItem 可能已被调用为位置 0,这意味着在您的集合中,现在位置 2 实际上位于索引 1。因此您的索引将很快与您的位置不同步。listview 子级也会发生同样的事情。我建议改用 sparseArray。

private final SparseArray<View> views = new SparseArray<>();

public View instantiateItem(ViewGroup container, final int position) {
    ...
    views.put(position, view);
    ...
}

public void destroyItem(ViewGroup container, int position, Object object) {
     View view = views.get(position);
     if (view != null) {
         container.removeView(view);
         views.remove(position);
     }
}
于 2014-04-29T15:09:38.233 回答