转载请注明出处:Fragment懒加载_Mr_Leixiansheng的博客-CSDN博客
普通加载,跳转第二页时已经被预加载好了,所以没有刷新动画
懒加载,跳转第二页时才启动加载,所以有刷新动画
内容:Fragment懒加载介绍
与普通Fragment区别
普通Fragment:至少会预加载1个Fragment
懒加载普通Fragment:只会加载显示给用户的普通Fragment
好处:节约流量,提高性能,不进行不必要的加载
原理:只在第一次显示给用户时进行数据的记载,不让其进行预加载,只加载显示页面数据
步骤:
1、继承并重写普通Fragment
2、子类复写BaseLazyFragment中的onFragmentVisibleChange(boolean isVisible)和onFragmentFirstVisible()方法
3、MainActivity中实现ViewPager+Fragment的显示 --> 可参考我之前的文章 ViewPager+FragmentPagerAdapter实现Tab/模仿微信界面(推荐使用)
代码如下:
1、继承并重写普通Fragment
package com.example.leixiansheng.fragmentlazyload.base;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.View;
/**
* Created by Leixiansheng on 2018/4/12.
*
* * Fragment基类,封装了懒加载的实现
* 1、Viewpager + Fragment情况下,fragment的生命周期因Viewpager的缓存机制而失去了具体意义
* 该抽象类自定义新的回调方法,当fragment可见状态改变时会触发的回调方法,和 Fragment 第一次可见时会回调的方法
*
*/
public class BaseLazyFragment extends Fragment {
private static final String TAG = "BaseLazyFragment";
private boolean isFragmentVisible;
private boolean isReuseView;
private boolean isFirstVisible;
private View rootView;
//setUserVisibleHint()在Fragment创建时会先被调用一次,传入isVisibleToUser = false
//如果当前Fragment可见,那么setUserVisibleHint()会再次被调用一次,传入isVisibleToUser = true
//如果Fragment从可见->不可见,那么setUserVisibleHint()也会被调用,传入isVisibleToUser = false
//总结:setUserVisibleHint()除了Fragment的可见状态发生变化时会被回调外,在new Fragment()时也会被回调
//如果我们需要在 Fragment 可见与不可见时干点事,用这个的话就会有多余的回调了,那么就需要重新封装一个
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//setUserVisibleHint()有可能在fragment的生命周期外被调用
if (rootView == null) {
return;
}
if (isFirstVisible && isVisibleToUser) {
onFragmentFirstVisible();
isFirstVisible = false;
}
if (isVisibleToUser) {
onFragmentVisibleChange(true);
isFragmentVisible = true;
return;
}
if (isFragmentVisible) {
isFragmentVisible = false;
onFragmentVisibleChange(false);
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initVariable();
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
//如果setUserVisibleHint()在rootView创建前调用时,那么
//就等到rootView创建完后才回调onFragmentVisibleChange(true)
//保证onFragmentVisibleChange()的回调发生在rootView创建完成之后,以便支持ui操作
if (rootView == null) {
rootView = view;
if (getUserVisibleHint()) {
if (isFirstVisible) {
onFragmentFirstVisible();
isFirstVisible = false;
}
onFragmentVisibleChange(true);
isFragmentVisible = true;
}
}
super.onViewCreated(isReuseView ? rootView : view, savedInstanceState);
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
@Override
public void onDestroy() {
super.onDestroy();
initVariable();
}
private void initVariable() {
isFirstVisible = true;
isFragmentVisible = false;
rootView = null;
isReuseView = true;
}
/**
* 设置是否使用 view 的复用,默认开启
* view 的复用是指,ViewPager 在销毁和重建 Fragment 时会不断调用 onCreateView() -> onDestroyView()
* 之间的生命函数,这样可能会出现重复创建 view 的情况,导致界面上显示多个相同的 Fragment
* view 的复用其实就是指保存第一次创建的 view,后面再 onCreateView() 时直接返回第一次创建的 view
*
* @param isReuse
*/
protected void reuseView(boolean isReuse) {
isReuseView = isReuse;
}
/**
* 去除setUserVisibleHint()多余的回调场景,保证只有当fragment可见状态发生变化时才回调
* 回调时机在view创建完后,所以支持ui操作,解决在setUserVisibleHint()里进行ui操作有可能报null异常的问题
*
* 可在该回调方法里进行一些ui显示与隐藏,比如加载框的显示和隐藏
*
* @param isVisible true 不可见 -> 可见
* false 可见 -> 不可见
*/
protected void onFragmentVisibleChange(boolean isVisible) {
}
/**
* 在fragment首次可见时回调,可在这里进行加载数据,保证只在第一次打开Fragment时才会加载数据,
* 这样就可以防止每次进入都重复加载数据
* 该方法会在 onFragmentVisibleChange() 之前调用,所以第一次打开时,可以用一个全局变量表示数据下载状态,
* 然后在该方法内将状态设置为下载状态,接着去执行下载的任务
* 最后在 onFragmentVisibleChange() 里根据数据下载状态来控制下载进度ui控件的显示与隐藏
*/
protected void onFragmentFirstVisible() {
}
protected boolean isFragmentVisible() {
return isFragmentVisible;
}
}
2、子类复写BaseLazyFragment中的onFragmentVisibleChange(boolean isVisible)和onFragmentFirstVisible()方法
package com.example.leixiansheng.fragmentlazyload.fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.example.leixiansheng.fragmentlazyload.R;
import com.example.leixiansheng.fragmentlazyload.base.BaseLazyFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Created by Leixiansheng on 2018/4/12.
*/
public class PageOneLazyFragment extends BaseLazyFragment implements SwipeRefreshLayout.OnRefreshListener{
@BindView(R.id.tv_title)
TextView mTvTitle;
@BindView(R.id.lv_content)
ListView mLvContent;
Unbinder unbinder;
@BindView(R.id.refresh)
SwipeRefreshLayout mRefresh;
private static final String TAG = "PageOneLazyFragment";
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
mRefresh.setRefreshing(false);
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page_one, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
protected void onFragmentFirstVisible() {
Log.i(TAG, "onFragmentFirstVisible");
mRefresh.setRefreshing(true);
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
mHandler.sendEmptyMessage(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
@Override
protected void onFragmentVisibleChange(boolean isVisible) {
Log.i(TAG, "onFragmentVisibleChange isVisible:" + isVisible);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onRefresh() {
// mRefresh.setRefreshing(true);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i(TAG, "onViewCreated");
}
@Override
public void onStop() {
super.onStop();
Log.i(TAG, "onStop");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "onActivityCreated");
}
}
package com.example.leixiansheng.fragmentlazyload.fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.example.leixiansheng.fragmentlazyload.R;
import com.example.leixiansheng.fragmentlazyload.base.BaseLazyFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Created by Leixiansheng on 2018/4/12.
*/
public class PageTwoLazyFragment extends BaseLazyFragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "PageTwoLazyFragment";
@BindView(R.id.tv_title)
TextView mTvTitle;
@BindView(R.id.lv_content)
ListView mLvContent;
@BindView(R.id.refresh)
SwipeRefreshLayout mRefresh;
Unbinder unbinder;
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
mRefresh.setRefreshing(false);
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page_two, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
protected void onFragmentFirstVisible() {
Log.i(TAG, "onFragmentFirstVisible");
mRefresh.setRefreshing(true);
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
mHandler.sendEmptyMessage(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
@Override
protected void onFragmentVisibleChange(boolean isVisible) {
Log.i(TAG, "onFragmentVisibleChange isVisible:" + isVisible);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onRefresh() {
// mRefresh.setRefreshing(true);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i(TAG, "onViewCreated");
}
@Override
public void onStop() {
super.onStop();
Log.i(TAG, "onStop");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "onActivityCreated");
}
}
3、MainActivity中实现ViewPager+Fragment的显示
package com.example.leixiansheng.fragmentlazyload;
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 com.example.leixiansheng.fragmentlazyload.fragment.PageOneFragment;
import com.example.leixiansheng.fragmentlazyload.fragment.PageOneLazyFragment;
import com.example.leixiansheng.fragmentlazyload.fragment.PageTwoFragment;
import com.example.leixiansheng.fragmentlazyload.fragment.PageTwoLazyFragment;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener{
@BindView(R.id.view_pager)
ViewPager mViewPager;
private List<Fragment> mFragmentList;
private FragmentPagerAdapter mAdapter;
private final boolean isLazyLoad = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initView();
mViewPager.addOnPageChangeListener(this);
}
private void initView() {
int mode = getIntent().getIntExtra(GuideActivity.FRAGMENT_MODE, 1);
mFragmentList = new ArrayList<>();
if (mode==GuideActivity.LAZY_MODE_) {
mFragmentList.add(new PageOneLazyFragment());
mFragmentList.add(new PageTwoLazyFragment());
} else {
mFragmentList.add(new PageOneFragment());
mFragmentList.add(new PageTwoFragment());
}
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
};
mViewPager.setAdapter(mAdapter);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
打印Log如下:
懒加载,PageOneFragment和PageTwoFragment 只在第一次进入时加载
先加载 PageOneFragment
04-12 16:06:35.793 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneLazyFragment: onCreate
04-12 16:06:35.794 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoLazyFragment: onCreate
04-12 16:06:35.799 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneLazyFragment: onFragmentFirstVisible
04-12 16:06:35.801 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneLazyFragment: onFragmentVisibleChange isVisible:true
04-12 16:06:35.801 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneLazyFragment: onViewCreated
04-12 16:06:35.801 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneLazyFragment: onActivityCreated
04-12 16:06:35.808 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoLazyFragment: onViewCreated
04-12 16:06:35.808 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoLazyFragment: onActivityCreated
再进入 PageTwoFragment
04-12 16:07:23.669 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneLazyFragment: onFragmentVisibleChange isVisible:false
04-12 16:07:23.670 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoLazyFragment: onFragmentFirstVisible
04-12 16:07:23.673 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoLazyFragment: onFragmentVisibleChange isVisible:true
小结:在onFragmentFirstVisible()中数据加载
再对比下普通的Fragment
package com.example.leixiansheng.fragmentlazyload.fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.example.leixiansheng.fragmentlazyload.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Created by Leixiansheng on 2018/4/12.
*/
public class PageOneFragment extends Fragment {
@BindView(R.id.tv_title)
TextView mTvTitle;
@BindView(R.id.lv_content)
ListView mLvContent;
@BindView(R.id.refresh)
SwipeRefreshLayout mRefresh;
Unbinder unbinder;
private static final String TAG = "PageOneFragment";
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
mRefresh.setRefreshing(false);
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page_one, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i(TAG, "onViewCreated");
}
@Override
public void onStop() {
super.onStop();
Log.i(TAG, "onStop");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "onActivityCreated");
mRefresh.setRefreshing(true);
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
mHandler.sendEmptyMessage(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
package com.example.leixiansheng.fragmentlazyload.fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.example.leixiansheng.fragmentlazyload.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Created by Leixiansheng on 2018/4/12.
*/
public class PageTwoFragment extends Fragment {
@BindView(R.id.tv_title)
TextView mTvTitle;
@BindView(R.id.lv_content)
ListView mLvContent;
@BindView(R.id.refresh)
SwipeRefreshLayout mRefresh;
Unbinder unbinder;
private static final String TAG = "PageTwoFragment";
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
mRefresh.setRefreshing(false);
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page_two, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i(TAG, "onViewCreated");
}
@Override
public void onStop() {
super.onStop();
Log.i(TAG, "onStop");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "onActivityCreated");
mRefresh.setRefreshing(true);
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
mHandler.sendEmptyMessage(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
package com.example.leixiansheng.fragmentlazyload;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by Leixiansheng on 2018/4/12.
*/
public class GuideActivity extends AppCompatActivity {
@BindView(R.id.btn_normal_fragment)
Button mBtnNormalFragment;
@BindView(R.id.btn_lazy_fragment)
Button mBtnLazyFragment;
public static final String FRAGMENT_MODE = "mode";
public static final int NORMAL_MODE = 1;
public static final int LAZY_MODE_ = 2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide);
ButterKnife.bind(this);
final Intent intent = new Intent(this, MainActivity.class);
mBtnNormalFragment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent.putExtra(FRAGMENT_MODE, NORMAL_MODE);
startActivity(intent);
}
});
mBtnLazyFragment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent.putExtra(FRAGMENT_MODE, LAZY_MODE_);
startActivity(intent);
}
});
}
}
打印Log如下:
普通加载,PageOneFragment和PageTwoFragment 同时加载
04-12 16:04:51.978 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneFragment: onCreate
04-12 16:04:51.978 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoFragment: onCreate
04-12 16:04:52.007 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneFragment: onViewCreated
04-12 16:04:52.008 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageOneFragment: onActivityCreated
04-12 16:04:52.018 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoFragment: onViewCreated
04-12 16:04:52.018 20139-20139/com.example.leixiansheng.fragmentlazyload I/PageTwoFragment: onActivityCreated