Android ViewPager Exception after clicking return button

I have a ViewPager that contains 3 fragments that work fine. I start the action with my any of my fragments inside the viewpager, and the action is displayed. After that, when I click the back button, my application crashes with the following exception:

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) 

Below is my code for ViewPagerActivity, which extends 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); } } } 

String mViewPager.setCurrentItem (0); causes a failure.

This is the ViewPagerAdapter code:

 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
source share
4 answers

Can you try moving the following line in the onCreate() method:

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

The application crashes because when you call the setCurrentItem(0) ViewPager , it tries to destroy invisible fragments to free memory. But at this point in the life cycle of the activity they do not exist yet (therefore, Invalid index 2, size is 0 ).

The number of fragments that it will support is determined by the setOffscreenPageLimit() method, 1 by default, which means that no more than 3 fragments will remain in the memory (the one that it shows is the previous and next).

The process of creating and destroying fragments is automatically controlled by ViewPager , and you must let it do its own thing. In addition, you use the FragmentStatePagerAdapter , which already saves the states of different fragments when they are destroyed, but also makes it a little more complex, passing information between fragments, because they do not necessarily exist.

If you really need to programmatically set the first fragment as a visible fragment, just try calling setCurrentItem() in onResume() instead of onStart() and see if the fragments are already there.

+1
source

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

Put the log on the getItem method and the log before setCurrentItem and make sure your getItem is not called before setCurrent (your getItem creates fragments).

I'm not sure, but, in my opinion, it is not necessary to force setCurrentItem to be set, and the other thing is that you create a new fragment in every getItem call. Store them in a collection to avoid memory leaks.

0
source

In my case, the problem was a little different, I think. I had the same type of exception that was called by the instantiateItem() method of my PagerAdapter when I replaced the current Fragment I was in and then clicked the back button to return to the original using the ViewPager . The exact line throwing the exception was:

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

in

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

As it turned out, when you add a View to your ViewPager , you should not use the int argument of the instantiateItem() method, but simply use 0. Thus, the line should look like this:

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

Hope this helps someone :)

0
source

Source: https://habr.com/ru/post/1448017/


All Articles