Collection 总结了项目中的一些基本模块,从而节省了开发人员的时间。
Collection聚合了项目搭建的一些基本模块,节约开发者时间,协助项目的快速搭建,RecyclerView+Adapter+Retrofit+RxJava+MVP+DataManager+基本Base,能够满足一个项目的基本实现。
推荐文章
适配Android x库的Collection-kotlin:https://juejin.im/post/5e59d0eef265da57315b0b0e
Collection-iOS库:https://juejin.im/post/5e423d4ef265da572a0cec9f
简书地址:https://www.jianshu.com/p/0a8c27bc8457
掘金地址:https://juejin.im/post/5ab9987451882555635e5401
1.上传下载增加进度条 2.Fragment增加布局和数据 初始化懒加载 3.网络请求优化(解决内存泄露问题) 4.增加文件断点下载 5.增加MVP注解生成文件(https://github.com/usernameyangyan/MvpAnnotationProject) 6.增加网络请求通过同步上传文件
1.DialogFragment替换AlertDialog 2.SharePreference统一初始化 3.简化Fragment的跳转逻辑 4.DataManager.DataForHttp增加文件下载
1.修复SQLite没有创建表查询异常 2.SQLite增加按条件查询List 3.增加PopupWindow显示位置设置 4.解决SQLit内容为null报错 5.状态栏修改:增加设置状态栏透明+黑色字体
1.去掉Relam数据模块,安装包大小减少 2.对原生SQLite数据库进行封装,使用更加方便 3.对DataManager的使用进行修整 4.增加AutoLineLayout/TagView 5.增加LinkedMultiValueMap 6.增加RxJavaUtils,可进行子/主线程数据处理切换
1.更新Realm数据库依赖。 2.更新RxJava、rxandroid、retrofit、converter-gson、adapter-rxjava2依赖。 3.封装好Fragment之间的交互,项目中可以选择使用一个Activity来作为跟容器,其它实现页面统一使用fragment来实现。 4.collectionLibary中的Config配置类增加json字段过滤、网络请求超时设置、网络请求头设置(全局请求头)。 5.增加自动换行布局。 6.Realm增加按数据字段查询和删除接口。 7.网络请求类型HttpType增加json类型请求参数。 8.网络请求增加个别接口请求头设置。 9.增加适配不同手机像素。
1.增加自定义控件TabLayout。
1.RxJava的依赖更新。 2.修正RecyclerView头部布局不能铺满问题。 3.PopupWindow的使用。 4.DisplayUtils工具类对状态栏的修改。
1.修正Retrofit DEFAULT_POST请求方式指向错误。 2.Retrofit 数据解析兼容没有公用been类,可以指定公用been类和不指定公用been类、或者混合使用。 3.Realm增加数据迁移(数据库字段增加或移除)。 4.增加几种通用的Dialog弹窗,提供方法自定义。 5.提供几种比较常用的Utils工具类
1.增加DataManager用来统一管理数据请求,包括Retrofit的请求、SharePreference以及Realm的数据请求。 2.Retrofit的请求的整合。 3.PullToRefreshRecyclerView的空布局bug修改。
implementation 'com.youngman:collectionlibrary:1.3.9'
Error:Could not find com.android.support:appcompat-v7:27.x.x. 因为library的Support Repository是27.x.x,可能跟项目有所冲突,如果sdk已经装了27还是会出现同样的错误。 解决办法:在项目根build.gradle中加入 maven { url "https://maven.google.com" }
| 属性 | 作用 |
|---|---|
| addHeaderView | 增加头部布局, 暂时只能添加一个头布局 |
| setEmptyView | 设置自定义的加载布局和空布局 |
| setRefreshView | 自定义刷新View |
| setDefaultLoadingMoreNoDataMessage | 设置默认没有数据的内容 |
| setLoadMoreView | 自定义加载更多View |
| setNoMoreDate | 显示没有更多数据 |
| setAutoRefresh | 自动刷新 |
| refreshComplete | 刷新数据完成 |
| loadMoreComplete | 加载更多数据完成 |
| setPullRefreshEnabled | 是否允许刷新 |
| setLoadMoreEnabled | 是否允许加载更多 |
| setRefreshTimeVisible | 显示加载更新时间 |
| isLoading | 是否正在loading数据 |
| isRefreshing | 正在refreshing数据 |
| setRefreshAndLoadMoreListener | 刷新和加载更多回调 |
| destroy | 内存回收 |
recycler_rv.setPullRefreshEnabled(true);
recycler_rv.setLoadMoreEnabled(true);
| 属性 | 作用 |
|---|---|
| STATE_PULL_DOWN | 拉的状态(还没到下拉到固定的高度时) |
| STATE_RELEASE_REFRESH | 下拉到固定高度提示释放刷新的状态 |
| STATE_REFRESHING | 正在刷新状态 |
| STATE_DONE | 刷新完成 |
| 属性 | 作用 |
|---|---|
| STATE_LOADING | 正在加载 |
| STATE_COMPLETE | 加 载完成 |
| STATE_NODATA | 没有数据 |
recycler_rv.setPullRefreshEnabled(true);
recycler_rv.setLoadMoreEnabled(true);
recycler_rv.setRefreshAndLoadMoreListener(this);
recycler_rv.setRefreshView(new DefinitionAnimationRefreshHeaderView(getActivity()));
recycler_rv.setLoadMoreView(new DefinitionAnimationLoadMoreView(getActivity()));
1.在initView()做自定义布局、相关动画的初始化,最后在initView()方法的最后面添加以下代码即可。
mContainer = LayoutInflater.from(context).inflate(R.layout.collection_library_layout_default_arrow_refresh, null);
//把刷新头部的高度初始化为0
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
lp.setMargins(0, 0, 0, 0);
this.setLayoutParams(lp);
this.setPadding(0, 0, 0, 0);
addView(mContainer, new LayoutParams(LayoutParams.MATCH_PARENT, 0));
setGravity(Gravity.BOTTOM);
//测量高度
measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mMeasuredHeight = getMeasuredHeight();
2.setRefreshTimeVisible(boolean show)是用来设置是否显示刷新时间控件,在默认刷新样式中通过mRecyclerView.setRefreshTimeVisible(false)即可隐藏刷新时间,如果在自定义的布局中没有这项这个方法就可以忽略。
3.destroy()是用来关掉改页面时把刷新View的一些动画等释放,防止内存泄漏。
1.在构造函数中设置 onStateChangeListener=this 2.onStateChange的模板样式
@Override
public void onStateChange(int state) {
//下拉时状态相同不做继续保持原有的状态
if (state == mState) return ;
//根据状态进行动画显示
switch (state){
case STATE_PULL_DOWN:
clearAnim();
startAnim();
break;
case STATE_RELEASE_REFRESH:
break;
case STATE_REFRESHING:
clearAnim();
startAnim();
scrollTo(mMeasuredHeight);
break;
case STATE_DONE:
break;
}
mState = state;
}
1.在initView()做自定义布局、相关动画的初始化,最后在initView()方法的最后面添加以下代码即可
mContainer = LayoutInflater.from(context)
.inflate(R.layout.layout_definition_animation_loading_more, null)
addView(mContainer)
gravity = Gravity.CENTER
2.destroy()是用来关掉改页面时把刷新View的一些动画等释放,防止内存泄漏。 3.在setState()进行状态切换后的相关操作逻辑,模板样式
@Override
public void setState(int state) {
if(isDestroy){
return;
}
switch (state){
case STATE_LOADING:
loadMore_Ll.setVisibility(VISIBLE);
noDataTv.setVisibility(INVISIBLE);
animationDrawable= (AnimationDrawable) loadingIv.getDrawable();
animationDrawable.start();
this.setVisibility(VISIBLE);
break;
case STATE_COMPLETE:
if(animationDrawable!=null){
animationDrawable.stop();
}
this.setVisibility(GONE);
break;
case STATE_NODATA:
loadMore_Ll.setVisibility(INVISIBLE);
noDataTv.setVisibility(VISIBLE);
animationDrawable= (AnimationDrawable) loadingIv.getDrawable();
animationDrawable.start();
this.setVisibility(VISIBLE);
break;
}
mState = state;
}
4.注意:在自定义加载更多样式时,如果需要有没有更多加载更多数据提示同样需要在布局中写好,然后在onSatae中根据状态对加载和没有跟多显示提示进行显示隐藏操作。
recycler_rv.setLoadMoreEnabled(true);
recycler_rv.setRefreshAndLoadMoreListener(this);
recycler_rv.setLoadMoreView(DefinitionAnimationLoadMoreView(activity));
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent);
swipeRefreshLayout.setOnRefreshListener(this);
由于PullToRefreshRecyclerView的下拉刷新和下拉加载更多完成时会自动刷新Adapter,而SwipeRefreshLayout刷新完成时需要手动进行notifyDataSetChanged刷新适配器。
View emptyView = LayoutInflater.from(getActivity()).inflate(R.layout.layout_empty,null);
mRecyclerView.setEmptyView(emptyView);
emptyView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int i=0;i {
public DefinitionRecyclerAdapter(Context mContext, List mDatas, PullToRefreshRecyclerView pullToRefreshRecyclerView) {
super(mContext, R.layout.item_pull_refresh, mDatas, pullToRefreshRecyclerView);
}
@Override
protected void convert(BaseViewHolder baseViewHolder, String s) {
baseViewHolder.setText(R.id.title,s);
}
}
public BaseRecyclerViewAdapter(Context mContext, int mLayoutResId, List mDatas, PullToRefreshRecyclerView pullToRefreshRecyclerView) {
this.mContext = mContext;
this.mLayoutResId = mLayoutResId;
this.mDatas = mDatas;
this.mRecyclerView=pullToRefreshRecyclerView;
}
public BaseRecyclerViewAdapter(Context mContext, int mLayoutResId, List mDatas) {
this.mContext = mContext;
this.mLayoutResId = mLayoutResId;
this.mDatas = mDatas;
}
itemClickAdapter.setOnItemLongClickListener(new BaseRecyclerViewAdapter.onItemLongClickListener() {
@Override
public boolean onItemLongClick(View view, int position) {
showToast("进行长按操作");
return true;
}
});
public class MultipleAdapter extends BaseRecyclerViewMultiItemAdapter {
private int mHeight;
public MultipleAdapter(Context mContext, List mDatas) {
super(mContext, mDatas);
mHeight = DisplayUtil.dip2px(mContext, 100);
addItemType(MultiItem.TYPE_TEXT, R.layout.item_main);
addItemType(MultiItem.TYPE_IMG, R.layout.item_img);
addItemType(MultiItem.TYPE_TEXT_IMG, R.layout.item_click);
}
@Override
protected void convert(BaseViewHolder baseViewHolder, MultiItem multiItem) {
switch (baseViewHolder.getItemViewType()) {
case MultiItem.TYPE_TEXT:
baseViewHolder.getView(R.id.card_view).getLayoutParams().height = mHeight;
baseViewHolder.setText(R.id.title, multiItem.getTitle());
break;
case MultiItem.TYPE_IMG:
baseViewHolder.setImageResource(R.id.ivImg, multiItem.getRes());
break;
case MultiItem.TYPE_TEXT_IMG:
baseViewHolder.setImageResource(R.id.ivImg, multiItem.getRes());
baseViewHolder.setText(R.id.titleTv, multiItem.getTitle());
break;
}
}
ItemTouchHelper.Callback callback=new BaseRecycleItemTouchHelper(dragAndDeleteAdapter);
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
@Override
public void onMoveComplete() {
ToastUtils.showToast(this, "移动操作完成");
}
@Override
public void onDeleteComplete() {
ToastUtils.showToast(this, "删除操作完成");
}
| 属性 | 作用 |
|---|---|
| DEBUG | 是否为BuildConfig.DEBUG,日志输出需要 |
| CONTEXT | 设置Context,必填项 |
| URL_DOMAIN | 网络请求的域名,需要以“/”结尾 |
| URL_CACHE | 网络缓存地址,需要设置缓存才可以成功 |
| MAX_CACHE_SECONDS | 设置OkHttp的缓存机制的最大缓存时间,默认为一天 |
| MAX_MEMORY_SIZE | 缓存最大的内存,默认为10M |
| MClASS | 设置网络请求json通用解析类 |
| EXPOSEPARAM | Json数据某些字段在没有数据是会不返回来,可通过这个属性设置过滤 |
| USER_CONFIG | SharePreference保存的名称 |
| CONNECT_TIMEOUT_SECONDS | 请求接口超时设定 |
| READ_TIMEOUT_SECONDS | 请求接口超时设定 |
| HEADERS | 设置Http全局请求头 |
| SQLITE_DB_NAME | 数据库名称 |
| SQLITE_DB_VERSION | 数据库版本名 |
private void config(){
//基本配置
Config.DEBUG= BuildConfig.DEBUG;
Config.CONTEXT=this;
//Retrofit配置
Config.URL_CACHE=AppConfig.URL_CACHE;
Config.MClASS= Result.class;
Config.URL_DOMAIN="https://api.apiopen.top/";
//SharePreference配置
Config.USER_CONFIG="Collection_User";
Config.SQLITE_DB_VERSION=0;
}
暂无开放 Issues,或尚未同步最近议题。