MVCHelper主要用于下拉刷新加载,失败,加载,空数据,成功的界面切换。
MVCHelper +(IDataSource或ITask)+ IDataAdapter + 下拉刷新控件 + 布局切换(ILoadViewFactory,ILoadView,ILoadMoreView)
TaskHelper主要用于没有布局切换和刷新控件的MVC架构,可以执行多个任务通过回调ICallback更新UI
TaskHelper+(ITask或IDataSource)+ ICallBack
Download sample Apk
历史版本和更新信息
https://github.com/LuckyJayce/MVCHelper/releases
Gradle导入
1.必须导入:
//MVCHelper核心类库
compile 'com.shizhefei:MVCHelper-Library:1.1.0'
//里面有使用recyclerview,所以需要导入recyclerview
compile 'com.android.support:recyclerview-v7:24.0.0'
2.可选:
<1> 使用 https://github.com/LuckyJayce/CoolRefreshView 的刷新控件导入
支持任意View的刷新 ,支持自定义Header,支持NestedScrollingParent,NestedScrollingChild的事件分发,嵌套ViewPager不会有事件冲突
//里面包含一个MVCCoolHelper 是适配这个控件的 MVCHelper
compile 'com.shizhefei:MVCHelper-CoolRefresh:1.1.0'
compile 'com.shizhefei:CoolRefreshView:1.0.1'
compile 'com.android.support:support-v4:24.0.0'
<2> 使用 https://github.com/chrisbanes/Android-PullToRefresh 的刷新控件导入
//里面包含一个MVCPullrefshHelper 是适配这个控件的 MVCHelper
compile 'com.shizhefei:MVCHelper-Pullrefresh:1.1.0'
//由于没有找到gradle排至,我自己把它上传到jcenter上
compile 'com.shizhefei:pulltorefresh:1.0.1'
<3> 使用 https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh 的刷新控件导入
//里面包含一个MVCUltraHelper 是适配这个控件的 MVCHelper
compile 'com.shizhefei:MVCHelper-UltraRefresh:1.1.0'
//这里6月29号目前最新的,要实时关注新版本去秋大的网站上去看
compile 'in.srain.cube:ultra-ptr:1.0.11'
<4> 使用android v4的SwipeRefreshLayout的作为刷新控件导入
//里面包含一个MVCSwipeRefreshHelper 是适配这个控件的 MVCHelper
compile 'com.shizhefei:MVCHelper-SwipeRefresh:1.1.0'
//v4包应该都有导入吧,v7包里面包含v4包
compile 'com.android.support:support-v4:24.0.0'
<5> 测试用例,可以方便的查看MVCHelper,Task的运行情况和返回数据,还提供了修改接口字段,用于接口测试很方便哦
//MVCHelper的测试用例,继承ABSTestCaseFragment实现List<TestCaseData> getTestCaseDatas()方法
compile 'com.shizhefei:MVCHelper-TestCase:1.1.0'
//里面用到了gson
compile 'com.google.code.gson:gson:2.2.4'
<6> MVCHelper-OkHttp 对OKHttp的简单封装
//MVCHelper的 OKHttp的简单封装
compile 'com.shizhefei:MVCHelper-OkHttp:1.1.0'
//里面用到了okhttp3
compile 'com.squareup.okhttp3:okhttp:3.4.0'
compile 'com.squareup.okio:okio:1.9.0'
结构
这里V和M是没有联系的,或许可以理解为是MVP结构吧.
类图:
https://raw.githubusercontent.com/LuckyJayce/MVCHelper/master/raw/MVCHelper%E7%B1%BB%E5%9B%BE.png
效果图:
一、 MVCHelper
MVCHelper. 实现下拉刷新,滚动底部自动加载更多,分页加载,自动切换显示网络失败布局,暂无数据布局,,真正的MVC架构.
1.Model (IDataSource)数据源,加载数据
同步请求实现IDataSource,异步请求(okhttp,volley,rxjava+retrofit)实现IAsyncDataSource
<1>同步请求(直接返回结果)
//数据源
public interface IDataSource<DATA> {
// 获取刷新的数据
public DATA refresh() throws Exception;
// 获取加载更多的数据
public DATA loadMore() throws Exception;
// 是否还可以继续加载更多
public boolean hasMore();
}
例如:分页加载书籍列表数据
public class BooksDataSource implements IDataSource<List<Book>> {
private int page = 1;
private int maxPage = 5;
@Override
public List<Book> refresh() throws Exception {
return loadBooks(1);
}
@Override
public List<Book> loadMore() throws Exception {
return loadBooks(page + 1);
}
private List<Book> loadBooks(int page) {
List<Book> books = new ArrayList<Book>();
for (int i = 0; i < 20; i++) {
books.add(new Book("page" + page + " Java编程思想 " + i, 108.00d));
}
this.page = page;
return books;
}
@Override
public boolean hasMore() {
return page < maxPage;
}
}
<2>异步请求(就是请求等待回调函数返回结果)
/**
* 异步数据源(比如Volley,OkHttp等异步请求使用)
* @param <DATA>
*/
public interface IAsyncDataSource<DATA> {
/**
* 获取刷新的数据
*
* @param sender 用于请求结束时发送数据给MVCHelper,MVCHelper再通知IDataAdapter调用notifyDataChenge方法
* @return 用于提供外部取消请求的处理.比如执行refresh还没请求结束又执行refresh,就会通过上次的RequestHandle取消上次的请求.MVCHelper的destroy也会用这个取消请求
* @throws Exception
*/
RequestHandle refresh(ResponseSender<DATA> sender) throws Exception;
/**
* 获取加载更多的数据
*
* @param sender 用于请求结束时发送数据给MVCHelper,MVCHelper再通知IDataAdapter调用notifyDataChenge方法
* @return 用于提供外部取消请求的处理.比如执行refresh还没请求结束又执行refresh,就会通过上次的RequestHandle取消上次的请求.MVCHelper的destroy也会用这个取消请求
* @throws Exception
*/
RequestHandle loadMore(ResponseSender<DATA> sender) throws Exception;
/**
* 是否还可以继续加载更多
*
* @return
*/
boolean hasMore();
}
例如:OkHttp请求
public class BooksOkHttpNormal_DataSource implements IAsyncDataSource<List<Book>> {
private int mPage;
private int mMaxPage = 5;
public BooksOkHttpNormal_DataSource() {
super();
}
@Override
public RequestHandle refresh(ResponseSender<List<Book>> sender) throws Exception {
return loadBooks(sender, 1);
}
@Override
public RequestHandle loadMore(ResponseSender<List<Book>> sender) throws Exception {
return loadBooks(sender, mPage + 1);
}
@Override
public boolean hasMore() {
return mPage < mMaxPage;
}
private RequestHandle loadBooks(final ResponseSender<List<Book>> sender, final int page) throws Exception {
Request request = new Request.Builder().url("https://www.baidu.com").get().build();
Call call = OkHttpUtils.client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//send 要放在最后一句(请求结束)
sender.sendError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final List<Book> books = new ArrayList<Book>();
for (int i = 0; i < 15; i++) {
books.add(new Book("page" + page + " Java编程思想 " + i, 108.00d));
}
mPage = page;
//send 要放在最后一句(请求结束)
sender.sendData(books);
}
});
return new OKHttpRequestHandle(call);
}
}
public class OKHttpRequestHandle implements RequestHandle {
private final Call call;
public OKHttpRequestHandle(Call call) {
super();
this.call = call;
}
@Override
public void cancle() {
call.cancel();
}
@Override
public boolean isRunning() {
return false;
}
}
例如:使用 MVCHelper-OkHttp
public class BooksOkHttp_AsyncDataSource implements IAsyncDataSource<List<Book>> {
private int mPage;
private int mMaxPage = 5;
@Override
public RequestHandle refresh(ResponseSender<List<Book>> sender) throws Exception {
return loadBooks(sender, 1);
}
@Override
public RequestHandle loadMore(ResponseSender<List<Book>> sender) throws Exception {
return loadBooks(sender, mPage + 1);
}
@Override
public boolean hasMore() {
return mPage < mMaxPage;
}
private RequestHandle loadBooks(final ResponseSender<List<Book>> sender, final int page) throws Exception {
GetMethod method = new GetMethod("https://www.baidu.com");
method.addHeader("a", "aaaaa");
method.addParam("api_key", "75ee6c644cad38dc8e53d3598c8e6b6c");
//method 里面已经封装了sender.sendData 和 sendError的方法,只要关心ResponseParser解析Response返回数据就好
method.executeAsync(sender, new ResponseParser<List<Book>>() {
@Override
public List<Book> parse(Response response) throws Exception {
List<Book> books = new ArrayList<Book>();
for (int i = 0; i < 15; i++) {
books.add(new Book("page" + page + " Java编程思想 " + i, 108.00d));
}
mPage = page;
return books;
}
});
return method;
}
}
**详细写法请看https://github.com/LuckyJayce/MVCHelper/tree/master/app/src/main/java/com/shizhefei/test/models/datasource
里面有
例子:volley
例子:okhttp
例子:rxjava+retrofit
2.View(IDataAdapter) 视图,显示数据
这里不是指Android的view,而是显示数据的概念和显示逻辑
public interface IDataAdapter<DATA> {
public abstract void notifyDataChanged(DATA data, boolean isRefresh);
public abstract DATA getData();
public boolean isEmpty();
}
例如:分页显示书籍列表数据
public class BooksAdapter extends BaseAdapter implements IDataAdapter<List<Book>> {
private List<Book> books = new ArrayList<Book>();
private LayoutInflater inflater;
public BooksAdapter(Context context) {
super();
inflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_book, parent, false);
}
TextView textView = (TextView) convertView;
textView.setText(books.get(position).getName());
return convertView;
}
@Override
public void notifyDataChanged(List<Book> data, boolean isRefresh) {
if (isRefresh) {
books.clear();
}
books.addAll(data);
notifyDataSetChanged();
}
@Override
public int getCount() {
return books.size();
}
@Override
public List<Book> getData() {
return books;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
3.Controller (Activity,Fragment,MVCHelper)控制器
控制器负责调用读取数据,调用显示数据,处理用户交互
Activity负责调度,代码如下
public class MainActivity extends Activity {
private MVCHelper<List<Book>> mvcHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置LoadView的factory,用于创建用户自定义的加载失败,加载中,加载更多等布局
// MVCHelper.setLoadViewFractory(new LoadViewFractory());
PullToRefreshListView refreshListView = (PullToRefreshListView) findViewById(R.id.pullToRefreshListView);
mvcHelper = new MVCPullrefshHelper<List<Book>>(refreshListView);
// 设置数据源
mvcHelper.setDataSource(new BooksDataSource());
// 设置适配器
mvcHelper.setAdapter(new BooksAdapter(this));
// 加载数据
mvcHelper.refresh();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 释放资源
mvcHelper.destory();
}
}
只要写了上述几行代码,恭喜你,你已经实现了分页加载显示书籍列表,实现下拉刷新,滚动底部自动加载更多,在网络请求失败的时候自动显示网络失败,没有数据时显示无数据布局,加载成功时显示书籍列表
4.ILoadViewFractory 自定义 失败布局,无数据布局,加载中布局
实现ILoadViewFractory
MVCHelper.setLoadViewFractory(new LoadViewFractory());
就这样,就会显示你自定义的布局
5.你可以自由的切换刷新类库
1.用CoolRefreshView 作为刷新框架(MVCCoolHelper)
地址:https://github.com/LuckyJayce/CoolRefreshView
CoolRefreshView coolRefreshView = (CoolRefreshView) findViewById(R.id.coolRefreshView);
MVCHelper<List<Book>> mvcHelper = new MVCCoolHelper<List<Book>>(coolRefreshView);
// 设置数据源
mvcHelper.setDataSource(new BooksDataSource());
// 设置适配器
mvcHelper.setAdapter(new BooksAdapter(this));
// 加载数据
mvcHelper.refresh();
2.用android-support-v4.jar 的SwipeRefreshLayout作为刷新框架(MVCSwipeRefreshHelper)
SwipeRefreshLayout swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
MVCHelper<List<Book>> mvcHelper = new MVCSwipeRefreshHelper<List<Book>>(swipeRefreshLayout);
// 设置数据源
mvcHelper.setDataSource(new BooksDataSource());
// 设置适配器
mvcHelper.setAdapter(new BooksAdapter(this));
// 加载数据
mvcHelper.refresh();
3.用Android-PullToRefresh-Library作为刷新框架(MVCPullrefshHelper)
地址:https://github.com/chrisbanes/Android-PullToRefresh
PullToRefreshListView refreshListView = (PullToRefreshListView) findViewById(R.id.pullToRefreshListView);
MVCHelper<List<Book>> mvcHelper = new MVCPullrefshHelper<List<Book>>(refreshListView);
// 设置数据源
mvcHelper.setDataSource(new BooksDataSource());
// 设置适配器
mvcHelper.setAdapter(new BooksAdapter(this));
// 加载数据
mvcHelper.refresh();
4.用android-Ultra-Pull-To-Refresh-library作为刷新框架(MVCUltraHelper)
地址:https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh
PtrClassicFrameLayout mPtrFrameLayout = (PtrClassicFrameLayout) findViewById(R.id.rotate_header_list_view_frame);
MVCHelper<List<Book>> mvcHelper = new MVCUltraHelper<List<Book>>(mPtrFrameLayout);
// 设置数据源
mvcHelper.setDataSource(new BooksDataSource());
// 设置适配器
mvcHelper.setAdapter(new BooksAdapter(this));
// 加载数据
mvcHelper.refresh();
5.不使用刷新框架(MVCNormalHelper)
View contentLayout = findViewById(R.id.content_layout);
MVCHelper<Book> mvcHelper= new MVCNormalHelper<Book>(contentLayout);
// 设置数据源
mvcHelper.setDataSource(new BookDetailDataSource());
// 设置适配器
mvcHelper.setAdapter(dataAdapter);
// 加载数据
mvcHelper.refresh();
6.如果使用其他刷新框架的话可以继承MVCHelper自定义一个
6.任何View的MVC
可以任意的View作为刷新的内容,并且提供相同的MVC架构操作
/***
* 测试下拉组件的非列表界面
*
* @author LuckyJayce
*
*/
public class BooDetailActivity extends Activity {
private MVCHelper<Book> listViewHelper;
private TextView authorTextView;
private TextView contentTextView;
private TextView descriptionTextView;
private TextView nameTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bookdetail);
nameTextView = (TextView) findViewById(R.id.name_textView);
authorTextView = (TextView) findViewById(R.id.author_textView);
descriptionTextView = (TextView) findViewById(R.id.description_textView);
contentTextView = (TextView) findViewById(R.id.content_textView);
PtrClassicFrameLayout contentLayout = (PtrClassicFrameLayout) findViewById(R.id.rotate_header_list_view_frame);
listViewHelper = new MVCUltraHelper<Book>(contentLayout);
// 设置数据源
listViewHelper.setDataSource(new BookDetailDataSource());
// 设置适配器
listViewHelper.setAdapter(dataAdapter);
// 加载数据
listViewHelper.refresh();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 释放资源
listViewHelper.destory();
}
private IDataAdapter<Book> dataAdapter = new IDataAdapter<Book>() {
private Book data;
@Override
public void notifyDataChanged(Book data, boolean isRefresh) {
this.data = data;
authorTextView.setText(data.getAuthor());
contentTextView.setText(data.getContent());
descriptionTextView.setText(data.getDescription());
nameTextView.setText(data.getName());
}
@Override
public boolean isEmpty() {
return data == null;
}
@Override
public Book getData() {
return data;
}
};
public void onClickBack(View view) {
finish();
}
}
7.不再局限于返回值的个数
原先
public class MovieDetailDataSource implements IDataSource<Movie>{
}
使用Data1的可以传一个泛型返回值
使用Data2的可以传两个泛型返回值
使用Data3的可以传三个泛型参数
public class MovieDetailDataSource implements IDataSource<Data3<Movie, List<Discuss>, List<Movie>>>{
}
二、 TaskHelper
主要用于执行多个任务,通过回调ICallback更新UI
1.Model (ITask, IAsyncTask)
同步请求实现Task,异步请求(okhttp,volley)实现IAsyncTask
/**
* @param <DATA>
* 数据类型
*/
public interface Task<DATA> {
/**
* 执行后台任务
*
* @param progressSender
* 进度更新发送者
* @return
* @throws Exception
*/
public DATA execute(ProgressSender progressSender) throws Exception;
/**
* cancel 和 execute 有可能不在同一个线程,cancle可能在UI线程被调用
*/
public void cancel();
}
public interface IAsyncTask<DATA> extends ISuperTask<DATA> {
/**
* @param sender 用于请求结束时发送数据给TaskHelper,MVCHelper,然后在通知CallBack的Post回调方法
* @return 用于提供外部取消请求的处理
* @throws Exception
*/
RequestHandle execute(ResponseSender<DATA> sender) throws Exception;
}
例如登陆
public class LoginTask implements Task<User> {
private String name;
private String password;
public LoginTask(String name, String password) {
super();
this.name = name;
this.password = password;
}
@Override
public User execute(ProgressSender progressSender) throws Exception {
if (name.equals("aaa") && password.equals("111")) {
return new User("1", "aaa", 23, "中国人");
} else {
throw new BizException("用户名或者密码不正确");
}
}
@Override
public void cancle() {
}
}
-
Android 仿饿了么点餐页面源码
Android 仿饿了么点餐页面源码 仿饿了么点餐页面 上滑进入详情 分类和商品级联滑动定位 添加购物车动画 购物车弹窗
-
Android后台模拟点击探索源码
Android后台模拟点击探索源码 工作中我们需要自制一套工具,其中遇到需要模拟点击事件的需求,类似按键精灵的功能,支持后台持续运行,满足触发条件时完成点击。 经过一番探索,一共整理出两种不同的方案:AccessibilityService 和 adb shell命令,读者可自
-
android证件拍照及裁剪源码
android证件拍照及裁剪源码 证件相机-证件拍照及裁剪,类似金融公司app拍照身份证正方面,实现了身份证正反面、营业执照横版、竖版的拍摄和裁剪功能
-
一个MVP架构的Android快速开发框架
一个MVP架构的Android快速开发框架 Android快速开发框架,MVP架构,丰富的功能、简单的实现、详细的注释、规范的风格。OKHttp、Glide图片加载、ZXing二维码、沉浸状态栏、下载安装、自动缓存以及各种Base、Demo、UI、Util直接用。全新的手势,侧滑返回、全局
-
Android快速实现新手引导层的库
NewbieGuide Android 快速实现新手引导层的库 这是一款可以通过简洁链式调用,一行代码实现引导层的显示,自动判断首次显示,当然也可以通过参数配置来满足不同的显示逻辑和需求。 通过自定义layout.xml实现文本及image的添加,非常方便位置的调整,避免代码
-
yuanma
-
asp技术
-
PHP源码
-
商城小程序源码下载
-
免费代码
-
公司网站模板
-
论坛源码
-
导航菜单
-
php代码
-
学校网站模板
-
源码大全
-
企业网站管理
-
网站代码
-
蜘蛛bt
-
asp 源代码
-
企业网站程序
-
导航网站源码
-
模版
-
代码网
-
oa系统下载
-
asp cms
-
php问答系统下载
-
多多淘宝客
-
个人主页源码
-
网站后台管理模板
-
php教程下载
-
网站源码免费下载
-
门户网站源码
-
免费论坛
-
网站模版下载
-
电脑报电子版
-
手机源码
-
网页设计模板
-
网站首页模板
-
外贸网站源码
-
帝国模板
-
后台管理
-
整站模板
-
企业网页设计模板
-
游戏源码
-
商城系统源码
-
素材解析平台
-
商城源码
-
免费个人网站模板
-
苹果cms10模板
-
网页源代码
-
源代码 下载
-
站长下载
-
免费源码下载
-
web源码
-
Android 仿饿了么点餐页面源码
Android 仿饿了么点餐页面源码 仿饿了么点餐页面 上滑进入详情 分类和商品级联滑动定位 添加购物车动画 购物车弹窗
-
Android后台模拟点击探索源码
Android后台模拟点击探索源码 工作中我们需要自制一套工具,其中遇到需要模拟点击事件的需求,类似按键精灵的功能,支持后台持续运行,满足触发条件时完成点击。 经过一番探索,一共整理出两种不同的方案:AccessibilityService 和 adb shell命令,读者可自
-
android证件拍照及裁剪源码
android证件拍照及裁剪源码 证件相机-证件拍照及裁剪,类似金融公司app拍照身份证正方面,实现了身份证正反面、营业执照横版、竖版的拍摄和裁剪功能
-
一个MVP架构的Android快速开发框架
一个MVP架构的Android快速开发框架 Android快速开发框架,MVP架构,丰富的功能、简单的实现、详细的注释、规范的风格。OKHttp、Glide图片加载、ZXing二维码、沉浸状态栏、下载安装、自动缓存以及各种Base、Demo、UI、Util直接用。全新的手势,侧滑返回、全局
-
Android快速实现新手引导层的库
NewbieGuide Android 快速实现新手引导层的库 这是一款可以通过简洁链式调用,一行代码实现引导层的显示,自动判断首次显示,当然也可以通过参数配置来满足不同的显示逻辑和需求。 通过自定义layout.xml实现文本及image的添加,非常方便位置的调整,避免代码
- yuanma
- asp技术
- PHP源码
- 商城小程序源码下载
- 免费代码
- 公司网站模板
- 论坛源码
- 导航菜单
- php代码
- 学校网站模板
- 源码大全
- 企业网站管理
- 网站代码
- 蜘蛛bt
- asp 源代码
- 企业网站程序
- 导航网站源码
- 模版
- 代码网
- oa系统下载
- asp cms
- php问答系统下载
- 多多淘宝客
- 个人主页源码
- 网站后台管理模板
- php教程下载
- 网站源码免费下载
- 门户网站源码
- 免费论坛
- 网站模版下载
- 电脑报电子版
- 手机源码
- 网页设计模板
- 网站首页模板
- 外贸网站源码
- 帝国模板
- 后台管理
- 整站模板
- 企业网页设计模板
- 游戏源码
- 商城系统源码
- 素材解析平台
- 商城源码
- 免费个人网站模板
- 苹果cms10模板
- 网页源代码
- 源代码 下载
- 站长下载
- 免费源码下载
- web源码