Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
按下后退按钮后出现Android ViewPager异常_Android_Android Viewpager_Fragment - Fatal编程技术网

按下后退按钮后出现Android ViewPager异常

按下后退按钮后出现Android ViewPager异常,android,android-viewpager,fragment,Android,Android Viewpager,Fragment,我有一个ViewPager,其中包含3个片段,工作正常。我从viewpager中的任何片段启动活动,并显示该活动。之后,当我按下“上一步”按钮时,我的应用程序崩溃,原因如下: FATAL EXCEPTION: main java.lang.RuntimeException: Unable to resume activity {AppName.Activities/AppName.Activities.ViewPagerActivity}: java.lang.IndexOutOfBoundsE

我有一个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)
以下是扩展FragmentActivity的ViewPageActivity的代码:

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;
    }
}
公共类ViewPagerAdapter扩展了FragmentStatePagerAdapter
{
私人最终语境;
阵列列表数据;
int totalMoodEntries=0;
静态片段f=null;
public ViewPagerAdapter(上下文mcontext,FragmentManager fm)
{
超级(fm);
上下文=mcontext;
}
@凌驾
公共片段getItem(int位置)
{
开关(位置)
{
案例0:
{
f=新图表片段(上下文、totalMoodEntries、数据);
打破
}
案例1:
{
f=新的ViewRecordsFragment(上下文、数据);
打破
}
案例2:
{
f=新的LearnMoreFragment(上下文);
打破
}
}
返回f;
}
@凌驾
public int getCount()
{
返回3;
}
}

问题在于,在创建新的ViewPageAdapter并将其设置为ViewPager后,您正在设置当前项0。您的片段仍然没有创建,因此它返回一个越界异常

在getItem方法上放置一个日志,在setCurrentItem之前放置一个日志,并检查getItem是否在setCurrent之前被调用(getItem正在创建片段)


我不确定,但我认为没有必要强制设置setCurrentItem,另一件事是在每个getItem调用中创建一个新片段。将它们保存到集合中以避免内存泄漏

您可以尝试在
onCreate()
方法中移动以下行:

mViewPager = (ViewPager) findViewById(R.id.viewPager);
adapter = new ViewPagerAdapter(getApplicationContext(),getSupportFragmentManager());
mViewPager.setAdapter(adapter);

应用程序正在崩溃,因为当您调用
ViewPager
setCurrentItem(0)
方法时,它试图销毁不可见的片段以释放内存。但在活动生命周期的这一点上,它们仍然不存在(因此
无效索引2,大小为0

它将保持活动状态的片段数是通过方法
setOffscreenPageLimit()
指定的,默认情况下为1,这意味着在内存中最多保留3个片段(显示的片段、上一个片段和下一个片段)

片段的创建和销毁过程由
ViewPager
自动管理,您应该让它完成自己的工作。此外,您使用的是
FragmentStatePagerAdapter
,它在不同片段被销毁时已经保存了它们的状态,但是它也使得在片段之间传递信息变得稍微复杂一些,因为它们不一定存在


如果您确实需要通过编程将第一个片段设置为可见片段,只需尝试在
onResume()
中调用
setCurrentItem()
,而不是
onStart()
,然后查看片段是否已经存在。

在我的情况下,我认为问题有所不同。每当我替换当前的
片段时,我的
PagerAdapter
instantiateItem()
方法就会引发相同类型的异常,然后按下后退按钮,用
ViewPager
返回到原始的异常。引发异常的确切行是:

((ViewPager) viewPagerContainer).addView(page, position);
在:

事实证明,当您将
视图
添加到
查看页面
时,不应该使用
实例化Item()
方法的int参数,而应该使用0。因此,该行应如下所示:

((ViewPager) viewPagerContainer).addView(page, 0);
我希望这对某人有所帮助:)

我所说的“做它的事”是指你不应该将片段存储在内存中的集合中。这确实可能导致可能的内存泄漏,使用FragmentStatePagerAdapter更是如此,其目标是仅在片段不可见时保留片段的状态以节省内存。
((ViewPager) viewPagerContainer).addView(page, 0);