使用viewpager默認會加載至少一個view,項目中有的頁面中的大圖比較多,如果一起加載比較耗時,並且浪費數據流量,我們想把viewpager滑動到哪頁加載哪頁,也就是viewpager懶加載方法。
首先看下Activity
private void initView() {
mPagerAdapter.addFragment(new OnlineArtistWesternFragment(OnlineArtistsActivity.this));
mPagerAdapter.addFragment(new OnlineArtistChinaFragment(OnlineArtistsActivity.this));
mPagerAdapter.addFragment(new OnlineArtistJapanFragment(OnlineArtistsActivity.this));
mViewPager.setPageMarginDrawable(R.drawable.viewpager_margin);
mViewPager.setOffscreenPageLimit(mPagerAdapter.getCount());
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(1);
initScrollableTabs(mViewPager);
}
/**
* Initiate the tabs
*/
public void initScrollableTabs(ViewPager mViewPager) {
ScrollableTabView mScrollingTabs = (ScrollableTabView) findViewById(R.id.online_artists_scrollingTabs);
ScrollingTabsAdapter mScrollingTabsAdapter = new ScrollingTabsOnlineAdapter(
OnlineArtistsActivity.this);
mScrollingTabs.setAdapter(mScrollingTabsAdapter);
mScrollingTabs.setViewPager(mViewPager);
fragment.java
onActivityCreate中
if (getUserVisibleHint() && isVisibleToUser){//getUserVisibleHint() 方法判斷界面是否可見
requestForData();
}
這樣做的作用是初始化時之加載當前view的數據,而不加載其他view的數據。保證初始化只加載一個view的數據
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {//設置當前界面可見
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser)
this.isVisibleToUser = true;
}
public void requestForData(){ //對外部提供方法,當界面滑動時請求數據加載
if (!isInit) {//確保只加載一次
requestForManInArea();//異步加載,加載完後刷新UI
requestForWomanArea();
requestForCombinationArea();
isInit = true;
}
}
viewpager的滑動監聽
@Override
public void onPageSelected(int position) {
selectTab(position);
if (mPager.getAdapter() instanceof PagerAdapter){
PagerAdapter pagerAdapter = (PagerAdapter) mPager.getAdapter();
if (pagerAdapter.getItem(position) instanceof OnlineArtistsFragment){
OnlineArtistsFragment onlineArtistsFragment = (OnlineArtistsFragment) pagerAdapter.getItem(position);
if (mPager.getCurrentItem() == 1)
return;
onlineArtistsFragment.requestForData();//請求數據加載
}
}
}
當我們設置mViewPager.setCurrentItem(1);時
會報出空指針,位置在我們調用控件引用刷新UI的地方。
查看ViewPager.java
public void setCurrentItem(int item, boolean smoothScroll) {
mPopulatePending = false;
setCurrentItemInternal(item, smoothScroll, false);
}
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {
setCurrentItemInternal(item, smoothScroll, always, 0);
}
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
if (mAdapter == null || mAdapter.getCount() <= 0) {
setScrollingCacheEnabled(false);
return;
}
if (!always && mCurItem == item && mItems.size() != 0) {
setScrollingCacheEnabled(false);
return;
}
if (item < 0) {
item = 0;
} else if (item >= mAdapter.getCount()) {
item = mAdapter.getCount() - 1;
}
final int pageLimit = mOffscreenPageLimit;
if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
// We are doing a jump by more than one page. To avoid
// glitches, we want to keep all current pages in the view
// until the scroll ends.
for (int i=0; i<mItems.size(); i++) {
mItems.get(i).scrolling = true;
}
}
final boolean dispatchSelected = mCurItem != item;
if (mFirstLayout) {//如果是第一次加載
// We don't have any idea how big we are yet and shouldn't have any pages either.
// Just set things up and let the pending layout handle things.
mCurItem = item;
if (dispatchSelected && mOnPageChangeListener != null) {
mOnPageChangeListener.onPageSelected(item);
}
if (dispatchSelected && mInternalPageChangeListener != null) {
mInternalPageChangeListener.onPageSelected(item);
}
requestLayout();
} else {
populate(item);
scrollToItem(item, smoothScroll, velocity, dispatchSelected);
}
}
看代碼我們知道,在setCurrentItem方法中,判斷是否是第一次加載,如果是,首先調用滑動監聽的onPageSelected回調方法,然後在requestLayout繪製界面
這樣的話 在滑動監聽中,我們調用了fragment的reqestData方法,其中會用到佈局控件的引用,但是界面還沒有繪製,控件引用還沒有初始化導致空指針問題。
解決方法:
在滑動監聽的onPageSelected回調中判斷position的值如果與我們設置的setCurrentItem 的position一樣,就return掉,讓viewPager直接去繪製界面。
否則請求數據加載。
if (mPager.getCurrentItem() == 1)
return;