前言
自己写的例子,很多不足。但是方便自己思路
LazyFragMent
/**
* User: Daidingkang(ddk19941017@Gmail.com)
* Date: 2017-11-01
* Time: 15:45
* FIXME
* 懒加载 - LazyFragment
* 防止频繁的销毁视图,setOffscreenPageLimit(2) 或者 重写PagerAdaper的destroyItem方法为空即可
* 取消预加载的原理其实就是用的懒加载,可以fragment的setUserVisibleHint实现,
* 如下
*
* 值得注意的是,为什么我没有去考虑View是否已经创建完毕(是否已经构建视图),就去执行LazyLoad的操作
* 也就是说界面还是会被ViewPager预加载!!!(所以得保持他不重复;1:重写PagerAdaper的destroyItem 2:View不为空的判断)
* 因为父类用的是ButterKnife,且调用时机是在创建完之后。所以使用控件不会空指针
* 这种写法看起来很简单,但是并不推荐用哦
*/
public abstract class LazyFragment<M extends BaseContract.IBaseMoudel, V extends BaseContract.IBaseView, P extends BasePresenter<M, V>> extends BaseFragment<M, V, P> {
/**
* Fragment当前状态是否可见
*/
protected boolean isVisible;
// 判断是否已经加载
private boolean mLoaded = false;
// 检测声明周期中,是否已经构建视图
private boolean onActivityCreated = false;
//setUserVisibleHint adapter中的每个fragment切换的时候都会被调用,如果是切换到当前页,那么isVisibleToUser==true,否则为false
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
isVisible = true;
if (onActivityCreated)
onVisible();
} else {
isVisible = false;
onInvisible();
}
}
/**
* 在activity完成后才调用它们
* @param savedInstanceState
*/
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
onActivityCreated = true;
if (isVisible)
realLoad();
}
/**
* 可见
*/
protected void onVisible() {
realLoad();
}
/**
* 控制只允许加载一次
*/
private void realLoad() {
if (mLoaded) {
onLazyLoad();
return;
}
mLoaded = true;
onFristLoad();
}
/**
* 可见时加载,并且在页面销毁之前,只会加载一次。
* 适用于加载完成后不需要频繁刷新界面;
* 使用场景:初始化,首页界面,个人界面
*/
protected abstract void onFristLoad();
/**
* 不可见
*/
protected void onInvisible() {
}
/**
* 延迟加载(懒加载),可见才加载,并且每次可见都会执行此方法,除了第一次(因为第一次会执行onFristLoad)
* 子类必须重写此方法
* 使用场景:每次都需要刷新的页面,例如:购物车界面,订单界面
*/
protected abstract void onLazyLoad();
/**
* 重写此方法,子类需要的时候自己继承
* 使用情况少,不利于界面优化
*/
@Override
protected void init() {
}
}
BaseFragment
/**
* User: Daidingkang(ddk19941017@Gmail.com)
* Date: 2017-10-31
* Time: 14:31
* FIXME
*/
public abstract class BaseFragment<M extends BaseContract.IBaseMoudel, V extends BaseContract.IBaseView, P extends BasePresenter<M, V>> extends Fragment {
public P mPretener;
private View mRootView;
private Unbinder mUnbinder;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getPresenter() != null) {
mPretener = getPresenter();
mPretener.attatchWindow(getMoudel(), (V) this);
}
}
protected abstract M getMoudel();
protected abstract P getPresenter();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (mRootView == null)
mRootView = initView(inflater, container);//划重点,否则懒加载还是会预加载此方法
//绑定到butterknife
mUnbinder = ButterKnife.bind(this, mRootView);
return mRootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
init();
}
protected abstract void init();
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if (mPretener == null) {
mPretener = getPresenter();
mPretener.attatchWindow(getMoudel(), (V) this);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mUnbinder != Unbinder.EMPTY) mUnbinder.unbind();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mPretener != null) mPretener.detachWindow();//释放资源
this.mPretener = null;
this.mRootView = null;
this.mUnbinder = null;
}
/**
* 子类实现需要注意设置 attachToRoot为false
* 否则会抛出StackOverflowError
* 注意此时还没有绑定注解控件
* @param inflater
* @param container
* @return
*/
protected abstract View initView(LayoutInflater inflater, ViewGroup container);
/**
* 此方法是让外部调用使fragment做一些操作的,比如说外部的activity想让fragment对象执行一些方法,
* 建议在有多个需要让外界调用的方法时,统一传bundle,里面存一个what字段,来区分不同的方法,在setData
* 方法中就可以switch做不同的操作,这样就可以用统一的入口方法做不同的事,和message同理
* <p>
* 使用此方法时请注意调用时fragment的生命周期,如果调用此setData方法时onActivityCreated
* 还没执行,setData里调用presenter的方法时,是会报空的,因为dagger注入是在onActivityCreated
* 方法中执行的,如果要做一些初始化操作,可以不必让外部调setData,在内部onActivityCreated中
* 初始化就可以了
*
* @param data
*/
public void setData(Object data) {
}
}