关于基类的那些事
安卓基础开发库,让开发简单点。
DevRing & Demo地址:https://github.com/LJYcoder/DevRing
前言
基类对于开发是很重要的一部分。在基类中一般可以进行以下操作
1.把一些频繁调用的代码封装起来。
2.提供抽象方法给子类实现,从而简化操作、得到更直接的数据。
使用好基类可以减少代码量,方便统一拓展,提高发开效率。
但由于Java单继承的特性,有时别人提供的基类不一定能应用到自己的项目里去,所以下面也会介绍通过LifecycleCallback的方法来实现Activity/Fragment基类的功能(该方式是从这里学习的)。
介绍
下面介绍demo中用到的基类,如Activity基类、Fragment基类、Adapter基类、Presenter基类。
基类的具体实现请根据自己的需求来定制,下面仅供参考。
1. Activity基类
1.1 BaseActivity
public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements IBaseActivity {
@BindColor(R.color.colorPrimary)
int mColor;
@Inject
@Nullable
protected P mPresenter;
protected abstract int getContentLayout();//返回页面布局id
protected abstract void initView(Bundle savedInstanceState);//做视图相关的初始化工作
protected abstract void initData(Bundle savedInstanceState);//做数据相关的初始化工作
protected abstract void initEvent();//做监听事件相关的初始化工作
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getContentLayout() != 0) {
setContentView(getContentLayout());
ButterKnife.bind(this);
}
initBarColor();//初始化状态栏/导航栏颜色,需在设置了布局后再调用
initView(savedInstanceState);
initData(savedInstanceState);
initEvent();
}
private void initBarColor() {
ColorBar.newColorBuilder()
.applyNav(true)
.navColor(mColor).navDepth(0)
.statusColor(mColor)
.statusDepth(0)
.build(this)
.apply();
}
@Override
public boolean isUseEventBus() {
return false;
}
@Override
public boolean isUseFragment() {
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mPresenter != null) {
mPresenter.destroy();
mPresenter = null;
}
}
}
BaseActivity的作用如下:
-
重写onCreate。
这样具体的Activity就不需要重写onCreate()方法,而只需重写getContentLayout()、initView(Bundle savedInstanceState);、initData(Bundle savedInstanceState)、initEvent()并在其中进行相应的操作即可 -
设置状态栏导航栏颜色。
很多时候,我们需要对app顶部的状态栏以及底部的导航栏(含有虚拟按键的那一栏)进行颜色设置从而实现沉浸式效果。对于Andriod4.4、5.0版本,它们设置颜色的方式有区别,所以需要做兼容处理。demo中使用的是UltimateBar开源库,它内部已经做了兼容操作,并提供了几个方法来设置颜色,如不透明的、半透明的、全透明的、隐藏等。 -
销毁Presenter层对View层的引用。
这里涉及MVP开发模式,不了解的可以先点这里。由于Activity经常需要销毁Presenter层对View层的引用,所以移至基类中实现。 -
实现IBaseActivity接口。
实现该接口,以便通过Application.ActivityLifecycleCallbacks完成部分"基类操作",看完1.2你就懂了。
1.2 通过ActivityLifecycleCallbacks实现基类操作
顾名思义--- Activity生命周期回调。
当注册了该回调用,每个Activity进入相关生命周期时都会触发相关回调。
所以我们可以通过Application.registerActivityLifecycleCallbacks(callback)方法注册回调,然后在ActivityLifecycleCallbacks里实现一些基类操作。
不多说,直接上代码。(代码涉及了一些Dagger2,可以点这里了解)
@Singleton
public class ActivityLifeCallback implements Application.ActivityLifecycleCallbacks {
@Inject
SimpleArrayMap<String, IActivityLife> mMapActivityLife;
@Inject
Provider<IActivityLife> mActivityLifeProvider;
@Inject
Lazy<FragmentLifeCallback> mFragmentLifeCallbackProvider;
@Inject
public ActivityLifeCallback() {
}
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
if (activity instanceof IBaseActivity) {
IActivityLife iActivityLife = mMapActivityLife.get(activity.toString());
if (iActivityLife == null) {
iActivityLife = mActivityLifeProvider.get();
mMapActivityLife.put(activity.toString(), iActivityLife);
}
iActivityLife.onCreate(activity, bundle);
}
boolean isUseFragment = activity instanceof IBaseActivity ? ((IBaseActivity) activity).isUseFragment() : true;
if (activity instanceof FragmentActivity && isUseFragment) {
((FragmentActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(mFragmentLifeCallbackProvider.get(), true);
}
}
@Override
public void onActivityStarted(Activity activity) {
IActivityLife iActivityLife = mMapActivityLife.get(activity.toString());
if (iActivityLife != null) {
iActivityLife.onStart();
}
}
@Override
public void onActivityResumed(Activity activity) {
IActivityLife iActivityLife = mMapActivityLife.get(activity.toString());
if (iActivityLife != null) {
iActivityLife.onResume();
}
}
@Override
public void onActivityPaused(Activity activity) {
IActivityLife iActivityLife = mMapActivityLife.get(activity.toString());
if (iActivityLife != null) {
iActivityLife.onPause();
}
}
@Override
public void onActivityStopped(Activity activity) {
IActivityLife iActivityLife = mMapActivityLife.get(activity.toString());
if (iActivityLife != null) {
iActivityLife.onStop();
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
IActivityLife iActivityLife = mMapActivityLife.get(activity.toString());
if (iActivityLife != null) {
iActivityLife.onSaveInstanceState(bundle);
}
}
@Override
public void onActivityDestroyed(Activity activity) {
IActivityLife iActivityLife = mMapActivityLife.get(activity.toString());
if (iActivityLife != null) {
iActivityLife.onDestroy();
}
mMapActivityLife.remove(activity.toString());
}
}
我把各生命周期具体要做的事情放到ActivityLife里执行了,下面贴上ActivityLife的代码:
public class ActivityLife implements IActivityLife {
private Activity mActivity;
private final PublishSubject<ActivityEvent> mLifecycleSubject = PublishSubject.create();
@Override
public void onCreate(Activity activity, Bundle savedInstanceState) {
mActivity = activity;
mLifecycleSubject.onNext(ActivityEvent.CREATE);
DevRing.activityStackManager().pushOneActivity(mActivity);
if (((IBaseActivity) mActivity).isUseEventBus()) {
DevRing.busManager().register(mActivity);
}
}
@Override
public void onStart() {
mLifecycleSubject.onNext(ActivityEvent.START);
}
@Override
public void onResume() {
mLifecycleSubject.onNext(ActivityEvent.RESUME);
}
@Override
public void onPause() {
mLifecycleSubject.onNext(ActivityEvent.PAUSE);
}
@Override
public void onStop() {
mLifecycleSubject.onNext(ActivityEvent.STOP);
}
@Override
public void onSaveInstanceState(Bundle outState) {
}
@Override
public void onDestroy() {
mLifecycleSubject.onNext(ActivityEvent.DESTROY);
DevRing.activityStackManager().popOneActivity(mActivity);
if (((IBaseActivity) mActivity).isUseEventBus()) {
DevRing.busManager().unregister(mActivity);
}
mActivity = null;
}
}
接下来,只要你的Activity实现了IBaseActivity接口,即可通过ActivityLifecycleCallbacks完成以下"基类操作":
-
帮助控制网络请求的生命周期。
通过PublishSubject的操作,在onPause()/onStop()/onDestroy()中发射终止事件,以便控制Retrofit网络请求在页面进入特定状态时终止。 -
EventBus的订阅/解除订阅。
根据isUseEventBus()来决定是否进行EventBus的注册/注销。 -
Activity栈管理的入栈与出栈。
以便后面可通过ActivityStackManager进行页面销毁工作。 -
FragmentLifecycleCallbacks的注册。
根据isUseFragment()来决定是否注册FragmentLifecycleCallbacks。
IBaseActivity接口代码:
public interface IBaseActivity {
/**
* 该Activity是否订阅事件总线
* @return true则自动进行注册/注销操作,false则不注册
*/
boolean isUseEventBus();
/**
* 该Activity是否包含Fragment(是否注册FragmentLifecycleCallbacks)
* @return
* 返回false则不注册FragmentLifecycleCallbacks,也就是说{@link FragmentLifeCallback}中的操作不会进行
*/
boolean isUseFragment();
}
2. Fragment基类
2.1 BaseFragment
public abstract class BaseFragment<P extends BasePresenter> extends Fragment implements IBaseFragment {
protected Activity mActivity;
//根布局视图
private View mContentView;
//视图是否已经初始化完毕
private boolean isViewReady;
//fragment是否处于可见状态
private boolean isFragmentVisible;
//是否已经初始化加载过
protected boolean isLoaded;
//用于butterknife解绑
private Unbinder unbinder;
@Inject
@Nullable
protected P mPresenter;
protected abstract boolean isLazyLoad();//是否使用懒加载 (Fragment可见时才进行初始化操作(以下四个方法))
protected abstract int getContentLayout();//返回页面布局id
protected abstract void initView();//做视图相关的初始化工作
protected abstract void initData();//做数据相关的初始化工作
protected abstract void initEvent();//做监听事件相关的初始化工作
@Override
public void onAttach(Context context) {
super.onAttach(context);
mActivity = (Activity) context;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (mContentView == null) {
try {
mContentView = inflater.inflate(getContentLayout(), container, false);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
Preconditions.checkNotNull(mContentView, "根布局的id非法导致根布局为空,请检查后重试!");
unbinder = ButterKnife.bind(this, mContentView);
}
return mContentView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//视图准备完毕
isViewReady = true;
if (!isLazyLoad() || isFragmentVisible) {
init();
}
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
isFragmentVisible = isVisibleToUser;
//如果视图准备完毕且Fragment处于可见状态,则开始初始化操作
if (isLazyLoad() && isViewReady && isFragmentVisible) {
init();
}
}
public void init() {
if (!isLoaded) {
isLoaded = true;
initView();
initData();
initEvent();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
//ButterKnife解绑
if (unbinder != null) unbinder.unbind();
isViewReady = false;
isLoaded = false;
}
@Override
public void onDestroy() {
super.onDestroy();
if (mPresenter != null) {
mPresenter.destroy();
mPresenter = null;
}
}
@Override
public void onSaveState(Bundle bundleToSave) {
}
@Override
public void onRestoreState(Bundle bundleToRestore) {
}
@Override
public boolean isUseEventBus() {
return false;
}
}
BaseFragment的作用如下:
-
延迟加载(懒加载)。 如果Fragment与ViewPager结合使用的话,当加载当前Fragment时,上一页和下一页的Fragment都会预先进行加载,这样如果加载的内容很多,容易造成卡顿、速度慢。
延迟主要就是通过在setUserVisibleHint和onActivityCreated中做判断来实现的,当视图准备完毕且Fragment处于可见状态时,才开始进行初始化操作。重写isLazyLoad()方法即可决定是否开启懒加载功能。
然后具体的fragment只需重写getContentLayout()、initView()、initData()、initEvent()中进行相应的操作即可。
另外有一点需要注意,如果fragment并不是和Viewpager结合使用,而是通过FragmentManager的Transaction进行add/hide/show的话,那么在显示Fragment的时候,请显式地调用setUserVisibleHint(),如下:
//包含多个Fragment的Activity中的代码
//显示或隐藏Fragment,用于切换Fragment的展示
private void addOrShowFragment(FragmentTransaction transaction, BaseFragment fragment, String tag) {
if (mCurrentFragment == fragment) return;
if (!fragment.isAdded()) {
transaction.hide(mCurrentFragment).add(R.id.fl_movie, fragment, tag).commit();
} else {
transaction.hide(mCurrentFragment).show(fragment).commit();
}
//不与ViewPager嵌套的话,需要显式调用setUserVisibleHint
mCurrentFragment.setUserVisibleHint(false);
mCurrentFragment = fragment;
mCurrentFragment.setUserVisibleHint(true);
}
-
销毁Presenter层对View层的引用。
这里涉及MVP开发模式,不了解的可以先点这里。由于Fragment经常需要销毁Presenter层对View层的引用,所以移至基类中实现。 -
实现IBaseFragment接口。
实现该接口,以便通过FragmentManager.FragmentLifecycleCallbacks完成部分"基类操作",看完2.2你就懂了。
2.2 通过FragmentManager.FragmentLifecycleCallbacks实现
同样顾名思义 --- Fragment生命周期回调。
当注册了该回调用,每个Fragment进入相关生命周期时都会触发相关回调。
所以我们可以通过((FragmentActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(callback, true)方法注册回调,然后在
FragmentLifecycleCallbacks里实现一些基类操作。
不多说,直接上代码。(代码涉及了一些Dagger2,可以点这里了解)
@Singleton
public class FragmentLifeCallback extends FragmentManager.FragmentLifecycleCallbacks {
@Inject
SimpleArrayMap<String, IFragmentLife> mMapFragmentLife;
@Inject
Provider<IFragmentLife> mFragmentLifeProvider;
@Inject
public FragmentLifeCallback() {
}
@Override
public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {
if (f instanceof IBaseFragment) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife == null || !iFragmentLife.isAdded()) {
iFragmentLife = mFragmentLifeProvider.get();
mMapFragmentLife.put(f.toString(), iFragmentLife);
// RingLog.e("onCreate activity:" + activity.toString());
// RingLog.e("onCreate iActivityLife:" + iActivityLife.toString());
}
iFragmentLife.onAttach(f, context);
}
}
@Override
public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onCreate(savedInstanceState);
}
}
@Override
public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onActivityCreate(savedInstanceState);
}
}
@Override
public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onCreateView(v,savedInstanceState);
}
}
@Override
public void onFragmentStarted(FragmentManager fm, Fragment f) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onStart();
}
}
@Override
public void onFragmentResumed(FragmentManager fm, Fragment f) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onResume();
}
}
@Override
public void onFragmentPaused(FragmentManager fm, Fragment f) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onPause();
}
}
@Override
public void onFragmentStopped(FragmentManager fm, Fragment f) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onStop();
}
}
@Override
public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onSaveInstanceState(outState);
}
}
@Override
public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onDestroyView();
}
}
@Override
public void onFragmentDestroyed(FragmentManager fm, Fragment f) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onDestroy();
}
mMapFragmentLife.remove(f.toString());
}
@Override
public void onFragmentDetached(FragmentManager fm, Fragment f) {
IFragmentLife iFragmentLife = mMapFragmentLife.get(f.toString());
if (iFragmentLife != null) {
iFragmentLife.onDetach();
}
}
}
我把各生命周期具体要做的事情放到FragmentLife里执行了,下面贴上FragmentLife的代码:
public class FragmentLife implements IFragmentLife {
private static final String SAVED_STATE = "saved_state";
private final PublishSubject<FragmentEvent> mLifecycleSubject = PublishSubject.create();
private Fragment mFragment;
private View mContentView;
private Bundle mSavedState;//用于保存/恢复数据
@Override
public void onAttach(Fragment fragment, Context context) {
mFragment = fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
mLifecycleSubject.onNext(FragmentEvent.CREATE);
if (((IBaseFragment) mFragment).isUseEventBus()) {
DevRing.busManager().register(mFragment);
}
}
@Override
public void onCreateView(View view, Bundle savedInstanceState) {
mLifecycleSubject.onNext(FragmentEvent.CREATE_VIEW);
mContentView = view;
}
@Override
public void onActivityCreate(Bundle savedInstanceState) {
restoreStateFromArguments();
}
@Override
public void onStart() {
mLifecycleSubject.onNext(FragmentEvent.START);
}
@Override
public void onResume() {
mLifecycleSubject.onNext(FragmentEvent.RESUME);
}
@Override
public void onPause() {
mLifecycleSubject.onNext(FragmentEvent.PAUSE);
}
@Override
public void onStop() {
mLifecycleSubject.onNext(FragmentEvent.STOP);
}
@Override
public void onSaveInstanceState(Bundle outState) {
saveStateToArguments();
}
@Override
public void onDestroyView() {
mLifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW);
if (mContentView != null) {
ViewGroup parent = (ViewGroup) mContentView.getParent();
if (parent != null) {
parent.removeView(mContentView);
}
}
saveStateToArguments();
}
@Override
public void onDestroy() {
mLifecycleSubject.onNext(FragmentEvent.DESTROY);
if (((IBaseFragment) mFragment).isUseEventBus()) {
DevRing.busManager().unregister(mFragment);
}
mContentView = null;
mFragment = null;
}
@Override
public void onDetach() {
mLifecycleSubject.onNext(FragmentEvent.DETACH);
}
@Override
public boolean isAdded() {
return mFragment != null && mFragment.isAdded();
}
private void saveStateToArguments() {
if (mFragment.getView() != null) {
Bundle state = new Bundle();
((IBaseFragment) mFragment).onSaveState(state);
mSavedState = state;
}
if (mSavedState != null) {
Bundle b = mFragment.getArguments();
if (b != null) {
b.putBundle(SAVED_STATE, mSavedState);
}
}
}
private void restoreStateFromArguments() {
Bundle b = mFragment.getArguments();
if (b != null) {
mSavedState = b.getBundle(SAVED_STATE);
if (mSavedState != null) {
((IBaseFragment) mFragment).onRestoreState(mSavedState);
}
}
}
}
接下来,只要你的Fragment实现了IBaseFragment接口(如果你的Activity实现了IBaseActivity,那还要确保isUseFragment()方法返回true),即可通过FragmentLifecycleCallbacks实现以下“基类操作”:
-
帮助控制网络请求的生命周期。
通过PublishSubject的操作,在onPause()/onStop()/onDestroy()中发射终止事件,以便控制Retrofit网络请求在页面进入特定状态时终止。 -
EventBus的订阅/解除订阅。
根据isUseEventBus()来决定是否进行EventBus的注册/注销。 -
数据的保存与恢复
fragment在保存和恢复数据方面,要比Activity复杂些,具体可以看这篇文章http://blog.csdn.net/donglynn/article/details/47065999 。
具体Fragment通过实现onSaveState(Bundle bundleToSave)进行数据保存以及onRestoreState(Bundle bundleToRestore);进行数据恢复即可。
IBaseFragment接口代码:
public interface IBaseFragment {
/**
* 需要保存数据时,将数据写进bundleToSave
*/
void onSaveState(Bundle bundleToSave);
/**
* 从bundleToRestore中获取你保存金曲的数据
*/
void onRestoreState(Bundle bundleToRestore);
/**
* 该Fragment是否订阅事件总线
* @return true则自动进行注册/注销操作,false则不注册
*/
boolean isUseEventBus();
}
3. Adapter基类
3.1 RecyclerBaseAdapter
public abstract class RecyclerBaseAdapter<T> extends RecyclerView.Adapter<ViewHolder> implements IRecyclerAdapter<T> {
private static final String TAG = RecyclerBaseAdapter.class.getSimpleName();
private List<T> mDataList;
private Context mContext;
protected RecyclerBaseAdapter(@NonNull Context context, @NonNull List<T> mDataList) {
if (context == null) {
throw new NullPointerException("context is not allow null!");
}
this.mDataList = mDataList;
this.mContext = context;
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final int p = holder.getLayoutPosition();
bindDataForView(holder, (mDataList != null && !mDataList.isEmpty()) ? (mDataList.size() > p ? mDataList.get(p) : null) : null, p);
}
@Override
public int getItemCount() {
return mDataList != null ? mDataList.size() : 0;
}
protected abstract void bindDataForView(ViewHolder holder, T t, int position);
@Override
public Context getContext() {
return mContext;
}
@Override
public T getItem(@IntRange(from = 0) int position) {
if (position <= -1) {
return null;
}
return !CollectionUtil.isEmpty(mDataList) ? mDataList.get(position) : null;
}
@Override
public List<T> getDataList() {
return mDataList;
}
//从某个位置开始,插入一组数据
@Override
public void insertItems(@NonNull List<T> list, @IntRange(from = 0) int startIndex) {
if (mDataList == null) {
return;
}
if (list == null || list.isEmpty()) {
LogUtil.e(TAG, "插入的数据集为空或长度小于等于零, 请检查你的数据集!");
return;
}
if (this.mDataList.containsAll(list)) {
return;
}
notifyItemRangeInserted(startIndex, list.size());
mDataList.addAll(startIndex, list);
notifyItemRangeChanged(startIndex, getItemCount() - startIndex);
}
//从最底下插入一组数据
@Override
public void insertItems(@NonNull List<T> list) {
this.insertItems(list, mDataList.size());
}
//从某个位置开始,插入一个数据
@Override
public void insertItem(@NonNull T t, @IntRange(from = 0) int position) {
if (mDataList == null) {
return;
}
if (t == null) {
LogUtil.e(TAG, "插入的数据为空, 请检查你的数据!");
return;
}
notifyItemInserted(position);
mDataList.add(position, t);
notifyItemRangeChanged(position, getItemCount() - position);
}
//从最底下插入一个数据
@Override
public void insertItem(@NonNull T t) {
this.insertItem(t, mDataList.size());
}
//替换所有数据
@Override
public void replaceData(@NonNull List<T> list) {
if (mDataList == null) {
return;
}
if (list == null || list.isEmpty()) {
LogUtil.e(TAG, "插入的数据集为空或长度小于等于零, 请检查你的数据集!");
return;
}
mDataList = list;
notifyDataSetChanged();
}
//从某个位置开始,更新n个数据
@Override
public void updateItems(@IntRange(from = 0) int positionStart, @IntRange(from = 0) int itemCount) {
notifyItemRangeChanged(positionStart, itemCount);
}
//更新所有数据
@Override
public void updateAll() {
updateItems(0, mDataList.size());
}
//移除某个位置的数据
@Override
public void removeItem(@IntRange(from = 0) int position) {
if (CollectionUtil.isEmpty(mDataList) || position <= -1) {
return;
}
notifyItemRemoved(position);
mDataList.remove(position);
notifyItemRangeChanged(position, getItemCount() - position);
}
//移除所有数据
@Override
public void removeAll() {
if (CollectionUtil.isEmpty(mDataList)) {
return;
}
notifyItemRangeRemoved(0, getItemCount());
mDataList.clear();
notifyItemRangeChanged(0, getItemCount());
}
}
RecyclerBaseAdapter的作用如下:
-
重写onBindViewHolder并提供抽象方法。 由于列表项实体是不确定的,所以用到了泛型。
具体的Adapter继承该基类,通过泛型传入具体的实体类型,然后重写bindDataForView方法,即可更直接地得到实体数据。 - 插入、删除、刷新列表项。 提供相关方法,方便子类快速调用。
3.2 LoadMoreBaseAdapter
如果你的RecyclerView需要有上拉加载更多的功能(添加Footer),那么可以继承LoadMoreBaseAdapter。
它继承RecyclerBaseAdapter,添加了Footer并提供了方法来设置footer的状态。
public abstract class LoadMoreBaseAdapter<T> extends RecyclerBaseAdapter<T> {
// 普通布局
private final int TYPE_ITEM = 1;
// 脚布局
private final int TYPE_FOOTER = 2;
// 当前加载状态,默认为加载完成
private int loadState = 2;
// 正在加载
public static final int LOADING = 1;
// 加载完成
public static final int LOADING_COMPLETE = 2;
// 加载到底了(全部数据加载完毕)
public static final int LOADING_END = 3;
public LoadMoreBaseAdapter(@NonNull Context context, @NonNull List<T> mDataList) {
super(context, mDataList);
}
@Override
public int getItemCount() {
return super.getItemCount() + 1;
}
@Override
public int getItemViewType(int position) {
// 最后一个item设置为FooterView
if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
@Override
protected void bindDataForView(ViewHolder holder, T t, int position) {
if (holder.getItemViewType() == TYPE_FOOTER) {
ProgressBar pbLoading = holder.getView(R.id.pb_loading);
TextView tvLoading = holder.getView(R.id.tv_loading);
LinearLayout llEnd = holder.getView(R.id.ll_end);
switch (loadState) {
case LOADING: // 正在加载
pbLoading.setVisibility(View.VISIBLE);
tvLoading.setVisibility(View.VISIBLE);
llEnd.setVisibility(View.GONE);
break;
case LOADING_COMPLETE: // 加载完成
pbLoading.setVisibility(View.INVISIBLE);
tvLoading.setVisibility(View.INVISIBLE);
llEnd.setVisibility(View.GONE);
break;
case LOADING_END: // 加载到底
pbLoading.setVisibility(View.GONE);
tvLoading.setVisibility(View.GONE);
llEnd.setVisibility(View.VISIBLE);
break;
default:
break;
}
} else {
bindDataForView_(holder, t, position);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//进行判断显示类型,来创建返回不同的View
if (viewType == TYPE_FOOTER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_footer, parent, false);
return new ViewHolder(view);
} else {
return onCreateViewHolder_(parent, viewType);
}
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
// 如果当前是footer的位置,那么该item占据2个单元格,正常情况下占据1个单元格
return getItemViewType(position) == TYPE_FOOTER ? gridManager.getSpanCount() : 1;
}
});
}
}
/**
* 设置上拉加载状态
*
* @param loadState 0.正在加载 1.加载完成 2.加载到底
*/
public void setLoadState(int loadState) {
this.loadState = loadState;
notifyDataSetChanged();
}
protected abstract void bindDataForView_(ViewHolder holder, T t, int position);
protected abstract ViewHolder onCreateViewHolder_(ViewGroup parent, int viewType);
}
当然,完整的上拉加载更多的流程还要配合列表的滚动监听来实现。完整的流程代码可以查看demo,效果图
上拉加载更多
4. Presenter基类
不了解MVP模式的可以先看《安卓开发模式 --- MVP》
public abstract class BasePresenter<V extends IBaseView,M extends IBaseModel>{
protected V mIView;
protected M mIModel;
public BasePresenter(V iView,M iModel) {
mIView = iView;
mIModel = iModel;
}
public BasePresenter(V iView) {
mIView = iView;
}
public BasePresenter() {
}
/**
* 释放引用,防止内存泄露,一般在activity和fragment销毁时调用
*/
public void destroy() {
mIView = null;
}
}
BasePresenter的作用:
- 提供mIView,mIModel方便子类调用。 由于IView,IModel的具体类型不确定,所以使用了泛型,子类通过泛型传入具体的IView、IModel类型。
- 避免内存泄漏。 提供destroy()方法给V层销毁时调用。