web-dev-qa-db-ja.com

ViewPager.setOffscreenPageLimit(0)が期待どおりに機能しない

ViewPagerインスタンスで使用するフラグメントは非常にリソースを集中的に使用するため、一度に1つずつロードしたいだけです。私が次を試してみると:

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

FragmentStatePagerAdapter.getItem(int position)オーバーライド関数は3回呼び出されます。これはmViewPager.setOffscreenPageLimit(1)を呼び出すと発生します。 0個のオフスクリーンページを指定したため、1回しか呼び出されないはずです。

mViewPager.setOffscreenPageLimit(2)を呼び出すと、FragmentStatePagerAdapter.getItem(int position)が5回呼び出されるため、すべてを正しく呼び出していると思います。

ViewPagerには最低1つのオフスクリーンページが必要ですか、それともここで何か間違っていますか?

94
Chris Lacy

ViewPagerには最低1つのオフスクリーンページが必要ですか

はい。ソースコードを正しく読んでいる場合、LogCatで次のような警告が表示されるはずです。

Requested offscreen page limit 0 too small; defaulting to 1
110
CommonsWare

私が見つけた最良の方法は setUserVisibleHint
これをフラグメントに追加します

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

最初に追加

   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{
     }
}
7
user5308871

あなたはこのように試すことができます:

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(){}
7
Terry

私の場合、ビューでいくつかのアニメーションを開始したかったのですが、setUserVisibleHintでいくつかの問題が発生しました...
私の解決策は次のとおりです。

1 /アダプタのaddOnPageChangeListener:

mViewPager.addOnPageChangeListener(this);

2/OnPageChangeListenerを実装します:

public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener

3/3つのメソッドをオーバーライドします。

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

}

@Override
public void onPageSelected(int position)
{ 
}

@Override
public void onPageScrollStateChanged(int state)
{
}

4 /クラスでこの変数を宣言して初期化する

private static int mTabState = 1;

notice:アダプターに3つのフラグメントがあり、どのフラグメントが時間内にユーザーに表示されるかを認識するsetCurrentItemおよびアダプターの現在の位置にmTabStateを使用します... 5/onPageSelectedメソッドでこのコードを追加します:

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

前のページまたは現在のページがページ0(位置0のフラグメント)の場合、このようなことを行います

6 /フラグメントクラス(アダプターの位置0のフラグメント)で、ブロードキャストレシーバーを作成し、onResumeメソッドで登録し、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: Fragment Pager Adapter witchに3つのFragmentsが表示されています。Adapterの位置0にあるFragmentのビューでアニメーションを表示したいため、BroadcastReceiverを使用します。フラグメントが選択されると、アニメーションメソッドを開始し、ユーザーにビューを表示します。フラグメントがユーザーに表示されない場合、非表示のビューを試みます...

1
AREF

ViewPagerは、setOffscreenPageLimit(0)で変更できない次のページ(フラグメント)をデフォルトでロードします。しかし、あなたはハックするために何かをすることができます。 ViewPagerを含むアクティビティにonPageSelected関数を実装できます。次のFragment(ロードしたくない)で、リソースを消費するすべてのinitコードを入れてonResume()メソッドの前に何もしない関数showViewContent()を作成します。次に、onPageSelected内でshowViewContent()関数を呼び出します。これが役立つことを願っています。

これは古いスレッドかもしれませんが、これは私にはうまくいくようです。この関数をオーバーライドします。

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

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

ハッピーコーディング...

0
ralphgabb

私も同じ問題を抱えています。このサイトで便利なコードを見つけて変換しました。

MViewPager.setOffscreenPageLimit(...);の最小整数。は1なので、0に変更しても2ページはロードされたままです。

最初に行うことは、maxPageCountを呼び出し、FragmentStatePagerAdapterメソッドgetCount()をオーバーライドしてmaxPageCountを返す静的intを作成することです。

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

次に、このmaxCountを変更できるプログラム内の任意の場所からアクセスできる静的メソッドを作成します。

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

次に、maxPageCountを1に初期化します。いつでも別のページを追加できます。私の場合、ユーザーが最初に現在のページを処理してから他のページを生成する必要がありました。彼はそれをやると、問題なく次のページにスワイプできます。

それが誰かを助けることを願っています。

0
K20

この//を使用して、データを取得するためのブール値を作成します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;
    }
} 
0
Rohit Sharma

「instantiateItem」関数の場合は、フラグメントを準備するだけで、重いコンテンツをロードしないでください。

"onPageChangeListener"を使用して、特定のページに移動するたびに、その重いコンテンツをロードして表示します。

0

Viewpagerでビューを更新する問題を解決するには、このコードを試してください。

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