Fragment懒加载

转载请注明出处:https://blog.csdn.net/mr_leixiansheng/article/details/79915818


  

普通加载,跳转第二页时已经被预加载好了,所以没有刷新动画


懒加载,跳转第二页时才启动加载,所以有刷新动画


内容: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







阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Mr_Leixiansheng/article/details/79915818
个人分类: 安卓进阶
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭