ViewPager+Fragment 懶加載
阿新 • • 發佈:2017-09-25
activit svi class span you ace -1 ring rep
鏈接:http://www.jianshu.com/p/c5d29a0c3f4c
來源:簡書 ViewPager+Fragment的模式再常見不過了,以國民應用微信為例,假設微信也是ViewPager+Fragment的實現方式,那表現形式上就是一個ViewPager管理了四個Fragment,左右滑動來回切換。但是ViewPager有一個奇葩的特性叫:預加載,比如打開微信,首先看到的是第一個Tab(微信),但事實上第二個Tab(通訊錄)已經加載好了。當選擇第二個Tab(通訊錄),第三個Tab(發現)已經加載好了,以此類推。
但上訴ViewPager+Fragment的這種組合並不完美,因為我希望用戶選擇了哪個Tab再去加載哪個Tab的數據,而不要去做預加載,假如當前頁面和預加載頁面都有大量的網絡請求,可能就會比較慢,有很多請求在排隊。關於這個問題,也有很偏激的做法,比如棄用ViewPager,自己手動管理Fragment,或者直接禁掉ViewPager預加載。有一種比較合適的方案是保持ViewPager預加載的特性,但是只初始化View,選擇當前Tab的時候再進行網絡請求。關於這一方案的實現,也是眾說紛紜,千奇百怪。
直接上代碼。
轉載於:
作者:尹star鏈接:http://www.jianshu.com/p/c5d29a0c3f4c
來源:簡書 ViewPager+Fragment的模式再常見不過了,以國民應用微信為例,假設微信也是ViewPager+Fragment的實現方式,那表現形式上就是一個ViewPager管理了四個Fragment,左右滑動來回切換。但是ViewPager有一個奇葩的特性叫:預加載,比如打開微信,首先看到的是第一個Tab(微信),但事實上第二個Tab(通訊錄)已經加載好了。當選擇第二個Tab(通訊錄),第三個Tab(發現)已經加載好了,以此類推。
但上訴ViewPager+Fragment的這種組合並不完美,因為我希望用戶選擇了哪個Tab再去加載哪個Tab的數據,而不要去做預加載,假如當前頁面和預加載頁面都有大量的網絡請求,可能就會比較慢,有很多請求在排隊。關於這個問題,也有很偏激的做法,比如棄用ViewPager,自己手動管理Fragment,或者直接禁掉ViewPager預加載。有一種比較合適的方案是保持ViewPager預加載的特性,但是只初始化View,選擇當前Tab的時候再進行網絡請求。關於這一方案的實現,也是眾說紛紜,千奇百怪。
直接上代碼。
public這是一個父類,看代碼這裏只有一個setUserVisibleHint需要說下,這是一個相當生僻的方法,我們可以用這個方法來判斷當前UI是否可見,所以在prepareFetchData方法裏我們做如下判斷:就是當前UI可見,並且fragment已經初始化完畢,如果網絡數據未加載,那麽請求數據,或者需要強制刷新頁面,那麽也去請求數據,So easy。子Fragment只需要繼承父類,實現抽象方法,在fetchData()裏做網絡請求或者其他耗時操作即可。再在寫個子類吧。abstract class BasePageFragment extends Fragment { protected boolean isViewInitiated; protected boolean isVisibleToUser; protected boolean isDataInitiated; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Overridepublic void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); isViewInitiated = true; prepareFetchData(); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser);this.isVisibleToUser = isVisibleToUser; prepareFetchData(); } public abstract void fetchData(); public boolean prepareFetchData() { return prepareFetchData(false); } public boolean prepareFetchData(boolean forceUpdate) { if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) { fetchData(); isDataInitiated = true; return true; } return false; } }
public class PageFragment extends BasePageFragment { public static PageFragment newInstance(String title){ PageFragment fragment = new PageFragment(); Bundle args = new Bundle(); args.putString("key_fragment_title", title); fragment.setArguments(args); return fragment; } private String title; private TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); title = getArguments().getString("key_fragment_title"); Trace.d(title + ":onCreate"); } @Override public void onResume() { super.onResume(); Trace.d(title + ":onResume"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Trace.d(title + ":onCreateView"); tv = new TextView(getActivity()); return tv; } @Override public void fetchData() { tv.setText(title); /** * 在這裏請求網絡。 */ } }
如果你也有這樣的需求或者煩惱,保證藥到病除。
有同學說實踐過程中遇到了些問題,比如Fragment只刷新一次,這個問題只要手動調用prepareFetchData(),傳true即可強制刷新了。還有同學質疑setUserVisibleHint()和onActivityCreated()的執行先後的問題。關於這個請看下圖。
ViewPager+Fragment 懶加載