Android - ViewPager Adapter, set primary item before adapter is instantiated
Asked Answered
B

6

8

I know i can do

 viewPager.setCurrentItem(position) 

to set my view pager at the desired position. My question is if and how i can do this before the adapter is instantiated.

Meaning that if I do

pagerAdapter = new ViewPagerAdapter(arg1,arg2....);
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(position);

item 0 is first build and after that the item at the desired position is also build. Which takes double the time...In my adapter each item needs quite a lot of work to be build, so it would be best to avoid the 0 position item to be build if possible. Maybe by passing the desired position as an argument at the adapter's instantiation...?

Any way to do that?

But answered 25/9, 2014 at 22:32 Comment(0)
E
1

You can fool the viewpager to start at a given position before the adapter is set, by calling onRestoreInstanceState, like this:

int currentItem = 5;

Parcel parcel = Parcel.obtain();
writeParcelable(BaseSavedState.EMPTY_STATE, 0);

writeInt(currentItem);
writeParcelable(null, 0);

setDataPosition(0);
SavedState savedState = ViewPager.SavedState.CREATOR.createFromParcel(parcel);

mPager.onRestoreInstanceState(savedState);

mPager.setAdapter(mAdapter);
Epicardium answered 7/7, 2015 at 12:46 Comment(1)
Unfortunately this doesn't work anymore in Android M, see my new answerInvariant
J
3

If the time and work is what you're worry about, I'd try to avoid building the page at position 0 until the desired one has been built. You could use a variable lets say "desiredPageHasBeenBuilt" in your adapter, when requesting the item at position 0 you could return an "empty page" if the variable desiredPageHasBeenBuilt is false, when your desired page has been build set the variable to true and the page 0 can be built.

Justinejustinian answered 25/9, 2014 at 23:33 Comment(1)
Example please ;)Alderman
I
3

For a solution that works in Android M as well as older versions, use reflection as follows:

int currentItem = 5;

// Set initial position first...
Field field = ViewPager.class.getDeclaredField("mRestoredCurItem");
field.setAccessible(true);
field.set(mPager, currentItem);

// ...and then set adapter
mPager.setAdapter(adapter);

Using reflection is safe, because you control the ViewPager implementation (it's included with your app).

If you use Proguard, then you need to include the following in its config:

-keepclassmembers class android.support.v4.view.ViewPager {
    private int mRestoredCurItem;
}  

or the field mRestoredCurItem will be renamed by Proguard.

Invariant answered 3/9, 2015 at 23:6 Comment(0)
C
3

You can just set blank adapter and after that set your real adapter this way you will "trick" the viewpager and you want load any data you dont want to.

this.viewPager.setAdapter(new PagerAdapter() {
        @Override
        public int getCount() {
            return 0;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return false;
        }
    });
this.viewPager.setCurrentItem(imagePosition, false);
this.viewPager.setAdapter(adapter);
this.viewPager.setCurrentItem(imagePosition, false);
Chapple answered 11/2, 2016 at 16:58 Comment(1)
This will not work, anytime you call setAdapter the ViewPager internally resets the current item to 0Isherwood
E
1

You can fool the viewpager to start at a given position before the adapter is set, by calling onRestoreInstanceState, like this:

int currentItem = 5;

Parcel parcel = Parcel.obtain();
writeParcelable(BaseSavedState.EMPTY_STATE, 0);

writeInt(currentItem);
writeParcelable(null, 0);

setDataPosition(0);
SavedState savedState = ViewPager.SavedState.CREATOR.createFromParcel(parcel);

mPager.onRestoreInstanceState(savedState);

mPager.setAdapter(mAdapter);
Epicardium answered 7/7, 2015 at 12:46 Comment(1)
Unfortunately this doesn't work anymore in Android M, see my new answerInvariant
E
0

Maybe this is not the answer you're looking for, but have you tried to it as it was designed? Do not start heavy work on page fragment before it is attached to the screen. That way you'll get that behavior you want without hacking android implementation.

Especially answered 17/3, 2018 at 11:6 Comment(0)
C
-1

you can do this trick:

refactor all of your heavy work into a function, because creating a fragment is not takes much time, and only execute the function when user is going to see it by calling that function inside OnPageChangeListener listener and at the

@Override
public void onPageSelected(int position){
    // call your function that do heavy working  
}
Congeneric answered 26/9, 2014 at 2:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.