code

ViewPager.setOffscreenPageLimit (0)이 예상대로 작동하지 않습니다.

codestyles 2020. 8. 26. 07:53
반응형

ViewPager.setOffscreenPageLimit (0)이 예상대로 작동하지 않습니다.


ViewPager인스턴스 에서 사용하는 조각 은 리소스 집약적이므로 한 번에 하나씩 만로드하고 싶습니다. 다음을 시도 할 때 :

mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);

FragmentStatePagerAdapter.getItem(int position)오버라이드 함수는 3 번 호출되는데, mViewPager.setOffscreenPageLimit(1). 오프 스크린 페이지를 0 개로 지정했기 때문에 한 번만 호출 될 것으로 예상합니다.

내가 호출하는 경우 때문에 내가 제대로 모든 전화 했어 생각 mViewPager.setOffscreenPageLimit(2), FragmentStatePagerAdapter.getItem(int position)내가 기대로 5 번이라고합니다.

ViewPager에 최소 1 개의 오프 스크린 페이지가 필요합니까, 아니면 여기서 뭔가 잘못하고 있습니까?


ViewPager에 최소 1 개의 오프 스크린 페이지가 필요합니까?

예. 소스 코드를 올바르게 읽고 있다면 LogCat에 다음과 같은 경고가 표시됩니다.

Requested offscreen page limit 0 too small; defaulting to 1

내가 찾은 가장 좋은 방법은 setUserVisibleHint가
이것을 조각에 추가하는 것입니다.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}

다음과 같이 시도 할 수 있습니다.

public abstract class LazyFragment extends Fragment {
    protected boolean isVisible;
    /**
     * 在这里实现Fragment数据的缓加载.
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    protected void onVisible(){
        lazyLoad();
    }
    protected abstract void lazyLoad();
    protected void onInvisible(){}

protected abstract void lazyLoad();
protected void onInvisible(){}

먼저 추가

   boolean isFragmentLoaded = false;

...보다

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser && !isFragmentLoaded) {
        //Load Your Data Here like.... new GetContacts().execute();

        isFragmentLoaded = true;
    }
else{
     }
}

ViewPager는 기본적으로 setOffscreenPageLimit (0)으로 변경할 수없는 다음 페이지 (Fragment)를로드합니다. 하지만 해킹 할 수 있습니다. ViewPager를 포함하는 Activity에서 onPageSelected 함수를 구현할 수 있습니다. 다음 Fragment (로드하고 싶지 않음)에서 모든 리소스 소비 초기화 코드를 입력하고 onResume () 메서드 전에 아무것도하지 않는 showViewContent () 함수를 작성합니다. 그런 다음 onPageSelected 내에서 showViewContent () 함수를 호출합니다. 이것이 도움이되기를 바랍니다.


제 경우에는 뷰에서 일부 애니메이션을 시작하고 싶었지만 setUserVisibleHint를 사용하면 몇 가지 문제가 있습니다 ...
제 솔루션은 다음과 같습니다.

1 / 어댑터에 대한 addOnPageChangeListener :

mViewPager.addOnPageChangeListener(this);

2/ implement OnPageChangeListener :

public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener

3/ override the 3 methodes :

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{

}

@Override
public void onPageSelected(int position)
{ 
}

@Override
public void onPageScrollStateChanged(int state)
{
}

4/ declare and initialize this variable on your class

private static int mTabState = 1;

notice : i have three fragments in my adapter, and use mTabState for setCurrentItem and current position of adapter which recognize which fragment is show to user in time ... 5/ in onPageSelected method add this codes :

if (mTabState == 0 || position == 0)
    {
        Intent intent = new Intent("animation");
        intent.putExtra("current_position", position);
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
    }

if previous page or current page is page 0(fragment in position 0) then do this stuff

6/ now in your fragment class (fragment in position 0 of adapter), you must create broadcast receiver and register it in onResume method and unregister it onPause methos :

BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (Objects.equals(intent.getAction(), "animation"))
        {
            int currentPosition = intent.getIntExtra("current_position", 0);
            if (currentPosition == 0)
            {
                startAnimation();
                setViewsVisible();
            } else
            {
                setViewsInvisible();
            }
        }
    }
};

@Override
public void onResume()
{
    super.onResume();
    LocalBroadcastManager.getInstance(mContext).registerReceiver(broadcastReceiver, new IntentFilter("animation"));
}

@Override
public void onPause()
{
    super.onPause();
    LocalBroadcastManager.getInstance(mContext).unregisterReceiver(broadcastReceiver);
}

summary : i have Fragment Pager Adapter witch shows Three Fragments in it, I want show some Animations on Views in Fragment in Position 0 of Adapter, For this I use BroadcastReceiver. When Fragment is Picked I start the Animation method and shows the Views to User, When Fragment is not Showing to User I try to Invisible Views...


for the "instantiateItem" function, just prepare the fragment, but don't load the heavy content.

Use "onPageChangeListener" , so that each time you go to a specific page, you load its heavy content and show it.


this may be old thread but this seems to work for me. Override this function :

@Override
public void setMenuVisibility(boolean menuVisible) { 
    super.setMenuVisibility(menuVisible);

    if ( menuVisible ) {
        /**
         * Load your stuffs here.
         */
    } else  { 
        /**
         * Fragment not currently Visible.
         */
    } 
}

happy codings...


I kind of have the same problem. I found some useful code on this site and transform it.

The min int for mViewPager.setOffscreenPageLimit(...); is 1, so even if you change it to 0 you will still have 2 pages loaded.

First thing to do is to create a static int we will call maxPageCount and override FragmentStatePagerAdapter method getCount() to return maxPageCount:

    @Override
    public int getCount() {
        return maxPageCount;
    }

Create then a static method accessible from any where in the program that will allow you to change this maxCount:

public static void addPage(){
    maxPageCount++; //or maxPageCount = fragmentPosition+2
    mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}

Now initialize maxPageCount to 1. When ever you want you can add another page. In my case when I needed the user to treat the current page first before generated the other. He do it and then, without problem can swipe to the next page.

Hope it help someone.


Use This // create boolean for fetching data private boolean isViewShown = false;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getView() != null) {
        isViewShown = true;
        // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
        fetchData();
    } else {
        isViewShown = false;
    }
} 

Please Try This Code for resolve issue of refreshing view in Viewpager....

/* DO NOT FORGET! The ViewPager requires at least “1” minimum OffscreenPageLimit */
int limit = (mAdapter.getCount() > 1 ? mAdapter.getCount() - 1 : 1);
mViewPager.setOffscreenPageLimit(limit);

참고URL : https://stackoverflow.com/questions/10073214/viewpager-setoffscreenpagelimit0-doesnt-work-as-expected

반응형