问题
众所周知我们在开发中常常会使用ViewPager和Fragment的组合,但是使用这样的组合页面在滑动的时候会有一些问题,比如从第一页滑动到第四页,再从第四页滑动到第一页,这个时候第一页的fragment会经历自身的两次生命周期的回调(从onCreate到onDestory),那么这个时候,界面被销毁,这个时候我们需要重新生产界面,填充数据。这个是我们不想看到的,每次滑动回来的时候,重新生成界面,重新请求网络数据。
分析
出现这种问题的原因
- 界面被销毁是由于fragment的生命周期被重新调用,创建的view被回收
- 数据重新加载,原因一部分数据设置为局部变量,fragment的生命周期被重新调用后无法获取引用;原因二,部分开发者可能认为fragment的生命周期被重新调用,那么fragment的变量都没有意义了,成员变量也需要重新生成。
解决方案
- 要强调的是fragment的生命周期被重新调用,但是其成员变量并没有被销毁
fragment中数据不需要重复加载,数据可以设置为成员变量,当fragment生命周期重新调用,请求数据的时候首先判断数据是否为空,不为空则不需要请求数据,可以直接用现有数据,当然刷新数据没有问题。
public class FragmentOne extends Fragment { private static final String TAG = FragmentOne.class.getSimpleName(); int mIndex;
onCreateView的时候,保存创建的rootview,并且在fragment重新调用onCreateView的时候判断是否为空,如果不为空就不需要重新创建view了,当然这可以判断也可以不断地,可以每次都创建,看需要,如果重复创建view又需要view还原到原来操作的位置,比如listview滑动的位置,这个时候就需要保存一下了。
public class FragmentOne extends Fragment { private static final String TAG = FragmentOne.class.getSimpleName(); View mRootView;
@Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mScrollView != null) { outState.putInt("y", mScrollView.getScrollY()); } Log.d(TAG, mScrollView + " , onSaveInstanceState : " + outState); }
- 填充数据,数据有了(不需要网络请求,也就是说不需要等待马上就有数据),界面可以重复创建也可以不重复创建,当然界面生成的时间人肉眼几乎是看不到的,数据和界面都及时生成,那么对于用户来说,就像是fragment的生命周期没有重新调用一样。
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (mRootView != null) {
ButterKnife.bind(this, mRootView);
return mRootView;
}
mRootView = inflater.inflate(R.layout.count_fragment, container, false);
ButterKnife.bind(this, mRootView);
mCount.setText("" + mIndex);
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.home, container, false);
ButterKnife.bind(this, root);
mPromotionPager.setAdapter(new PromotionAdapter());
Log.d(TAG, "onCreateView state : " + savedInstanceState);
if (savedInstanceState != null) {
mScrollView.setScrollY(savedInstanceState.getInt("y"));
}
return root;
}
这样ViewPager每次来回滑动的时候Fragment就不会重复加载数据了。