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

来源:互联网 发布:java数据库连接池c3p0 编辑:程序博客网 时间:2024/04/30 15:38
在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragment有个不好或者太好的地方。例如你在ViewPager中添加了三个Fragment,当加载ViewPager中第一个Fragment时,它会默认帮你预先加载了第二个Fragment,当你加载第二个Fragment时,它会帮你加载第三个Fragment。这样虽然有时很好,但是用户只需看一个Fragment时,我们就做了一些多余工作加载了第二个Fragment。在这只需要取消Fragment的预加载即可,只有当用户切换到某个Fragment才加载..


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

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. import android.support.v4.app.Fragment;  
  2.   
  3. public abstract class BaseFragment extends Fragment {  
  4.       
  5.     /** Fragment当前状态是否可见 */  
  6.     protected boolean isVisible;  
  7.       
  8.       
  9.     @Override  
  10.     public void setUserVisibleHint(boolean isVisibleToUser) {  
  11.         super.setUserVisibleHint(isVisibleToUser);  
  12.           
  13.         if(getUserVisibleHint()) {  
  14.             isVisible = true;  
  15.             onVisible();  
  16.         } else {  
  17.             isVisible = false;  
  18.             onInvisible();  
  19.         }  
  20.     }  
  21.       
  22.       
  23.     /** 
  24.      * 可见 
  25.      */  
  26.     protected void onVisible() {  
  27.         lazyLoad();       
  28.     }  
  29.       
  30.       
  31.     /** 
  32.      * 不可见 
  33.      */  
  34.     protected void onInvisible() {  
  35.           
  36.           
  37.     }  
  38.       
  39.       
  40.     /**  
  41.      * 延迟加载 
  42.      * 子类必须重写此方法 
  43.      */  
  44.     protected abstract void lazyLoad();  
  45. }  

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

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  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.   
  8. public class CustomListFragment extends BaseFragment {  
  9.   
  10.     private static final String FRAGMENT_INDEX = "fragment_index";  
  11.     private final int FIRST_FRAGMENT = 0;  
  12.     private final int SECOND_FRAGMENT = 1;  
  13.     private final int THIRD_FRAGMENT = 2;  
  14.   
  15.     private TextView mFragmentView;  
  16.   
  17.     private int mCurIndex = -1;  
  18.     /** 标志位,标志已经初始化完成 */  
  19.     private boolean isPrepared;  
  20.     /** 是否已被加载过一次,第二次就不再去请求数据了 */  
  21.     private boolean mHasLoadedOnce;  
  22.   
  23.     /** 
  24.      * 创建新实例 
  25.      *  
  26.      * @param index 
  27.      * @return 
  28.      */  
  29.     public static CustomListFragment newInstance(int index) {  
  30.         Bundle bundle = new Bundle();  
  31.         bundle.putInt(FRAGMENT_INDEX, index);  
  32.         CustomListFragment fragment = new CustomListFragment();  
  33.         fragment.setArguments(bundle);  
  34.         return fragment;  
  35.     }  
  36.   
  37.     @Override  
  38.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  39.         if(mFragmentView == null) {  
  40.             mFragmentView = (TextView) inflater.inflate(R.layout.fragment, container, false);  
  41.             //获得索引值  
  42.             Bundle bundle = getArguments();  
  43.             if (bundle != null) {  
  44.                 mCurIndex = bundle.getInt(FRAGMENT_INDEX);  
  45.             }  
  46.             isPrepared = true;  
  47.             lazyLoad();  
  48.         }  
  49.           
  50.         //因为共用一个Fragment视图,所以当前这个视图已被加载到Activity中,必须先清除后再加入Activity  
  51.         ViewGroup parent = (ViewGroup)mFragmentView.getParent();  
  52.         if(parent != null) {  
  53.             parent.removeView(mFragmentView);  
  54.         }  
  55.         return mFragmentView;  
  56.     }  
  57.   
  58.     @Override  
  59.     protected void lazyLoad() {  
  60.         if (!isPrepared || !isVisible || mHasLoadedOnce) {  
  61.             return;  
  62.         }  
  63.   
  64.         new AsyncTask<Void, Void, Boolean>() {  
  65.   
  66.             @Override  
  67.             protected void onPreExecute() {  
  68.                 super.onPreExecute();  
  69.                 //显示加载进度对话框  
  70.                 UIHelper.showDialogForLoading(getActivity(), "正在加载..."true);  
  71.             }  
  72.   
  73.             @Override  
  74.             protected Boolean doInBackground(Void... params) {  
  75.                 try {  
  76.                     Thread.sleep(2000);  
  77.                     //在这里添加调用接口获取数据的代码  
  78.                     //doSomething()  
  79.                 } catch (Exception e) {  
  80.                     e.printStackTrace();  
  81.                 }  
  82.                 return true;  
  83.             }  
  84.   
  85.             @Override  
  86.             protected void onPostExecute(Boolean isSuccess) {  
  87.                 if (isSuccess) {  
  88.                     // 加载成功  
  89.                     setView();  
  90.                     mHasLoadedOnce = true;  
  91.                 } else {  
  92.                     // 加载失败  
  93.                 }  
  94.                 //关闭对话框  
  95.                 UIHelper.hideDialogForLoading();  
  96.             }  
  97.         }.execute();  
  98.     }  
  99.   
  100.     private void setView() {  
  101.         // 根据索引加载不同视图  
  102.         switch (mCurIndex) {  
  103.         case FIRST_FRAGMENT:  
  104.             mFragmentView.setText("第一个");  
  105.             break;  
  106.   
  107.         case SECOND_FRAGMENT:  
  108.             mFragmentView.setText("第二个");  
  109.             break;  
  110.   
  111.         case THIRD_FRAGMENT:  
  112.             mFragmentView.setText("第三个");  
  113.             break;  
  114.         }  
  115.     }  
  116. }  

到这里我们只是写好了Fragment,在FragmentActivity中还需要对ViewPager设置一下,让它每次只加载一个Fragment,ViewPager.setOffscreenPageLimit(int limit),其中参数可以设为0或者1,参数小于1时,会默认用1来作为参数,未设置之前,ViewPager会默认加载两个Fragment。所以,我们只需要调用下它,设置下加载Fragment个数即可。

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  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.   
  12. public class MainActivity extends FragmentActivity implements OnClickListener{  
  13.   
  14.     private RadioButton mFstBtn;  
  15.     private RadioButton mSndBtn;  
  16.     private RadioButton mThdBtn;  
  17.       
  18.     private ViewPager mViewPager;  
  19.     private ListFragmentPagerAdapter mPagerAdapter;  
  20.     private List<Fragment> mFragments = new ArrayList<Fragment>();  
  21.       
  22.     private final int FIRST_FRAGMENT = 0;  
  23.     private final int SECOND_FRAGMENT = 1;  
  24.     private final int THIRD_FRAGMENT = 2;  
  25.       
  26.       
  27.     @Override  
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.activity_main);  
  31.         initButton();  
  32.         initViewPager();  
  33.     }  
  34.       
  35.       
  36.     /** 
  37.      * 初始化按钮 
  38.      */  
  39.     private void initButton() {  
  40.         mFstBtn = (RadioButton)findViewById(R.id.id_rb_fst);  
  41.         mFstBtn.setOnClickListener(this);  
  42.         mSndBtn = (RadioButton)findViewById(R.id.id_rb_snd);  
  43.         mSndBtn.setOnClickListener(this);  
  44.         mThdBtn = (RadioButton)findViewById(R.id.id_rb_thd);  
  45.         mThdBtn.setOnClickListener(this);  
  46.     }  
  47.       
  48.       
  49.     /** 
  50.      * 初始化ViewPager控件 
  51.      */  
  52.     private void initViewPager() {  
  53.         mViewPager = (ViewPager)findViewById(R.id.id_vp_viewpager);  
  54.         //关闭预加载,默认一次只加载一个Fragment  
  55.         mViewPager.setOffscreenPageLimit(1);  
  56.         //添加Fragment  
  57.         mFragments.add(CustomListFragment.newInstance(FIRST_FRAGMENT));  
  58.         mFragments.add(CustomListFragment.newInstance(SECOND_FRAGMENT));  
  59.         mFragments.add(CustomListFragment.newInstance(THIRD_FRAGMENT));  
  60.         //适配器  
  61.         mPagerAdapter = new ListFragmentPagerAdapter(getSupportFragmentManager(), mFragments);  
  62.         mViewPager.setAdapter(mPagerAdapter);  
  63.         mViewPager.setOnPageChangeListener(onPageChangeListener);  
  64.     }  
  65.   
  66.       
  67.     private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {  
  68.           
  69.         @Override  
  70.         public void onPageSelected(int position) {  
  71.             //根据用户选中的按钮修改按钮样式  
  72.             switch (position) {  
  73.             case FIRST_FRAGMENT:  
  74.                 mFstBtn.setChecked(true);  
  75.                 mSndBtn.setChecked(false);  
  76.                 mThdBtn.setChecked(false);  
  77.                 break;  
  78.   
  79.             case SECOND_FRAGMENT:  
  80.                 mFstBtn.setChecked(false);  
  81.                 mSndBtn.setChecked(true);  
  82.                 mThdBtn.setChecked(false);  
  83.                 break;  
  84.                   
  85.             case THIRD_FRAGMENT:  
  86.                 mFstBtn.setChecked(false);  
  87.                 mSndBtn.setChecked(false);  
  88.                 mThdBtn.setChecked(true);  
  89.             break;  
  90.             }  
  91.         }  
  92.           
  93.         @Override  
  94.         public void onPageScrolled(int arg0, float arg1, int arg2) {}  
  95.           
  96.         @Override  
  97.         public void onPageScrollStateChanged(int arg0) {}  
  98.     };  
  99.       
  100.       
  101.     @Override  
  102.     public void onClick(View v) {  
  103.         switch (v.getId()) {  
  104.         case R.id.id_rb_fst:  
  105.             mViewPager.setCurrentItem(FIRST_FRAGMENT);  
  106.             break;  
  107.   
  108.         case R.id.id_rb_snd:  
  109.             mViewPager.setCurrentItem(SECOND_FRAGMENT);  
  110.             break;  
  111.               
  112.         case R.id.id_rb_thd:  
  113.             mViewPager.setCurrentItem(THIRD_FRAGMENT);  
  114.             break;  
  115.         }  
  116.     }  
  117. }  

源码下载


0 0
原创粉丝点击