工厂模式实现并发请求多个接口 (同步后台数据实现离线APP)
Posted 大雄童鞋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工厂模式实现并发请求多个接口 (同步后台数据实现离线APP)相关的知识,希望对你有一定的参考价值。
背景:客户现场没有网络,需要在APP上面录入信息并上传后台服务器
解决方案:
使用APP之前,先(下载)同步后台基本数据,同步完成后,客户直接使用离线版进行数据录入即可。
具体实现:
方案一、登录APP后,后台扔过来一个文件,客户端去下载(不利于更新数据)
方案二、登录APP后,分在线和离线两种模式,在线模式同步后台的基本数据后,离线模式就可以直接使用了。
采用多接口请求,判断上次的更新时间,来实现后台新添加的数据进行本地数据的更新
下面具体介绍方案二:
先看一个工厂模式的反射版本
public abstract class Factory
public abstract <T extends Product> T createProduct(Class<T> clz);
//具体工厂
public class ConcreteFactory extends Factory
@Override
public <T extends Product> T createProduct(Class<T> clz)
Product product = null;
try
product = (Product) Class.forName(clz.getName()).newInstance();
catch (Exception e)
e.printStackTrace();
return (T)product;
//客户端
Factory factory = new ConcreteFactory();
Product product = factory.createProduct(ConcreteProductB.class);
product.method();
根据需求,我们就同步产品、批次、机构作为案例
下面我们就用这种方式来实现并发求多个接口,并监听所有接口数据请求结束并返回
public abstract class SynFactory
public abstract <T extends AbsBaseSyn> T createSyn(Class<T> clz);
//具体工厂
public class SynConcreteFactory extends SynFactory
@Override
public <T extends AbsBaseSyn> T createSyn(Class<T> clz)
AbsBaseSyn baseSyn = null;
try
baseSyn = (AbsBaseSyn) Class.forName(clz.getName()).newInstance();
catch (Exception e)
e.printStackTrace();
return (T) baseSyn;
//定义抽象方法
public abstract class AbsBaseSyn
public abstract void init(Context context, FragmentManager fragmentManager, SynDialogFragment synDialogFragment, ExecutorService cachedThreadPool);
/**
* 产品类的抽象方法
* 由具体的产品类去实现
*/
public abstract ApiRequest syn(int page);
public abstract void cancle(boolean isCancle);
public abstract void continueRequest(int page, String tag);
//具体实现父类
public class BaseSyn extends AbsBaseSyn
protected Context mContext;
protected FragmentManager mFragmentManager;
protected SynDialogFragment mSynDialogFragment;
protected UpdateTimeDao mUpdateTimeDao;
public static boolean isCancle;
private ExecutorService cachedThreadPool;
//开始同步
@Override
public ApiRequest syn(int page)
return null;
//取消请求
@Override
public void cancle(boolean isCancle)
this.isCancle = isCancle;
//继续请求下一页
@Override
public void continueRequest(int page, String tag)
Log.v("tag", tag);
if(!isCancle)
syn(page);
//初始化
@Override
public void init(Context context, FragmentManager fragmentManager, SynDialogFragment synDialogFragment,
ExecutorService cachedThreadPool)
this.mContext = context;
mFragmentManager = fragmentManager;
this.mSynDialogFragment = synDialogFragment;
this.cachedThreadPool = cachedThreadPool;
mUpdateTimeDao = new UpdateTimeDao();
//保存所有数据
protected void save(final IBaseDao baseDao, final int message, final List list, final String function)
if(!cachedThreadPool.isShutdown())
cachedThreadPool.execute(new SynSave(baseDao, message, list, function));
//-----------------------------------------loading------------------------------------------
//取消loading dialog
protected void dismissSyning()
if (null != mSynDialogFragment)
mSynDialogFragment.dismiss();
//渲染错误的dialog
protected void showError(String result)
dismissSyning();
cancle(true);
showErrorDialog(result);
private void showErrorDialog(String result)
final CommonDialogFragment fragment = new CommonDialogFragment();
fragment.setResult("同步失败")
.setType(1)
.setResultDetails(result)
.setRightButtonStr("好的")
.setOnButtonClickListener(new CommonDialogFragment.OnButtonClickListener()
@Override
public void onLeftButtonClick(View v)
@Override
public void onRightButtonClick(View v)
);
fragment.showDialog("切换至在线", mFragmentManager);
//同步完成就发送消息
public class SynHandle extends Handler
@Override
public void handleMessage(Message msg)
super.handleMessage(msg);
EventBus.getDefault().post(new SynProgressEvent(msg));
//保存数据的方法
public class SynSave implements Runnable
private IBaseDao baseDao;
private int message;
private List list;
private String function;
private SynHandle mSynHandle;
public SynSave(final IBaseDao baseDao, final int message, final List list, final String function)
this.baseDao = baseDao;
this.message = message;
this.list = list;
this.function = function;
mSynHandle = new SynHandle();
@Override
public void run()
baseDao.firstUpdateList(list);
setUpdateTime(function);
BaseTools.putFirstUser(function);
mSynHandle.sendEmptyMessage(message);
private void setUpdateTime(final String columns)
GetSystemTimeRequest request = new GetSystemTimeRequest<GetSystemTimeResponse>()
@Override
public void onLogicSuccess(GetSystemTimeResponse response)
super.onLogicSuccess(response);
String time = response.getData().getSysInfo().getTime();
//改为每个用户都有多个更新时间,比如产品列表一个、批次列表一个
new UpdateTimeDao().setUpdateTime(time, columns);
;
request.get();
下面具体的请求类:产品数据请求、批次数据请求、机构数据请求
//产品数据同步
public class ProductSyn extends BaseSyn
GetProductListRequest mGetProductListRequest;
private List<Product> mProductList = new ArrayList<>();
private int mProductListPage = 1;
public ProductSyn()
mProductList.clear();
@Override
public ApiRequest syn(final int page)
super.syn(page);
initProductList(page);
return mGetProductListRequest;
@Override
public void cancle(boolean isCancle)
super.cancle(isCancle);
private void initProductList(final int page)
if (page == 1)
Log.v("tag", "initProductList");
mGetProductListRequest = new GetProductListRequest<GetProductListRespons>()
@Override
public void onStart()
super.onStart();
@Override
public void onLogicSuccess(GetProductListRespons respons)
super.onLogicSuccess(respons);
List<Product> list = respons.getData().getProductList();
if (ListUtils.isEmpty(list))
save(new ProductDao(), Contacts.M_PRODUCT, mProductList, UpdateTimeDao.PRODUCT_TIME);
return;
mProductListPage = page + 1;
mProductList.addAll(list);
continueRequest(mProductListPage, "initProductList"+page);
@Override
public void onLogicFailure(GetProductListRespons respons)
super.onLogicFailure(respons);
showError("initProductList" + respons.getError());
dismissSyning();
@Override
public void onFailure(int errorCode, String msg)
super.onFailure(errorCode, msg);
showError(errorCode + msg);
dismissSyning();
;
GetProductListRequest.Param param = new GetProductListRequest.Param();
param.setUpdateTime(mUpdateTimeDao.getUpdateTime(UpdateTimeDao.PRODUCT_TIME));
param.setPageNum(page);
param.setPageSize(Contacts.PAGE_SIZE_1000);
mGetProductListRequest.setParam(param);
mGetProductListRequest.get();
//批次数据同步
public class BatchSyn extends BaseSyn
GetProductBatchListRequest mGetProductBatchListRequest;
private List<Batch> mBatchList = new ArrayList<>();
private int mBatchListPage = 1;
public BatchSyn()
mBatchList.clear();
@Override
public ApiRequest syn(final int page)
super.syn(page);
initBatchList(page);
return mGetProductBatchListRequest;
private void initBatchList(final int page)
if (page == 1)
Log.v("tag", "initBatchList");
mGetProductBatchListRequest = new GetProductBatchListRequest<GetProductBatchListRespons>()
@Override
public void onStart()
super.onStart();
@Override
public void onLogicSuccess(GetProductBatchListRespons respons)
super.onLogicSuccess(respons);
List<Batch> list = respons.getData().getProductBatchList();
if (ListUtils.isEmpty(list))
save(new BatchDao(), Contacts.M_BATCH, mBatchList, UpdateTimeDao.PRODUCTBATCH_TIME);
return;
mBatchListPage = page + 1;
mBatchList.addAll(list);
continueRequest(mBatchListPage, "initBatchList"+page);
@Override
public void onLogicFailure(GetProductBatchListRespons respons)
super.onLogicFailure(respons);
showError("initBatchList" + respons.getError());
dismissSyning();
@Override
public void onFailure(int errorCode, String msg)
super.onFailure(errorCode, msg);
showError(errorCode + msg);
dismissSyning();
;
GetProductBatchListRequest.Param param = new GetProductBatchListRequest.Param();
param.setUpdateTime(mUpdateTimeDao.getUpdateTime(UpdateTimeDao.PRODUCTBATCH_TIME));
param.setPageNum(page);
param.setPageSize(Contacts.PAGE_SIZE_1000);
mGetProductBatchListRequest.setParam(param);
mGetProductBatchListRequest.get();
//机构数据同步
public class OrgSyn extends BaseSyn
GetOrgListRequest mGetOrgListRequest;
private List<Org> mOrgList = new ArrayList<>();
private int mOrgListPage = 1;
public OrgSyn()
mOrgList.clear();
@Override
public ApiRequest syn(final int page)
super.syn(page);
initOrgList(page);
return mGetOrgListRequest;
private void initOrgList(final int page)
if (page == 1)
Log.v("tag", "initOrgList");
mOrgList.clear();
mGetOrgListRequest = new GetOrgListRequest<GetOrgListRespons>()
@Override
public void onStart()
super.onStart();
@Override
public void onLogicSuccess(GetOrgListRespons respons)
super.onLogicSuccess(respons);
List<Org> list = respons.getData().getRows();
if (ListUtils.isEmpty(list))
save(new OrgDao(), Contacts.M_ORG, mOrgList, UpdateTimeDao.ORG_TIME);
return;
mOrgListPage = page + 1;
mOrgList.addAll(list);
continueRequest(mOrgListPage, "initOrgList" + mOrgListPage);
@Override
public void onLogicFailure(GetOrgListRespons respons)
super.onLogicFailure(respons);
showError("initOrgList" + respons.getError());
dismissSyning();
@Override
public void onFailure(int errorCode, String msg)
super.onFailure(errorCode, msg);
showError(errorCode + msg);
dismissSyning();
;
GetOrgListRequest.Param param = new GetOrgListRequest.Param();
param.setLastUpdateTimeBegin(mUpdateTimeDao.getUpdateTime(UpdateTimeDao.ORG_TIME));
param.setPageNum(page);
param.setPageSize(Contacts.PAGE_SIZE_1000);
param.setOrderField("LastUpdateTime");
mGetOrgListRequest.setParam(param);
mGetOrgListRequest.get();
最后客户端调用:
//1、首先创建一个class数组
private Class<AbsBaseSyn>[] synClass = new Class[]
ProductSyn.class,
BatchSyn.class,
OrgSyn.class
;
//2、开始同步
private void doSync()
mSynFactory = new SynConcreteFactory();
resetSyn();
cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < synClass.length; i++)
AbsBaseSyn basesyn = mSynFactory.createSyn(synClass[i]);
basesyn.init(getContext(), getFragmentManager(), mSynDialogFragment, cachedThreadPool);
basesyn.syn(1);
//3、同步结束后在onProgressEvent中取完成后的消息
private int progress;
private boolean messageState;
private List<Integer> mMessageList = new ArrayList<>();
@Subscribe(threadMode = ThreadMode.MAIN)
public void onProgressEvent(SynProgressEvent event)
Message msg = event.getMsg();
for (int i = 0; i < mMessageList.size(); i++)
if (msg.what == Contacts.MESSAGES[i])
mMessageList.set(i, msg.what);
progress = progress + (100 / mMessageList.size());
//传递进度
setUploadProgress(progress);
break;
for (int i = 0; i < mMessageList.size(); i++)
if (mMessageList.get(i) == 0)
messageState = true;
break;
if (!messageState)
//同步完成
dismissSyning();
resetSyn();
messageState = false;
是怎么做到监听所有请求都返回成功了,再弹出同步成功?
打印一下mMessageList的数据变化,你就知道了
Log.d("tag",
"[ " + mMessageList.get(0) + ","
+ mMessageList.get(1) + ","
+ mMessageList.get(2) + ","
+ " ]"
);
如图,只要有一个请求返回了,就会更新一次mMessageList,直到mMessageList中没有0,那么就同步成功了。
其他的一些支持类和方法:
public static final int M_PRODUCT = 1;
public static final int M_BATCH = 2;
public static final int M_ORG = 3;
public static final int MESSAGES[] =
M_PRODUCT,
M_BATCH,
M_ORG
;
//重置同步属性
private void resetSyn()
resetCancle();
progress = 0;
resetMsg();
//重置mMessageList,使mMessageList中是3个0
private void resetMsg()
mMessageList.clear();
for (int i = 0; i < Contacts.MESSAGES.length; i++)
mMessageList.add(0);
//取消请求
private void cancleSyn()
for (int i = 0; i < synClass.length; i++)
AbsBaseSyn basesyn = mSynFactory.createSyn(synClass[i]);
basesyn.cancle(true);
if(cachedThreadPool != null)
cachedThreadPool.shutdown();
//重置请求取消
private void resetCancle()
for (int i = 0; i < synClass.length; i++)
AbsBaseSyn basesyn = mSynFactory.createSyn(synClass[i]);
basesyn.cancle(false);
下面展示下所有类:
附加:用到的知识点:
1、持久层:litepal
2、请求:OKHttp
3、Executors线程池
4、弹框:DialogFragment
5、消息:EventBus
6、模式:工厂模式
以上是关于工厂模式实现并发请求多个接口 (同步后台数据实现离线APP)的主要内容,如果未能解决你的问题,请参考以下文章