搜索
热搜: 活动 交友 discuz
查看: 3541|回复: 1
打印 上一主题 下一主题

ViewPager+Fragment取消预加载(延迟加载)

[复制链接]

160

主题

165

帖子

814

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
814
跳转到指定楼层
楼主
发表于 2016-4-23 14:09:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragment有个不好或者太好的地方。例如你在ViewPager中添加了三个Fragment,当加载ViewPager中第一个Fragment时,它会默认帮你预先加载了第二个Fragment,当你加载第二个Fragment时,它会帮你加载第三个Fragment。这样虽然有时很好,但是用户只需看一个Fragment时,我们就做了一些多余工作加载了第二个Fragment。在这只需要取消Fragment的预加载即可,只有当用户切换到某个Fragment才加载..

首先,介绍两个方法void setUserVisibleHint(boolean isVisibleToUser)、boolean getUserVisibleHint(),它们分别用作设置/获得Fragment可见状态,我们可以重写Fragment在其中做判断,代码如下:


  1. import android.support.v4.app.Fragment;

  2. public abstract class BaseFragment extends Fragment {
  3.      
  4.     /** Fragment当前状态是否可见 */
  5.     protected boolean isVisible;
  6.      
  7.      
  8.     @Override
  9.     public void setUserVisibleHint(boolean isVisibleToUser) {
  10.         super.setUserVisibleHint(isVisibleToUser);
  11.          
  12.         if(getUserVisibleHint()) {
  13.             isVisible = true;
  14.             onVisible();
  15.         } else {
  16.             isVisible = false;
  17.             onInvisible();
  18.         }
  19.     }
  20.      
  21.      
  22.     /**
  23.      * 可见
  24.      */
  25.     protected void onVisible() {
  26.         lazyLoad();     
  27.     }
  28.      
  29.      
  30.     /**
  31.      * 不可见
  32.      */
  33.     protected void onInvisible() {
  34.          
  35.          
  36.     }
  37.      
  38.      
  39.     /**
  40.      * 延迟加载
  41.      * 子类必须重写此方法
  42.      */
  43.     protected abstract void lazyLoad();
  44. }
复制代码

在我们的Fragment中,只需要继承这个类,然后重写其中的lazyLoad()方法,当Fragment对用户可见(即用户切换到此Fragment时)我们在lazyLoad()中加载所需数据,详细代码看下面,我写了个假的获取数据线程:

  1. import android.os.AsyncTask;
  2. import android.os.Bundle;
  3. import android.view.LayoutInflater;
  4. import android.view.View;
  5. import android.view.ViewGroup;
  6. import android.widget.TextView;

  7. public class CustomListFragment extends BaseFragment {

  8.     private static final String FRAGMENT_INDEX = fragment_index;
  9.     private final int FIRST_FRAGMENT = 0;
  10.     private final int SECOND_FRAGMENT = 1;
  11.     private final int THIRD_FRAGMENT = 2;

  12.     private TextView mFragmentView;

  13.     private int mCurIndex = -1;
  14.     /** 标志位,标志已经初始化完成 */
  15.     private boolean isPrepared;
  16.     /** 是否已被加载过一次,第二次就不再去请求数据了 */
  17.     private boolean mHasLoadedOnce;

  18.     /**
  19.      * 创建新实例
  20.      *
  21.      * @param index
  22.      * @return
  23.      */
  24.     public static CustomListFragment newInstance(int index) {
  25.         Bundle bundle = new Bundle();
  26.         bundle.putInt(FRAGMENT_INDEX, index);
  27.         CustomListFragment fragment = new CustomListFragment();
  28.         fragment.setArguments(bundle);
  29.         return fragment;
  30.     }

  31.     @Override
  32.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  33.         if(mFragmentView == null) {
  34.             mFragmentView = (TextView) inflater.inflate(R.layout.fragment, container, false);
  35.             //获得索引值
  36.             Bundle bundle = getArguments();
  37.             if (bundle != null) {
  38.                 mCurIndex = bundle.getInt(FRAGMENT_INDEX);
  39.             }
  40.             isPrepared = true;
  41.             lazyLoad();
  42.         }
  43.          
  44.         //因为共用一个Fragment视图,所以当前这个视图已被加载到Activity中,必须先清除后再加入Activity
  45.         ViewGroup parent = (ViewGroup)mFragmentView.getParent();
  46.         if(parent != null) {
  47.             parent.removeView(mFragmentView);
  48.         }
  49.         return mFragmentView;
  50.     }

  51.     @Override
  52.     protected void lazyLoad() {
  53.         if (!isPrepared || !isVisible || mHasLoadedOnce) {
  54.             return;
  55.         }

  56.         new AsyncTask<void, boolean="">() {

  57.             @Override
  58.             protected void onPreExecute() {
  59.                 super.onPreExecute();
  60.                 //显示加载进度对话框
  61.                 UIHelper.showDialogForLoading(getActivity(), 正在加载..., true);
  62.             }

  63.             @Override
  64.             protected Boolean doInBackground(Void... params) {
  65.                 try {
  66.                     Thread.sleep(2000);
  67.                     //在这里添加调用接口获取数据的代码
  68.                     //doSomething()
  69.                 } catch (Exception e) {
  70.                     e.printStackTrace();
  71.                 }
  72.                 return true;
  73.             }

  74.             @Override
  75.             protected void onPostExecute(Boolean isSuccess) {
  76.                 if (isSuccess) {
  77.                     // 加载成功
  78.                     setView();
  79.                     mHasLoadedOnce = true;
  80.                 } else {
  81.                     // 加载失败
  82.                 }
  83.                 //关闭对话框
  84.                 UIHelper.hideDialogForLoading();
  85.             }
  86.         }.execute();
  87.     }

  88.     private void setView() {
  89.         // 根据索引加载不同视图
  90.         switch (mCurIndex) {
  91.         case FIRST_FRAGMENT:
  92.             mFragmentView.setText(第一个);
  93.             break;

  94.         case SECOND_FRAGMENT:
  95.             mFragmentView.setText(第二个);
  96.             break;

  97.         case THIRD_FRAGMENT:
  98.             mFragmentView.setText(第三个);
  99.             break;
  100.         }
  101.     }
  102. }</void,>
复制代码
到这里我们只是写好了Fragment,在FragmentActivity中还需要对ViewPager设置一下,让它每次只加载一个Fragment,ViewPager.setOffscreenPageLimit(int limit),其中参数可以设为0或者1,参数小于1时,会默认用1来作为参数,未设置之前,ViewPager会默认加载两个Fragment。所以,我们只需要调用下它,设置下加载Fragment个数即可。
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import android.support.v4.app.Fragment;
  4. import android.support.v4.app.FragmentActivity;
  5. import android.support.v4.view.ViewPager;
  6. import android.support.v4.view.ViewPager.OnPageChangeListener;
  7. import android.view.View;
  8. import android.view.View.OnClickListener;
  9. import android.widget.RadioButton;
  10. import android.os.Bundle;

  11. public class MainActivity extends FragmentActivity implements OnClickListener{

  12.     private RadioButton mFstBtn;
  13.     private RadioButton mSndBtn;
  14.     private RadioButton mThdBtn;
  15.      
  16.     private ViewPager mViewPager;
  17.     private ListFragmentPagerAdapter mPagerAdapter;
  18.     private List<fragment> mFragments = new ArrayList<fragment>();
  19.      
  20.     private final int FIRST_FRAGMENT = 0;
  21.     private final int SECOND_FRAGMENT = 1;
  22.     private final int THIRD_FRAGMENT = 2;
  23.      
  24.      
  25.     @Override
  26.     protected void onCreate(Bundle savedInstanceState) {
  27.         super.onCreate(savedInstanceState);
  28.         setContentView(R.layout.activity_main);
  29.         initButton();
  30.         initViewPager();
  31.     }
  32.      
  33.      
  34.     /**
  35.      * 初始化按钮
  36.      */
  37.     private void initButton() {
  38.         mFstBtn = (RadioButton)findViewById(R.id.id_rb_fst);
  39.         mFstBtn.setOnClickListener(this);
  40.         mSndBtn = (RadioButton)findViewById(R.id.id_rb_snd);
  41.         mSndBtn.setOnClickListener(this);
  42.         mThdBtn = (RadioButton)findViewById(R.id.id_rb_thd);
  43.         mThdBtn.setOnClickListener(this);
  44.     }
  45.      
  46.      
  47.     /**
  48.      * 初始化ViewPager控件
  49.      */
  50.     private void initViewPager() {
  51.         mViewPager = (ViewPager)findViewById(R.id.id_vp_viewpager);
  52.         //关闭预加载,默认一次只加载一个Fragment
  53.         mViewPager.setOffscreenPageLimit(1);
  54.         //添加Fragment
  55.         mFragments.add(CustomListFragment.newInstance(FIRST_FRAGMENT));
  56.         mFragments.add(CustomListFragment.newInstance(SECOND_FRAGMENT));
  57.         mFragments.add(CustomListFragment.newInstance(THIRD_FRAGMENT));
  58.         //适配器
  59.         mPagerAdapter = new ListFragmentPagerAdapter(getSupportFragmentManager(), mFragments);
  60.         mViewPager.setAdapter(mPagerAdapter);
  61.         mViewPager.setOnPageChangeListener(onPageChangeListener);
  62.     }

  63.      
  64.     private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
  65.          
  66.         @Override
  67.         public void onPageSelected(int position) {
  68.             //根据用户选中的按钮修改按钮样式
  69.             switch (position) {
  70.             case FIRST_FRAGMENT:
  71.                 mFstBtn.setChecked(true);
  72.                 mSndBtn.setChecked(false);
  73.                 mThdBtn.setChecked(false);
  74.                 break;

  75.             case SECOND_FRAGMENT:
  76.                 mFstBtn.setChecked(false);
  77.                 mSndBtn.setChecked(true);
  78.                 mThdBtn.setChecked(false);
  79.                 break;
  80.                  
  81.             case THIRD_FRAGMENT:
  82.                 mFstBtn.setChecked(false);
  83.                 mSndBtn.setChecked(false);
  84.                 mThdBtn.setChecked(true);
  85.             break;
  86.             }
  87.         }
  88.          
  89.         @Override
  90.         public void onPageScrolled(int arg0, float arg1, int arg2) {}
  91.          
  92.         @Override
  93.         public void onPageScrollStateChanged(int arg0) {}
  94.     };
  95.      
  96.      
  97.     @Override
  98.     public void onClick(View v) {
  99.         switch (v.getId()) {
  100.         case R.id.id_rb_fst:
  101.             mViewPager.setCurrentItem(FIRST_FRAGMENT);
  102.             break;

  103.         case R.id.id_rb_snd:
  104.             mViewPager.setCurrentItem(SECOND_FRAGMENT);
  105.             break;
  106.             
  107.         case R.id.id_rb_thd:
  108.             mViewPager.setCurrentItem(THIRD_FRAGMENT);
  109.             break;
  110.         }
  111.     }
  112. }
  113. </fragment></fragment>
复制代码



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

160

主题

165

帖子

814

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
814
沙发
 楼主| 发表于 2016-4-23 14:10:14 | 只看该作者
评论:
其实很简单就两个方法

第一个 setUserVisibleHint 重新这个方法 判断是否当前显示中

第二个setOffscreenPageLimit设置这个0或为1
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|安卓论坛  

GMT+8, 2024-5-16 16:54 , Processed in 0.064900 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Design S!|ƽ̶

快速回复 返回顶部 返回列表