Android之Viewpager+Fragment实现懒加载示例
Viewpager + Fragment 是我们 Android 开发中比较经常用到的一种组合。然而,在实际开发中,我们会发现 Fragment 的生命周期比较独特,而 Viewpager + Fragment 在配合使用时会出现一些让人头疼的问题,比如说 ViewPager 内的 Fragment 会在 ViewPager 初始化之后都会先执行一遍生命周期方法,导致了页面切换卡顿等问题。因此,我们需要通过一些技巧来解决这个问题,提升用户体验。
本文将介绍一种常见的解决方案,即实现 Fragment 的懒加载。这种方案可以让我们的 ViewPager 内的 Fragment 在切换时只加载当前展示的 Fragment,避免了无意义的性能开销。
下面就来具体讲解如何实现 Fragment 的懒加载。
# Fragment 的生命周期方法
为了实现 Fragment 的懒加载,我们需要了解 Fragment 的生命周期方法。一般而言,Fragment 的生命周期包括以下方法:
- onAttach:当 Fragment 被添加到 Activity 中时调用。
- onCreate:当 Fragment 被创建时调用。
- onCreateView:创建该 Fragment 的 View 时调用。
- onActivityCreated:当 Activity 的 onCreated 方法执行完后调用。
- onStart:当 Fragment 可见时调用。
- onResume:当 Fragment 可交互时调用。
- onPause:当 Fragment 失去焦点时调用。
- onStop:当 Fragment 不可见时调用。
- onDestroyView:当该 Fragment 的 View 被销毁时调用。
- onDestroy:当 Fragment 被销毁时调用。
- onDetach:当 Fragment 从 Activity 中移除时调用。
# 实现方式
那么,如何实现 Fragment 的懒加载呢?主要的思路就在 onCreateView 这个方法上。我们可以在该方法中判断 Fragment 是否已经准备好了数据,如果没有,再进行加载。
具体的实现可以参考下面这段代码:
public class LazyFragment extends Fragment {
private boolean isPrepared;
private boolean isVisible;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint()) {
isVisible = true;
lazyLoad();
} else {
isVisible = false;
onInvisible();
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isPrepared = true;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
/**
* 懒加载
*/
protected void lazyLoad() {
if (!isPrepared || !isVisible) {
return;
}
// 加载数据
}
protected void onInvisible() {
// Fragment 不可见时的处理操作
}
}
在这里,我们使用了两个 Boolean 类型的变量,isPrepared 和 isVisible,分别代表该 Fragment 是否准备好了数据和是否可见。通过重写 setUserVisibleHint 方法和 onCreateView 方法,我们可以在 onCreateView 方法中判断是否需要加载数据。
其中,setUserVisibleHint 方法会在 Fragment 可见性发生变化时被调用,而 onCreateView 方法则会在创建 Fragment 的 View 时进行调用。在 setUserVisibleHint 方法中,根据变量 isVisible 判断 Fragment 是否可见,如果可见则调用 lazyLoad 方法进行加载;反之,则调用 onInvisible 方法进行处理。在 lazyLoad 方法中,根据变量 isPrepared 判断 Fragment 是否准备好了数据,如果都准备好了,则进行数据加载的操作。
# 在 AdapterView 和 FragmentPagerAdapter 中使用
当使用 AdapterView 和 FragmentPagerAdapter 等相关的类时,在使用 Fragment 进行懒加载时需要额外注意。
对于 AdapterView,我们需要重写 onWindowFocusChanged 方法,并在该方法中调用判断 Fragment 是否需要进行懒加载的操作。比如下面这样:
public class LazyListView extends ListView {
private boolean mIsFirstVisible;
private boolean mIsVisible;
public LazyListView(Context context) {
super(context);
init();
}
public LazyListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LazyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// 次可见
mIsFirstVisible = true;
// 是否可见
mIsVisible = false;
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == VISIBLE) {
if (mIsFirstVisible) {
mIsFirstVisible = false;
// 次可见时,需要进行加载
lazyLoad();
} else {
// 如果已经不是 次出现,则需要判断 Fragment 是否可见
if (mIsVisible) {
lazyLoad();
}
}
mIsVisible = true;
} else {
mIsVisible = false;
}
}
/**
* 懒加载
*/
private void lazyLoad() {
// 加载数据
}
}
对于 FragmentPagerAdapter,我们可以在 getItem 方法中调用懒加载的操作,在 onCreateView 和 setUserVisibleHint 方法中判断是否需要进行加载操作。比如下面这样:
public class LazyFragmentPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragments;
public LazyFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
@Override
public Fragment getItem(int position) {
Fragment fragment = mFragments.get(position);
// 调用懒加载的操作
Bundle bundle = new Bundle();
bundle.putString("key", fragment.getClass().getSimpleName());
fragment.setArguments(bundle);
return fragment;
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
Bundle bundle = fragment.getArguments();
if (bundle != null) {
String key = bundle.getString("key");
if (TextUtils.equals(key, FragmentA.class.getSimpleName())
|| TextUtils.equals(key, FragmentB.class.getSimpleName())) {
// 关键代码:重载 Fragment,改变实例 Fragment 的 setUserVisibleHint 时的回调逻辑
fragment.setUserVisibleHint(false);
}
}
return fragment;
}
}
# 总结
以上就是实现 Fragment 的懒加载的一种常见方法。在实际开发中我们可以根据需求进行改造和优化。通过懒加载方案的实现我们可以有效减少无用资源的消耗,优化用户体验。
