【问题标题】:how load fragment in ViewPager only when its selected仅在选中时如何在 ViewPager 中加载片段
【发布时间】:2013-10-21 03:31:54
【问题描述】:

我在Viewpager 中使用了3 个Fragments,问题是我在Asynctask 和加载器中加载大数据。在像HTC one 这样的设备上,它工作得很好,但是,在低端设备上,它需要很多时间。这主要是因为当我实现pagerAdapter 时,我将片段放在ArrayList 中,这会在加载主活动时强制片段实例化。我需要的是它只是“加载”第一个片段(主),当用户Swype 时,加载另一个片段。它有什么方法可以实现这一目标?这是我的页面适配器

public class PagerAdapter extends FragmentPagerAdapter  {

    private final ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
   // private final ArrayList<String> titulos = new ArrayList<String>();

   // private int NUM_PAGES =0;
    public PagerAdapter(FragmentManager manager,int num_pages) {
        super(manager);
     //   this.NUM_PAGES = num_pages;
    }


    public void addFragment(Fragment fragment,String title) {
        mFragments.add(fragment);
            notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        //return NUM_PAGES;
       return mFragments.size();
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);

    }

} 

【问题讨论】:

  • 尝试 pager.setOffscreenPageLimit(1);这将一次保留一个片段。
  • 这将保留在“内存”中,但是每次使用 swype 时都会创建片段。
  • 是的..它会刷新..
  • 那你想要什么???你写道:“只有在被选中时才在 ViewPager 中加载片段”
  • 我只想在它被选中时加载,但之后不再需要刷新

标签: java android android-fragments android-viewpager


【解决方案1】:

来自 Sun 的上述方法对我不起作用(也许对你有用),但我想我也会分享我对他方法的编辑。顺便说一句Sun,很好的方法!

private boolean _hasLoadedOnce= false; // your boolean field

@Override
public void setUserVisibleHint(boolean isFragmentVisible_) {
    super.setUserVisibleHint(true);


    if (this.isVisible()) {
        // we check that the fragment is becoming visible
        if (isFragmentVisible_ && !_hasLoadedOnce) {
            new NetCheck().execute();
            _hasLoadedOnce = true;
        }
    }
}

【讨论】:

  • 不同之处在于,在第二个 if 中,@Sun 写了 !isFragmentVisible。在我的情况下,它也不起作用,因为我需要在片段可见时执行异步任务,而不是之后。
  • 注意,方法 setUserVisibleHint(boolean isFragmentVisible) 是在 Fragment LifeCycle 之外调用的。不要指望它遵循生命周期规则。
【解决方案2】:

我将在此处添加我的解决方案,因为我遇到了类似的问题。我的异步任务没有加载大量数据,但它可以防止不必要的网络调用。这是我在 Fragment 中添加的内容:

private boolean _hasLoadedOnce= false; // your boolean field

@Override
public void setUserVisibleHint(boolean isFragmentVisible_) {
    super.setUserVisibleHint(isVisibleToUser);


    if (this.isVisible()) {
        // we check that the fragment is becoming visible
        if (!isFragmentVisible_ && !_hasLoadedOnce) {
            //run your async task here since the user has just focused on your fragment
            _hasLoadedOnce = true;
        }
    }
}

使用上面的代码,您的 Fragment 将被加载,但您的异步任务在用户第一次真正滚动到 Fragment 之前不会运行。显示后,您的异步任务将首次自动运行。然后,您可以提供一种通过按钮加载更多数据或拉动刷新的方法。上面的 Fragment 在我的 ViewPager 中,似乎工作正常。

【讨论】:

  • 谢谢老板。你节省了我的时间。前两天我正在尝试我的搜索问题。它调用下一个片段。非常感谢
  • setUserVisibleHint 我曾经使用过它并努力防止预加载,但问题是当我在此方法中调用我的异步并且在 postExecute 方法中具有一些布局和 TextView 并且所有都得到空指针。
  • 需要注意的是,这个setUserVisibleHint是在onCreate之前调用的。如果您的任务需要引用活动/上下文,这将产生一个 NPE。
  • @RaRa 解决NPE,你可以试试new Handler().post(() -&gt; makeRequest());
  • 我得到了“无法解析符号” isVisibleToUser 。确实意味着 super.setUserVisibleHint(isFragmentVisible); ?
【解决方案3】:

略微修改的版本以修复由于某些视图未完全初始化而导致的潜在 NPE

private boolean _hasLoadedOnce= false; // your boolean field

@Override
public void setUserVisibleHint(boolean isFragmentVisible_) {
    super.setUserVisibleHint(isVisibleToUser);


    if (this.isVisible()) {
        // we check that the fragment is becoming visible
        if (!isFragmentVisible_ && !_hasLoadedOnce) {
            new Handler().post(() -> {
                makeAsyncRequest();//do your asyn stuffs 
                _hasLoadedOnce = true;
            });
        }
    }
}

【讨论】:

  • 我得到了“无法解析符号” isVisibleToUser 。确实意味着 super.setUserVisibleHint(isFragmentVisible); ?
  • setUserVisibleHint() 已弃用,是的,它应该是 super.setUserVisibleHint(isFragmentVisible);
【解决方案4】:

如果您有很多页面并且想要在不可见时销毁它们,请使用 fragmentStatePageAdapter。 它已经实现了一个 setMenuVisibility(boolean menuVisible) 当片段变得可见时,所以使用它。

【讨论】:

    【解决方案5】:

    我可能会迟到,但这是我的解决方案,它按预期工作。在您的所有子片段中创建一个boolean 变量:

    private boolean loadFragmentExecuted = false;
    

    在子片段中创建一个名为loadFragment 的通用方法,并将您在onCreateView 中添加的所有逻辑移至该方法:

    public void loadFragment()
    {
        if(!loadFragmentExecuted)
        {
            //Add your logic to manipulate the UI or load data etc...
            loadFragmentExecuted = true;
        }
    }
    

    在您的网页浏览逻辑中动态创建片段,例如:

    //add the fragment
    String fragmentName = "com.something." + fragmentId;
    
    //check if the class exists
    try
    {
        Class myFragmentClass = Class.forName(fragmentName);
        Fragment myFragment = (Fragment) myFragmentClass.newInstance();
        mFragments.add(myFragment);
    }
    catch (ClassNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IllegalAccessException e)
    {
        e.printStackTrace();
    }
    catch (InstantiationException e)
    {
        e.printStackTrace();
    }
    

    然后设置您的寻呼机适配器并附上一个tablayout:

    //set our pager adapter that contains different fragments
    mPagerAdapter = new BasePagerAdapter(mFragmentManager, mFragments);
    
    //link the adapter to the viewpager
    mViewPager.setAdapter(mPagerAdapter);
    
    //cache fragments
    int limit = (mPagerAdapter.getCount() > 0 ? mPagerAdapter.getCount() : 1);
    mViewPager.setOffscreenPageLimit(limit);
    
    //add the page listner to the viewPager and link it to the tabLayout
    mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
    
    //on tab selected select current viewpager item
    mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
    {
        @Override
        public void onTabSelected(TabLayout.Tab tab)
        {
            mViewPager.setCurrentItem(tab.getPosition());
    
            //get fragment for the selected tab
            Fragment f = mPagerAdapter.getItem(tab.getPosition());
    
            //load the content of the fragment
            try
            {
                Class c = f.getClass();
                Method loadFragment = c.getMethod("loadFragment");
                loadFragment.invoke(f);
            }
            catch (IllegalAccessException e){}
            catch (InvocationTargetException e){}
            catch (NoSuchMethodException e){}
        }
    
        @Override
        public void onTabUnselected(TabLayout.Tab tab)
        {
        }
    
        @Override
        public void onTabReselected(TabLayout.Tab tab)
        {
        }
    });
    

    【讨论】:

      猜你喜欢
      • 2018-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多