1. 程式人生 > >ViewPager+Fragment取消預載入(延遲載入)

ViewPager+Fragment取消預載入(延遲載入)

在專案中,都或多或少地使用的Tab佈局,所以大都會用到ViewPager+Fragment,但是Fragment有個不好或者太好的地方。例如你在ViewPager中添加了三個Fragment,當載入ViewPager中第一個Fragment時,它會預設幫你預先載入了第二個Fragment,當你載入第二個Fragment時,它會幫你載入第三個Fragment。這樣雖然有時很好,但是使用者只需看一個Fragment時,我們就做了一些多餘工作載入了第二個Fragment。在這隻需要取消Fragment的預載入即可,只有當用戶切換到某個Fragment才載入..

\

首先,介紹兩個方法void setUserVisibleHint(boolean isVisibleToUser)、boolean getUserVisibleHint()

,它們分別用作設定/獲得Fragment可見狀態,我們可以重寫Fragment在其中做判斷,程式碼如下:

 

import android.support.v4.app.Fragment;

public abstract class BaseFragment extends Fragment {
	
	/** Fragment當前狀態是否可見 */
	protected boolean isVisible;
	
	
	@Override
	public void setUserVisibleHint(boolean isVisibleToUser) {
		super.setUserVisibleHint(isVisibleToUser);
		
		if(getUserVisibleHint()) {
			isVisible = true;
			onVisible();
		} else {
			isVisible = false;
			onInvisible();
		}
	}
	
	
	/**
	 * 可見
	 */
	protected void onVisible() {
		lazyLoad();		
	}
	
	
	/**
	 * 不可見
	 */
	protected void onInvisible() {
		
		
	}
	
	
	/** 
	 * 延遲載入
	 * 子類必須重寫此方法
	 */
	protected abstract void lazyLoad();
}

在我們的Fragment中,只需要繼承這個類,然後重寫其中的lazyLoad()方法,當Fragment對使用者可見(即使用者切換到此Fragment時)我們在lazyLoad()中載入所需資料,詳細程式碼看下面,我寫了個假的獲取資料執行緒:

 

 

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class CustomListFragment extends BaseFragment {

	private static final String FRAGMENT_INDEX = fragment_index;
	private final int FIRST_FRAGMENT = 0;
	private final int SECOND_FRAGMENT = 1;
	private final int THIRD_FRAGMENT = 2;

	private TextView mFragmentView;

	private int mCurIndex = -1;
	/** 標誌位,標誌已經初始化完成 */
	private boolean isPrepared;
	/** 是否已被載入過一次,第二次就不再去請求資料了 */
	private boolean mHasLoadedOnce;

	/**
	 * 建立新例項
	 * 
	 * @param index
	 * @return
	 */
	public static CustomListFragment newInstance(int index) {
		Bundle bundle = new Bundle();
		bundle.putInt(FRAGMENT_INDEX, index);
		CustomListFragment fragment = new CustomListFragment();
		fragment.setArguments(bundle);
		return fragment;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		if(mFragmentView == null) {
			mFragmentView = (TextView) inflater.inflate(R.layout.fragment, container, false);
			//獲得索引值
			Bundle bundle = getArguments();
			if (bundle != null) {
				mCurIndex = bundle.getInt(FRAGMENT_INDEX);
			}
			isPrepared = true;
			lazyLoad();
		}
		
		//因為共用一個Fragment檢視,所以當前這個檢視已被載入到Activity中,必須先清除後再加入Activity
		ViewGroup parent = (ViewGroup)mFragmentView.getParent();
		if(parent != null) {
			parent.removeView(mFragmentView);
		}
		return mFragmentView;
	}

	@Override
	protected void lazyLoad() {
		if (!isPrepared || !isVisible || mHasLoadedOnce) {
			return;
		}

		new AsyncTask() {

			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				//顯示載入進度對話方塊
				UIHelper.showDialogForLoading(getActivity(), 正在載入..., true);
			}

			@Override
			protected Boolean doInBackground(Void... params) {
				try {
					Thread.sleep(2000);
					//在這裡新增呼叫介面獲取資料的程式碼
					//doSomething()
				} catch (Exception e) {
					e.printStackTrace();
				}
				return true;
			}

			@Override
			protected void onPostExecute(Boolean isSuccess) {
				if (isSuccess) {
					// 載入成功
					setView();
					mHasLoadedOnce = true;
				} else {
					// 載入失敗
				}
				//關閉對話方塊
				UIHelper.hideDialogForLoading();
			}
		}.execute();
	}

	private void setView() {
		// 根據索引載入不同檢視
		switch (mCurIndex) {
		case FIRST_FRAGMENT:
			mFragmentView.setText(第一個);
			break;

		case SECOND_FRAGMENT:
			mFragmentView.setText(第二個);
			break;

		case THIRD_FRAGMENT:
			mFragmentView.setText(第三個);
			break;
		}
	}
}

到這裡我們只是寫好了Fragment,在FragmentActivity中還需要對ViewPager設定一下,讓它每次只加載一個Fragment, ViewPager.setOffscreenPageLimit(int limit) ,其中引數可以設為0或者1,引數小於1時,會預設用1來作為引數,未設定之前,ViewPager會預設載入兩個Fragment。所以,我們只需要呼叫下它,設定下載入Fragment個數即可。

 

 

import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RadioButton;
import android.os.Bundle;

public class MainActivity extends FragmentActivity implements OnClickListener{

	private RadioButton mFstBtn;
	private RadioButton mSndBtn;
	private RadioButton mThdBtn;
	
	private ViewPager mViewPager;
	private ListFragmentPagerAdapter mPagerAdapter;
	private List mFragments = new ArrayList();
	
	private final int FIRST_FRAGMENT = 0;
	private final int SECOND_FRAGMENT = 1;
	private final int THIRD_FRAGMENT = 2;
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initButton();
		initViewPager();
	}
	
	
	/**
	 * 初始化按鈕
	 */
	private void initButton() {
		mFstBtn = (RadioButton)findViewById(R.id.id_rb_fst);
		mFstBtn.setOnClickListener(this);
		mSndBtn = (RadioButton)findViewById(R.id.id_rb_snd);
		mSndBtn.setOnClickListener(this);
		mThdBtn = (RadioButton)findViewById(R.id.id_rb_thd);
		mThdBtn.setOnClickListener(this);
	}
	
	
	/**
	 * 初始化ViewPager控制元件
	 */
	private void initViewPager() {
		mViewPager = (ViewPager)findViewById(R.id.id_vp_viewpager);
		//關閉預載入,預設一次只加載一個Fragment
		mViewPager.setOffscreenPageLimit(1);
		//新增Fragment
		mFragments.add(CustomListFragment.newInstance(FIRST_FRAGMENT));
		mFragments.add(CustomListFragment.newInstance(SECOND_FRAGMENT));
		mFragments.add(CustomListFragment.newInstance(THIRD_FRAGMENT));
		//介面卡
		mPagerAdapter = new ListFragmentPagerAdapter(getSupportFragmentManager(), mFragments);
		mViewPager.setAdapter(mPagerAdapter);
		mViewPager.setOnPageChangeListener(onPageChangeListener);
	}

	
	private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
		
		@Override
		public void onPageSelected(int position) {
			//根據使用者選中的按鈕修改按鈕樣式
			switch (position) {
			case FIRST_FRAGMENT:
				mFstBtn.setChecked(true);
				mSndBtn.setChecked(false);
				mThdBtn.setChecked(false);
				break;

			case SECOND_FRAGMENT:
				mFstBtn.setChecked(false);
				mSndBtn.setChecked(true);
				mThdBtn.setChecked(false);
				break;
				
			case THIRD_FRAGMENT:
				mFstBtn.setChecked(false);
				mSndBtn.setChecked(false);
				mThdBtn.setChecked(true);
			break;
			}
		}
		
		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {}
		
		@Override
		public void onPageScrollStateChanged(int arg0) {}
	};
	
	
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.id_rb_fst:
			mViewPager.setCurrentItem(FIRST_FRAGMENT);
			break;

		case R.id.id_rb_snd:
			mViewPager.setCurrentItem(SECOND_FRAGMENT);
			break;
			
		case R.id.id_rb_thd:
			mViewPager.setCurrentItem(THIRD_FRAGMENT);
			break;
		}
	}
}