八月十五号更新:
再次修改BaseFragment
public abstract class BaseFragment extends Fragment {
protected boolean isLoad;
protected boolean isPrepared;
protected boolean isVisible;
protected static final String FRAGMENT_INDEX = "fragment_index";
protected int index = 0;
protected int page = 1;
protected boolean isNull = false;
protected View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (view == null) {
view = initView(savedInstanceState);
isPrepared = true;
}
initById();
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint()) {
isVisible = true;
onVisible();
} else {
isVisible = false;
}
}
<T extends View> T getView(int id) {
//noinspection unchecked
return (T) view.findViewById(id);
}
private void onVisible() {
initData();
}
protected abstract View initView(Bundle savedInstanceState);
protected abstract void initById();
protected abstract void initData();
protected void setLoad() {
isLoad = true;
}
}
继承这个BaseFragment 因为setUserVisibleHint这个方法只有碰到ViewPager才会触发,所以所有的fragment都可以继承
继承Fragment
public class TestFragment extends BaseFragment {
@Override
protected View initView(Bundle savedInstanceState) {
return null;
}
@Override
protected void initById() {
}
@Override
protected void initData() {
if (!isPrepared || !isVisible || isLoad) {
return;
}
<span style="white-space:pre"> </span>//填充数据
setLoad();
}
}
在项目中使用Fragment和viewPager是很常见的事情,但是细心的人就会发现如果fragment有多个页面的话,当你还没切换到第二个页面的时候viewpager就已经把第二个页面在后台加载了,这个是viewpager的特性。
举个简单的例子:你在页面加个progressBar,让他显示一秒再消失,但是你打开App,然后等两秒,再切换到第二个页面,这个时候就会发现progressbar早已经消失了。
阅读viewpager的源码就会发现有这个方法setOf'fscreenPageLimit();
这个就是控制viewpager一次加载几个页面的方法,看原源码就会发现就算你传0,viewpager也会默认为1,通过修改viewpager可以实现不预加载,但是以后SDK更新的话你就用不到新东西,这个方法明显是不理想的.
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();
}
}
DFEAULT_OFFSCREEN_RAGES这个变量是1
再来看看Fragment的API,setUserVisibleHint这个方法告诉我们Fragment的UI是否是可见的。
很明显从这里下手可以得到想要的结果。
Demo采用了TabLayout和viewpager结合滑动效果
这里在絮叨一下TabLayout,tabMode有两个属性,一个是fixed,另一个是scrollable,前者是不管有几个tab,只占一个屏幕的宽度,后者自适应屏幕的宽度,滑动显示tab
现在想要的结果是切换哪个页面再加载哪个页面的数据为了效果明显加一个进度显示,这样很直观就可以看出来
这个是主页面的xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demo.fragmentdemo.MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/colorAccent" />
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
viewpager页面的xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="30sp" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
package demo.fragmentdemo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* by 12406 on 2016/5/12.
*/
public abstract class BaseFragment extends Fragment {
boolean isVisible;
static final String FRAGMENT_INDEX = "fragment_index";
int index = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
if (bundle != null) {
index = bundle.getInt(FRAGMENT_INDEX);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = initView();
initData();
return view;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint()) {
isVisible = true;
onVisible();
} else {
isVisible = false;
onInvisible();
}
}
private void onVisible() {
initData();
}
private void onInvisible() {
}
protected abstract View initView();
protected abstract void initData();
}
在可见的时候调用onVisible();不可见的时候去调用onInvisible();
继承BaseFragment的Fragment
package demo.fragmentdemo;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* by 12406 on 2016/5/12.
*/
public class DemoFragment extends BaseFragment {
private View inflate;
private TextView tv;
private boolean isPrepared;//初始化完成
private boolean isLoad;//是否加载过
private ProgressBar progressBar;
public static Fragment newInstance(int index) {
Bundle bundle = new Bundle();
DemoFragment fragment = new DemoFragment();
bundle.putInt(FRAGMENT_INDEX, index);
fragment.setArguments(bundle);
return fragment;
}
@Override
protected View initView() {
if (inflate == null) {
inflate = View.inflate(getActivity(), R.layout.fragment_viewpager, null);
tv = (TextView) inflate.findViewById(R.id.tv);
progressBar = (ProgressBar) inflate.findViewById(R.id.progressBar);
isPrepared = true;
}
return inflate;
}
@Override
protected void initData() {
if (!isPrepared || !isVisible || isLoad) {
return;
}
progressBar();
isLoad = true;
}
public void switchId(int id) {
switch (id) {
case 0:
tv.setText("界面一");
break;
case 1:
tv.setText("界面二");
break;
case 2:
tv.setText("界面三");
break;
case 3:
tv.setText("界面四");
break;
case 4:
tv.setText("界面五");
break;
case 5:
tv.setText("界面六");
break;
case 6:
tv.setText("界面七");
break;
}
}
public void progressBar() {
progressBar.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE);
switchId(index);
}
}, 1000);
}
}
用一个进度条很明显就可以看出来是否预加载了。
下载链接:Demo