4

正常に動作している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を拡張するViewPagerActivityのコードです。

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;
    }
}
4

4 に答える 4

2

メソッドで次の行を移動してみてくださいonCreate():

mViewPager = (ViewPager) findViewById(R.id.viewPager);
adapter = new ViewPagerAdapter(getApplicationContext(),getSupportFragmentManager());
mViewPager.setAdapter(adapter);
于 2012-11-23T20:15:41.310 に答える
1

setCurrentItem(0)のメソッドを呼び出すと、ViewPager目に見えないフラグメントを破棄してメモリを解放しようとするため、アプリケーションがクラッシュします。しかし、アクティビティ ライフサイクルのその時点では、それらはまだ存在していません (したがってInvalid index 2, size is 0)。

保持するフラグメントの数は、メソッドsetOffscreenPageLimit()で指定されます。デフォルトでは 1 です。これは、最大で 3 つのフラグメントがメモリに保持されることを意味します (表示されているフラグメント、前のフラグメント、および次のフラグメント)。

フラグメントの作成と破棄のプロセスは によって自動的に管理されViewPagerます。さらに、 を使用していますFragmentStatePagerAdapter。これは、さまざまなフラグメントが破棄されたときにその状態を既に保存していますが、必ずしも存在するとは限らないため、フラグメント間で情報を渡すのが少し複雑になります。

最初のフラグメントを可視フラグメントとしてプログラムで設定する必要がある場合は、 の代わりにsetCurrentItem()inを呼び出して、フラグメントが既に存在するかどうかを確認してください。onResume()onStart()

于 2012-11-23T20:21:26.487 に答える
0

The problem is that you are setting current item 0, after creating a new ViewPageAdapter and setting it to the ViewPager. Your fragments are still not created so it return a out of bounds exception.

Put a log on the getItem method, and a log before setCurrentItem, and check that your getItem is not called before the setCurrent (Your getItem is creating the fragments).

I'm not sure, but in my opinion it's not necesary to force a setCurrentItem, and the another thing is that you are creating a new fragment in each getItem call. Save them on a collection to avoid memory leaks

于 2012-11-23T19:39:29.990 に答える
0

私の場合、問題は少し違っていたと思います。私がいた現在のものを置き換えるたびにinstantiateItem()、私のメソッドによって同じタイプの例外がスローされ、[戻る]ボタンを押して元のものに戻りました. 例外をスローした正確な行は次のとおりです。PagerAdapterFragmentViewPager

((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結局のところ、aを に追加するときViewPagerは、メソッドの int 引数を使用するのではなくinstantiateItem()、単に 0 を使用する必要があります。したがって、行は次のようになります。

((ViewPager) viewPagerContainer).addView(page, 0);

これが誰かに役立つことを願っています:)

于 2014-03-11T15:05:04.907 に答える