使用 Fragments 和 ViewPager 一段时间后,Android 应用程序崩溃
Posted
技术标签:
【中文标题】使用 Fragments 和 ViewPager 一段时间后,Android 应用程序崩溃【英文标题】:Android app crashing after a while using Fragments and ViewPager 【发布时间】:2012-06-21 06:19:32 【问题描述】:在尝试恢复我的片段时,我的 android 应用程序崩溃了。我没有将任何自定义变量添加到我要恢复的包中,这都是默认的。我正在使用片段和 ViewPager。请参阅下面的代码 sn-ps:
public static class MyAdapter extends FragmentStatePagerAdapter
public MyAdapter(FragmentManager fm)
super(fm);
@Override
public int getCount()
return NUM_ITEMS;
public int getCurrentItemPosition(Fragment fragment)
return getItemPosition(fragment);
@Override
public Fragment getItem(int position)
return ContentFragment.newInstance(position);
public class MyActivity extends FragmentActivity
static final int NUM_ITEMS = 100000;
public int currentSelectedPage;
private int changeToFragmentIndex;
public DateTime midDate;
MyAdapter mAdapter;
ViewPager mPager;
/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.diary);
MyApplication application = (MyApplication)getApplication();
application.dataController.myActivity = this;
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
int newDay = application.daysBetween(DateTime.now(), DateTime.parse(application.day.dateToShortString()));
this.currentSelectedPage = NUM_ITEMS/2+newDay;
mPager.setCurrentItem(NUM_ITEMS/2+newDay);
mPager.setOnPageChangeListener(new SimpleOnPageChangeListener()
public void onPageSelected(int position)
currentSelectedPage = position;
ContentFragment fragment = (ContentFragment) mAdapter.instantiateItem(mPager, currentSelectedPage);
fragment.loadData();
);
public class ContentFragment extends Fragment
private View v;
static final int NUM_ITEMS = 100000;
static ContentFragment newInstance(int num)
ContentFragment f = new ContentFragment();
return f;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
if (container == null)
return null;
v = inflater.inflate(R.layout.diarycontent, container, false);
return v;
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
@Override
public void onSaveInstanceState(Bundle savedInstanceState)
super.onSaveInstanceState(savedInstanceState);
setUserVisibleHint(true);
我收到了这个堆栈跟踪:
Caused by: java.lang.NullPointerException
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:519)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:1 55)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:522)
据我了解,这可能是支持包的一个已知问题,一种可能的解决方案是在 onSaveInstanceState 中使用 setUserVisibleHint(true)。但这没有帮助。
有谁知道问题的另一种解决方案或我做错了什么?
【问题讨论】:
嗨@xteci 你解决了这个问题吗?我也遇到这样的错误,还是找不到解决办法 我也是,你们有什么发现吗? @hakim 你可以使用这个答案,它对我有用***.com/questions/18642890/… 【参考方案1】:一旦我开始在 Tab 中使用 ViewPager 和 FragmentStatePagerAdapter,我就遇到了同样类型的问题。
然后我在所有与此问题相关的论坛上玩了两天,想知道为什么会出现这个问题以及如何解决它,但没有找到任何符合我要求的完美解决方案。
为了避免 NPE 崩溃,我得到了解决方案,使用 FragmentPagerAdapter 而不是 FragmentStatePagerAdapter。当我替换 FragmentPagerAdapter 而不是 FragmentStatePagerAdapter 时,不会遇到 NPE 崩溃问题,但同一页面不会自行刷新以进行进一步导航(这是我的要求)。
最后覆盖 FragmentStatePagerAdapter 上的 saveState 方法,一切正常。
@Override
public Parcelable saveState()
// Do Nothing
return null;
我如何轻松重现此问题: 我正在使用更高版本(4.1)的设备并按照以下步骤操作: 1. 进入设置 -> 开发者选项。 2. 点击“不保留活动”选项。
现在我开始玩我的应用了。
在每次应用程序由于 android.support.v4.app.FragmentManagerImpl.getFragment(Unknown Source) 处的 NPE 而崩溃时覆盖 saveState() 方法之前。但是在覆盖 saveState() 之后没有注册崩溃。
我希望这样做不会有任何问题。
【讨论】:
此解决方案将完全破坏视图状态,并且每个片段都会再次实例化,而不会恢复任何视图状态。仅当您不想恢复视图状态时才有用。并非对所有情况都有用【参考方案2】:我最初使用@Lalit Kumar Sahoo 建议的解决方案。但是,我注意到一个严重的问题:每次旋转设备时,片段管理器都会添加新片段而不会删除旧片段。所以我进一步搜索,发现了一个带有解决方法建议的错误报告 (post #1)。我使用此修复程序并在我的应用程序中进行了测试,该问题似乎已解决,没有任何副作用:
解决方法:在项目的 src/android/support/v4/app 文件夹中创建自定义 FragmentStatePagerAdapter 并使用它。
package android.support.v4.app;
import android.os.Bundle;
import android.view.ViewGroup;
public abstract class FixedFragmentStatePagerAdapter extends FragmentStatePagerAdapter
public FixedFragmentStatePagerAdapter(FragmentManager fm)
super(fm);
@Override
public Object instantiateItem(ViewGroup container, int position)
Fragment f = (Fragment)super.instantiateItem(container, position);
Bundle savedFragmentState = f.mSavedFragmentState;
if (savedFragmentState != null)
savedFragmentState.setClassLoader(f.getClass().getClassLoader());
return f;
【讨论】:
【参考方案3】:你到底为什么这样做:
mPager.setOnPageChangeListener(new SimpleOnPageChangeListener()
public void onPageSelected(int position)
currentSelectedPage = position;
ContentFragment fragment = (ContentFragment) mAdapter.instantiateItem(mPager, currentSelectedPage);
fragment.loadData();
);
这个:
@Override
public Fragment getItem(int position)
return ContentFragment.newInstance(position);
实例化片段。
您可以在片段中加载这样的数据:
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
loadData();
【讨论】:
我这样做是因为我在正确更新片段时遇到了一些麻烦。我测试了你的代码,崩溃仍然发生。 这为我解决了,或者真的把它藏起来了***.com/questions/18642890/…以上是关于使用 Fragments 和 ViewPager 一段时间后,Android 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
使用 Fragments 和 ViewPager 一段时间后,Android 应用程序崩溃
ViewPager 和 Fragments — 存储 Fragment 状态的正确方法是啥?
将 ViewPager 与 Fragments 一起使用时,在滑动时会破坏 Fragment
如何从 ViewPager 的 onPageSelected AsyncTask 到 Fragments?