我有一个ViewPager,其中包含3个正常工作的片段。我从viewpager中的任何片段开始一个活动,并显示活动。之后当我按下后退按钮时,我的应用程序崩溃了以下例外情况:
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to resume activity {AppName.Activities/AppName.Activities.ViewPagerActivity}: java.lang.IndexOutOfBoundsException: Invalid index 2, size is 0
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2120)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:957)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IndexOutOfBoundsException: Invalid index 2, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
at java.util.ArrayList.set(ArrayList.java:484)
at android.support.v4.app.FragmentStatePagerAdapter.destroyItem(FragmentStatePagerAdapter.java:97)
at android.support.v4.view.ViewPager.populate(ViewPager.java:415)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:271)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:244)
at AppName.Activities.ViewPagerActivity.setUpView(ViewPagerActivity.java:36)
at AppName.Activities.ViewPagerActivity.onStart(ViewPagerActivity.java:28)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
at android.app.Activity.performStart(Activity.java:3791)
at android.app.Activity.performRestart(Activity.java:3821)
at android.app.Activity.performResume(Activity.java:3826)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110)
以下是我的ViewPagerActivity代码,它扩展了FragmentActivity ::
public class ViewPagerActivity extends FragmentActivity
{
private ViewPager mViewPager;
private ViewPagerAdapter adapter;
boolean flag = false;
@Override
protected void onCreate(Bundle arg0)
{
super.onCreate(arg0);
setContentView(R.layout.view_pager);
}
@Override
protected void onStart()
{
super.onStart();
setUpView();
}
private void setUpView()
{
mViewPager = (ViewPager) findViewById(R.id.viewPager);
adapter = new ViewPagerAdapter(getApplicationContext(),getSupportFragmentManager());
mViewPager.setAdapter(adapter);
mViewPager.setCurrentItem(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.settings:
startActivity(new Intent(this, AppSettingsActivity.class));
return true;
case R.id.addSituationMenu:
Intent i = new Intent(this, MainLayout.class);
i.putExtra("parentActivity", "SplashScreenLayout");
startActivity(i);
return true;
case R.id.historyActivity:
startActivity(new Intent(this, HistoryActivity.class));
return true;
case R.id.chartActivity:
startActivity(new Intent(this, ViewPagerActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
行mViewPager.setCurrentItem(0);导致崩溃。
这是ViewPagerAdapter代码:
public class ViewPagerAdapter extends FragmentStatePagerAdapter
{
private final Context context;
ArrayList<ArrayList<Object>> data;
int totalMoodEntries = 0;
static Fragment f = null;
public ViewPagerAdapter(Context mcontext, FragmentManager fm)
{
super(fm);
context = mcontext;
}
@Override
public Fragment getItem(int position)
{
switch (position)
{
case 0:
{
f = new ChartFragment(context, totalMoodEntries, data);
break;
}
case 1:
{
f = new ViewRecordsFragment(context, data);
break;
}
case 2:
{
f = new LearnMoreFragment(context);
break;
}
}
return f;
}
@Override
public int getCount()
{
return 3;
}
}
答案 0 :(得分:2)
您可以尝试在onCreate()
方法中移动以下行:
mViewPager = (ViewPager) findViewById(R.id.viewPager);
adapter = new ViewPagerAdapter(getApplicationContext(),getSupportFragmentManager());
mViewPager.setAdapter(adapter);
答案 1 :(得分:1)
应用程序崩溃,因为当您调用setCurrentItem(0)
的{{1}}方法时,它会尝试销毁不可见的片段以释放内存。但是在活动生命周期的那一点上,它们仍然不存在(因此ViewPager
)。
它将保持活动的片段数量通过方法Invalid index 2, size is 0
指定,默认为1,这意味着最多3个片段将保留在内存中(显示的片段,前一个片段)一个和下一个)。
片段的创建和销毁过程由setOffscreenPageLimit()
自动管理,你应该让它做它的东西。此外,您正在使用ViewPager
,它在销毁时已经保存了不同片段的状态,但它也使得在片段之间传递信息变得有点复杂,因为它们不一定存在。 / p>
如果您确实需要以编程方式将第一个片段设置为可见片段,只需尝试调用FragmentStatePagerAdapter
中的setCurrentItem()
而不是onResume()
,然后查看片段是否已存在。
答案 2 :(得分:0)
问题是您在创建新的ViewPageAdapter并将其设置为ViewPager后设置当前项目0。您的片段仍未创建,因此会返回超出范围的异常。
记录getItem方法和setCurrentItem之前的日志,并检查在setCurrent(您的getItem创建片段)之前未调用getItem。
我不确定,但在我看来强制setCurrentItem并不是必要的,另一件事是你在每个getItem调用中创建一个新的片段。将它们保存在集合中以避免内存泄漏
答案 3 :(得分:0)
就我而言,我认为这个问题有点不同。每当我替换当前的instantiateItem()
时,我都会使用PagerAdapter
Fragment
方法抛出相同类型的异常,然后按“返回”按钮返回原来的ViewPager
((ViewPager) viewPagerContainer).addView(page, position);
。抛出异常的确切行是:
private class SmartViewPagerAdapter extends PagerAdapter {
// [...]
@Override
public int getCount() {
return ABOUT_VIEW_PAGER_IMAGES.length;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == (View) arg1;
}
@Override
public Object instantiateItem(ViewGroup viewPagerContainer, int position) {
Drawable pageImage = getResources().getDrawable(ABOUT_VIEW_PAGER_IMAGES[position]);
Drawable pageTitle = getResources().getDrawable(ABOUT_VIEW_PAGER_TITLES[position]);
String pageDescription = getString(ABOUT_VIEW_PAGER_DESCRIPTIONS[position]);
SmartViewPagerPage page =
new SmartViewPagerPage(getActivity(), pageImage, pageTitle, pageDescription);
((ViewPager) viewPagerContainer).addView(page, position);
return page;
}
}
在:
View
事实证明,当你向ViewPager
添加instantiateItem()
时,你不应该使用((ViewPager) viewPagerContainer).addView(page, 0);
方法的int参数,而只是使用0.因此,该行应该看起来像这样:
{{1}}
我希望这有助于某人:)