文/程序員男神
前言
最近醫(yī)院上線,我們開發(fā)都奔赴醫(yī)院現(xiàn)場支持,每天加班到很晚射亏。自己也搞的精神不振罪裹,還好都把問題解決了。后面的幾天輕松了不少。本文就是最近在開發(fā)新需求遇到的問題,記錄下來以便后面供自己參考。
問題描述
在android開發(fā)中徐绑,經(jīng)常會用到ViewPager+Fragment來實現(xiàn)切換Tab頁。但是莫辨,由于ViewPager的內(nèi)部機制傲茄,它總會默認至少預(yù)加載一個頁面。
因為有時候用戶希望選擇了哪個Tab再去加載哪個Tab的數(shù)據(jù)沮榜,而不是預(yù)加載盘榨,如果當前頁面和預(yù)加載頁面都需要實時刷新當前Fragment,或者有大量的網(wǎng)絡(luò)請求蟆融,可能就會比較慢草巡。
解決方案1:
ViewPager因為內(nèi)部機制,有預(yù)加載機制型酥。那我們直接把ViewPager的預(yù)加載設(shè)置為0不就可以了山憨?
vp.setOffscreenPageLimit(0);
查看源碼:
/**
* Set the number of pages that should be retained to either side of the
* current page in the view hierarchy in an idle state. Pages beyond this
* limit will be recreated from the adapter when needed.
*
* <p>This is offered as an optimization. If you know in advance the number
* of pages you will need to support or have lazy-loading mechanisms in place
* on your pages, tweaking this setting can have benefits in perceived smoothness
* of paging animations and interaction. If you have a small number of pages (3-4)
* that you can keep active all at once, less time will be spent in layout for
* newly created view subtrees as the user pages back and forth.</p>
*
* <p>You should keep this limit low, especially if your pages have complex layouts.
* This setting defaults to 1.</p>
*
* @param limit How many pages will be kept offscreen in an idle state.
*/
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
+ DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}
我們分析得知:即使設(shè)置為0,也會把limit設(shè)置為默認值1弥喉。
解決方案2:
package com.winning.rims.tabtest.tst;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
/**
* Fragment預(yù)加載問題的解決方案:
* 1.可以懶加載的Fragment
* 2.切換到其他頁面時停止加載數(shù)據(jù)(可選)
* Created by dj on 2018-09-10.
* blog :http://blog.csdn.net/linglongxin24/article/details/53205878
*/
public abstract class BaseFragment extends Fragment {
/**
* 視圖是否已經(jīng)初初始化
*/
protected boolean isInit = false;
protected boolean isLoad = false;
protected final String TAG = "BaseFragment";
private View view;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(setContentView(), container, false);
isInit = true;
/**初始化的時候去加載數(shù)據(jù)**/
isCanLoadData();
return view;
}
/**
* 視圖是否已經(jīng)對用戶可見郁竟,系統(tǒng)的方法
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
isCanLoadData();
}
/**
* 是否可以加載數(shù)據(jù)
* 可以加載數(shù)據(jù)的條件:
* 1.視圖已經(jīng)初始化
* 2.視圖對用戶可見
*/
private void isCanLoadData() {
if (!isInit) {
return;
}
if (getUserVisibleHint()) {
lazyLoad();
isLoad = true;
} else {
if (isLoad) {
stopLoad();
}
}
}
/**
* 視圖銷毀的時候講Fragment是否初始化的狀態(tài)變?yōu)閒alse
*/
@Override
public void onDestroyView() {
super.onDestroyView();
isInit = false;
isLoad = false;
}
protected void showToast(String message) {
if (!TextUtils.isEmpty(message)) {
Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
}
}
/**
* 設(shè)置Fragment要顯示的布局
*
* @return 布局的layoutId
*/
protected abstract int setContentView();
/**
* 獲取設(shè)置的布局
*
* @return
*/
protected View getContentView() {
return view;
}
/**
* 找出對應(yīng)的控件
*
* @param id
* @param <T>
* @return
*/
protected <T extends View> T findViewById(int id) {
return (T) getContentView().findViewById(id);
}
/**
* 當視圖初始化并且對用戶可見的時候去真正的加載數(shù)據(jù)
*/
protected abstract void lazyLoad();
/**
* 當視圖已經(jīng)對用戶不可見并且加載過數(shù)據(jù),如果需要在切換到其他頁面時停止加載數(shù)據(jù)档桃,可以調(diào)用此方法
*/
protected void stopLoad() {
}
}
方案2的用法:
(1)枪孩、創(chuàng)建新的Fragment類,繼承BaseFragment藻肄;
(2)、setContentView()拒担,返回該xml布局文件嘹屯;
(3)、lazyLoad()从撼,在此方法內(nèi)加載需要的數(shù)據(jù)州弟;
(4)钧栖、stopLoad()方法可選,當視圖已經(jīng)對用戶不可見并且加載過數(shù)據(jù)婆翔,如果需要在切換到其他頁面時停止加載數(shù)據(jù)拯杠,可以覆寫此方法。
package com.winning.rims.tabtest.tst;
import android.util.Log;
import com.winning.rims.tabtest.R;
/**
* 描述: Fragment1
* 作者|時間: djj on 2018/9/11 16:14
* 博客地址: http://www.reibang.com/u/dfbde65a03fc
*
*/
public class Fragment1 extends BaseFragment {
@Override
public int setContentView() {
return R.layout.fm_layout1;
}
@Override
protected void lazyLoad() {
String message = "Fragment1" + (isInit ? "已經(jīng)初始并已經(jīng)顯示給用戶可以加載數(shù)據(jù)" : "沒有初始化不能加載數(shù)據(jù)")+">>>>>>>>>>>>>>>>>>>";
showToast(message);
Log.d(TAG, message);
}
@Override
protected void stopLoad() {
Log.d(TAG, "Fragment1" + "已經(jīng)對用戶不可見啃奴,可以停止加載數(shù)據(jù)");
}
}
fm_layout1 xmL布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="22sp"
android:textColor="@color/colorAccent"
android:text="第一個Fragment" />
</LinearLayout>
其他Fragment一樣潭陪,不在此多舉例子。
activity 中的代碼實例:
package com.winning.rims.tabtest.tst;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.RadioGroup;
import com.winning.rims.tabtest.R;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RadioGroup rg;
private ViewPager vp;
private void assignViews() {
rg = (RadioGroup) findViewById(R.id.rg);
vp = (ViewPager) findViewById(R.id.vp);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
assignViews();
initData();
}
private void initData() {
final List<Fragment> fragments = new ArrayList<>();
fragments.add(new Fragment1());
fragments.add(new Fragment2());
fragments.add(new Fragment3());
fragments.add(new Fragment4());
vp.setOffscreenPageLimit(0);
vp.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
});
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
vp.setCurrentItem(radioGroup.indexOfChild(radioGroup.findViewById(i)));
}
});
}
}
activity_main1 xml布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".tst.MainActivity">
<RadioGroup
android:id="@+id/rg"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_weight="1"
android:background="#FFFFFF"
android:button="@null"
android:gravity="center"
android:text="第一個"
android:textColor="#000000"
android:textSize="18sp" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_weight="1"
android:background="#FFFFFF"
android:button="@null"
android:gravity="center"
android:text="第二個"
android:textColor="#000000"
android:textSize="18sp" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_weight="1"
android:background="#FFFFFF"
android:button="@null"
android:gravity="center"
android:text="第三個"
android:textColor="#000000"
android:textSize="18sp" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_weight="1"
android:background="#FFFFFF"
android:button="@null"
android:gravity="center"
android:text="第四個"
android:textColor="#000000"
android:textSize="18sp" />
</RadioGroup>
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
日志
通過查看日志最蕾,我們發(fā)現(xiàn)依溯,每次切換,都會先走stopLoad(),然后才去調(diào)用lazyLoad()方法瘟则。
總結(jié):
雖然參考到別人代碼黎炉,但是自己敲了一遍,還是很有收獲的醋拧,解決問題慷嗜,不需要焦頭爛額的思考的感覺真好。加油丹壕,真好洪添。哈哈哈...
參考代碼:https://blog.csdn.net/linglongxin24/article/details/53205878