ViewPager 片段随着时间的推移而被破坏?
Posted
技术标签:
【中文标题】ViewPager 片段随着时间的推移而被破坏?【英文标题】:ViewPager Fragments getting destroyed over time? 【发布时间】:2012-04-09 02:07:30 【问题描述】:我正在使用android的support.v4
包来开发一个包含多个Fragment
s的ViewPager。
我试图在用户更改页面时隐藏视图。因此,我实现了一个OnPageChangeListener
来监听我的适配器,并在发生页面更改时在我的Fragment
s 中调用update()
方法。但是我收到了NullPointerException
,我不知道为什么。
代码如下:
public class MyActivity extends FragmentActivity implements
OnPageChangeListener
private static final int NUM_ITEMS = 2;
private ViewPager mPager;
private static SpaceAdapter mAdapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_pager);
mAdapter = new SpaceAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setOnPageChangeListener(this);
public static class SpaceAdapter extends FragmentPagerAdapter
public SpaceAdapter(FragmentManager fm)
super(fm);
@Override
public int getCount()
return NUM_ITEMS;
@Override
public Fragment getItem(int position)
switch (position)
case 0:
return new MyFragment();
case 1:
return new MyFragment();
default:
return new MyFragment();
@Override
public void onPageScrollStateChanged(int arg0)
Log.i("pagination", "scroll state changed: " + arg0);
@Override
public void onPageScrolled(int arg0, float arg1, int arg2)
// Log.i("pagination", "page scroll: " + arg0 + " with: " + arg1 + ", " + arg2);
if (mAdapter.getItem(arg0) instanceof IUpdateOnPage)
((IUpdateOnPage) mAdapter.getItem(arg0)).updateOnPage();
@Override
public void onPageSelected(int arg0)
Log.i("pagination", "page selected: " + arg0);
和
public class MyFragment extends Fragment implements
SurfaceHolder.Callback, IUpdateOnPage
private SurfaceView charts;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View v = inflater.inflate(R.layout.crew, null);
bindViews(v);
return v;
private void bindViews(View v)
charts = (SurfaceView) v.findViewById(R.id.civ_charts);
charts.getHolder().addCallback(this);
Log.i("wtf", "huh " + String.valueOf(charts == null)); // logs false
@Override
public void updateOnPage()
if (charts != null)
Log.i("crew surface", "hidden");
charts.setVisibility(View.GONE);
else
Log.i("crew surface", "charts is null"); //THIS HERE gets logged
w当我复制/粘贴时,我删除了 SurfaceHolder.Callback
方法,但它们在那里。 bindViews(v)
方法记录 charts == null
,并且总是返回 false。当我页面时,updateOnPage
被调用,charts == null
返回 true。为什么会发生这种情况,我该如何解决?
这是第 108 行:
charts.setVisibility(View.GONE);
【问题讨论】:
好的,经过进一步调查,我假设片段在分页开始时被破坏(即使视图仍然存在?)。滑动时,我仍然可以看到“一半”片段,直到新片段捕捉到全视图。所以,如果所有的引用都被收集了,剩下的就是视图,我该怎么做呢? 如果您收到NullPointerException
,您可以发布 logcat 输出吗?
好吧,我实际上正在捕捉它,因此不会引发异常。问题是charts.setVisibility(View.GONE);
。图表为空。它位于第二个代码示例的最后,位于else
的正上方。添加了堆栈跟踪。
【参考方案1】:
初始化ViewPager
时添加以下内容,
mPager.setOffscreenPageLimit(NUM_ITEMS-1);
在您的情况下,这会将屏幕外页面的数量设置为 1(即,当另一个页面当前处于焦点时,它将在内存中保留额外的屏幕外页面)。这将强制您的 ViewPager
保留所有 Fragment
s,即使它们不在焦点上。
【讨论】:
解决了我遇到的另一个小性能问题,非常感谢!但是当这个片段使用相同的空指针显示时它仍然会崩溃.. 实际上,这解决了核心问题。我不再需要调用 setVisibilty(View.gone) 了。奇怪,但谢谢!澄清一下——SurfaceView 没有正确分页,即使我滑动它,它仍然保留在所有页面上。 这很奇怪,因为setOffscreenPageLimit
在 v4 中默认为 1(并且 NUM_ITEMS - 1 等于 1),但我很高兴您的问题已得到解决。
实际上我将代码“笨拙”了一点,然后将其粘贴到此处。我有 7 个片段,但这是唯一一个有表面视图的片段,也是唯一一个有问题的片段......不过谢谢!
很高兴听到您成功了。在我看来,ViewPager
的生命周期没有得到很好的记录......这可能有点棘手。【参考方案2】:
我检查了您的代码,我认为问题在于在onPageScrolled
中,您正在调用getItem
。这个实现(实际上就像它在 web 上的大多数实现一样)每次都返回一个新实例。但是,我见过的大多数示例都不会调用getItem
,所以这通常没问题。
在您的情况下,我会在 getItem
中懒惰地创建片段:如果该位置不存在,则创建它,然后将其挂在 ArrayList
或其他集合中,但如果它已经存在,只需从该集合中返回它。
否则,你创建一个片段实例 A,然后滚动到另一个片段实例 B。你试图告诉片段实例 A 清理一些视图,但你最终告诉一个新的片段实例 C 这样做。它还没有机会建立自己的视图,所以你得到了指向图表的空指针。
【讨论】:
哦,这很好。我从某处的谷歌示例中获得了这个实现,但我将研究实现一个数组或其他东西来维护片段。谢谢!以上是关于ViewPager 片段随着时间的推移而被破坏?的主要内容,如果未能解决你的问题,请参考以下文章
将 ViewPager 与 Fragments 一起使用时,在滑动时会破坏 Fragment