您的位置:首页 > 移动开发 > Android开发

ViewPager+Fragment(二)装修房

2017-08-10 22:02 190 查看
上节课我们使用VF(ViewPager+Fragment)搭配使用做出了底部导航栏的效果,既然效果已经出来了为什么还需要写这篇文章呢?

1 毛坯房缺点

我们在每个Fragment中打上如下的log,然后点击导航菜单栏切换Fragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
Log.i("TAG", "onCreateView: four");
return inflater.inflate(R.layout.fragment_four, container, false);
}

@Override
public void onDestroyView() {
super.onDestroyView();
Log.i("TAG", "onDestroyView: FourFragment");
}




我在这里说明下FragmentStatePagerAdapter和FragmentPagerAdapter都是Fragment适配器,这个适配器的作用是什么呢?就是缓存和预加载页面,在这个例子中一共四个页面,当我点击第三个页面的时候,调用了1的销毁方法和4的创建方法,而此时2并没有销毁,仍然在缓存中只是不可见而已,当我们切换到2的页面时候,同理,4销毁,1创建,3不改变状态只是不可见。

猛地一看,哎呦,不错啊,安卓一直都需要我去缓存数据终于懂得主动帮我缓存数据了,当我很开心的时候,发现了很严重的问题:

我点到第3个就觉得没有意思了,不往下点了,可是系统仍然会预加载第四个界面的数据!如果第四个界面很简单那还好,要是数据很多,加杂各种动画,呵呵,那你的程序在内存中的消耗将无比巨大,这对于一个追求完美的程序员来说是不能容忍的

2 懒加载

不会偷懒的程序员不是好的程序员

1 我点击哪个页面加载哪个页面的数据,下一个页面的数据我不加载

2 刚刚加载过的页面如果马上又打开,不会去重新加载数据而是使用缓存数据


package com.viewpager02.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
* A simple {@link Fragment} subclass.
*/
public abstract class CommentFragment extends Fragment {
/**
* 标记已加载完成,保证懒加载只能加载一次
*/
private boolean hasLoaded = false;
/**
* 标记Fragment是否已经onCreate
*/
private boolean isCreated = false;
/**
* 界面对于用户是否可见
*/
private boolean isVisibleToUser = false;
private View view;

public CommentFragment() {
// Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
init(getView(inflater, getLayoutId(), container), savedInstanceState);
return view;
}

private View getView(LayoutInflater inflater, int layoutId, ViewGroup container) {
return inflater.inflate(layoutId, container, false);
}

public void init(View view, Bundle savedInstanceState) {
isCreated = true;
this.view = view;
lazyLoad(this.view, savedInstanceState);
}
/**
* 监听界面是否展示给用户,实现懒加载
* 这个方法也是网上的一些方法用的最多的一个,我的思路也是这个,不过把整体思路完善了一下
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.i("TAG", "setUserVisibleHint: ");
super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser = isVisibleToUser;//注:关键步骤
lazyLoad(view, null);
}

/**
* 懒加载方法,获取数据什么的放到这边来使用,在切换到这个界面时才进行网络请求
*/
private void lazyLoad(View view, Bundle savedInstanceState) {

//如果该界面不对用户显示、已经加载、fragment还没有创建,
//三种情况任意一种,不获取数据
if (!isVisibleToUser || hasLoaded || !isCreated) {
return;
}
lazyInit(view, savedInstanceState);
hasLoaded = true;//注:关键步骤,确保数据只加载一次
}

/**
* 子类必须实现的方法,这个方法里面的操作都是需要懒加载的
*/
public abstract void lazyInit(View view, Bundle savedInstanceState);
public abstract int getLayoutId();

@Override
public void onDestroyView() {
super.onDestroyView();
isCreated = false;
hasLoaded = false;
}

}


public class OneFragment extends CommentFragment {

@Override
public void lazyInit(View view, Bundle savedInstanceState) {
Log.i("TAG", "lazyInit: One!大量数据");//这里处理耗时操作请求数据
}

@Override
public int getLayoutId() {
return R.layout.fragment_one;//获取布局文件
}
}


查看Log日志



果然如我们所料,点击一个新的Fragment才会加载一个的数据。

结尾附上demo地址

ViewPager02
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息