FragmentPagerAdapter主要看思想
FragmentPagerAdapter执行流程,暂且说是生命周期吧
可以去ViewPage的populate()
方法中查看
startUpdate()
-> instantiateItem()
->destroyItem()
->setPrimaryItem()
->finishUpdate()
在ViewPage源码addNewItem()
中调用instantiateItem()
方法
接下来我们去看FragmentPageAdapter的源码中instantiateItem()方法做了什么
FragmentTransaction 如果不熟悉Fragment的生命周期和FragmentTransaction的主要方法
public Object instantiateItem(@NonNull ViewGroup container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
final long itemId = getItemId(position);
// Do we already have this fragment?
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
mCurTransaction.attach(fragment);
} else {
fragment = getItem(position);
if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), itemId));
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
// 主要在这里 !!!!!
if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
// Lifecycle.State.STARTED 创建并启动,可见不可操作 就是onStarted()方法
mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
} else {
//旧的
fragment.setUserVisibleHint(false);
}
}
return fragment;
}
知道了这里基本上就可以实现懒加载了
我是这样写的
首先在BaseFragment中
@Override
public void onStart() {
super.onStart();
loadData();
}
protected void loadData() { //网络数据加载
}
这里的话很多人都是在onResume方法中去进行懒加载看个人吧,也可以用之前旧的写法在这里旧不说明了
这里我写一个示例
private boolean isFirstLoad = true; // 是否第一次加载
@Override
public void onResume(){
if(isFirstLoad){
isFirstLoad = false;
loadData();
}
protected void loadData() { //网络数据加载 }
}
然后在子类中
public class NewsFragment extends CoyoteFragment<NewsPresenter, NewsModel> implements NewsContract.View {
private String type;
@BindView(R.id.rlv_news)
RecyclerView mRecyclerView;
private NewsAdapter adapter;
@BindView(R.id.refreshLayout)
RefreshLayout mRefreshLayout; //刷新框架
private int page = 1;
private int pageSize = 20;
private List newsData; //数据源
private boolean isFirstResume = false; //第一次进入
/**
* 获取Fragment实例
*
* @param type 类型
* @return NewsFragment
*/
public static NewsFragment getInstance(String type) {
Bundle bundle = new Bundle();
bundle.putString(VALUE_TYPE, type);
NewsFragment newsFragment = new NewsFragment();
newsFragment.setArguments(bundle);
return newsFragment;
}
@Override
protected int getLayoutId() {
Bundle bundle = getArguments();
if (bundle != null) {
type = bundle.getString(VALUE_TYPE);
} else {
throw new NullPointerException("request type not null");
}
return R.layout.fragment_news;
}
@Override
protected void initData() {
adapter = new NewsAdapter(getContext());
mRecyclerView.setLayoutManager(new LinearLayoutManager(MyApplication.getInstance(), LinearLayoutManager.VERTICAL, false));
//下拉刷新监听
mRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh(@NonNull RefreshLayout refreshLayout) {
mMvpPresenter.getRefreshNews(type, 1, pageSize,
NewsContract.Presenter.RefreshState.REFRESH);
}
});
//上拉加载监听
mRefreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
mMvpPresenter.getRefreshNews(type, ++page, pageSize,
NewsContract.Presenter.RefreshState.LOADMORE);
}
});
}
/**
* 数据渲染
*/
@Override
public void onResume() {
super.onResume();
//已经存在请求回来数据
if(this.newsData != null && !isFirstResume){
if(this.newsData.size() > 0){
Log.i("NewsFragment", "onResume: " + type);
isFirstResume = true;
adapter.setDatas(newsData);
mRecyclerView.setAdapter(adapter);
}
}
}
/**
* 请求网络数据
*/
@Override
protected void loadData() {
mMvpPresenter.getNews(type, page, pageSize);
}
/**
* 拿到数据源并且在onResumed的时候就直接重新刷新数据
* 因为我这里使用的是局部刷新就没调用notifyDataSetChanged()方法
* 具体的话可以去了解 AsyncListDiffer
* @param news
*/
@Override
public void refreshData(List news) {
this.newsData = news;
if(isResumed()){
Log.i("NewsFragment", "refreshData: " + type);
adapter.setDatas(newsData);
mRecyclerView.setAdapter(adapter);
}
}
@Override
public RefreshLayout finishRefresh(int delayed, boolean success, Boolean noMoreData, NewsPresenter.RefreshState refreshState) {
if (refreshState == NewsPresenter.RefreshState.REFRESH) {
return mRefreshLayout.finishRefresh(delayed, success, noMoreData);
} else if (refreshState == NewsPresenter.RefreshState.LOADMORE) {
return mRefreshLayout.finishLoadMore(delayed, success, noMoreData);
}
return null;
}
}
在mainFragment中我是使用TabLayout+Fragment的方式
只需要在初始化Adapter的时候传BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT就ok
adapter = new HomeViewPageAdapter(titles, getChildFragmentManager(), FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);