作者:https://www.jianshu.com/p/b2b9a3699095
来源:GiftedCat
前言
前段时间要求项目中需要实现一个刷卡考勤的功能,因为涉及到上传图片文件,为加快考勤的速度,封装了一个异步轮询上传文件的帮助类
效果
先上效果图
![0f2a396c79e4d6d39d09b1e1c7121cc2.gif](https://i-blog.csdnimg.cn/blog_migrate/61627336459ef61203c88a4729dfb0f1.gif)
设计思路
![ab8be35a7f31e988b08a794e57ca5229.png](https://i-blog.csdnimg.cn/blog_migrate/d9986616fac3b5a1d547928c54b04638.png)
数据库使用的框架是GreenDao,一个非常好用的东西
先创建一个GreenDao的数据表的实体
来保存我们的考勤记录,我这边只写了一下几个参数,方便大家观看,使用的时候大家记得要编译一下来生成Dao文件跟get,set方法
1@Entity
2public class Attendance {
3
4 @Id(autoincrement = true)
5 public Long id;
6
7 /** 8 * 是否已上传 9 * */
10 public Boolean isUpload;
11
12 /**13 * 文件路径14 * */
15 public String path;
16
17 /**18 * 姓名19 * */
20 private String name;
21
22 /**23 * 考勤时间24 * */
25 private Date attendanceDate;
26
27}
帮助类的实现
首先是轮询线程判断是否运行
1 /**2 * 开启上传线程3 */
4 public void startUpThread() {
5 if (!isRun) {
6 return;
7 }
8 singleThreadExecutor.execute(upRunnable);
9 }
线程需要注意内存泄露,这个是必须的
1 /** 2 * 自建一个Runnable判断activity是否销毁,防止内存泄露 3 * */
4 private class UpRunnable implements Runnable {
5
6 private WeakReference activityWeakReference; 7 8 public UpRunnable(Activity activity) { 9 //使用弱引用赋值10 activityWeakReference = new WeakReference<>(activity);11 }1213 @Override14 public void run() {15 //判断activity是否已销毁16 if (activityWeakReference.get() != null){17 upRecord();18 }19 }20 }
先查询队列判断是否有数据需要上传
没有需要上传的数据延迟两秒后从数据库查询并填充队列
开始下一次的轮询
1 private void upRecord() {
2 Attendance Attendance = queue.poll();
3 if (null == Attendance) {
4 //没有需要上传的文件
5 LogUtils.d("上传队列为空 2秒后开始 检查是否存在上报");
6 try {
7 Thread.sleep(2000);
8 } catch (InterruptedException e) {
9 e.printStackTrace();
10 }
11 handleLocalAttendance();
12 startUpThread();
13 } else {
14 //有需要上传的文件,回调给页面
15 if (onUploadListener != null) {
16 onUploadListener.onUpload(Attendance);
17 } else {
18 startUpThread();
19 }
20 }
21 }
查询数据库的代码
1 /** 2 * 查询是否有上传任务 3 */
4 private void handleLocalAttendance() {
5 List attendances = DBHelper.getInstance().getSession().getAttendanceDao() 6 .queryBuilder().where(AttendanceDao.Properties.IsUpload.eq(false)) 7 .list(); 8 if (null != attendances && attendances.size() > 0) { 9 queue.addAll(attendances);10 }11 }
帮助类的使用
首先是先在初始化帮助类
1 UploadHelper uploadHelper = new UploadHelper(this);
2 uploadHelper.setOnUploadListener(new OnUploadListener() {
3 @Override
4 public void onUpload(Attendance attendance) {
5 //有需要上传的文件
6 uploadToServer(attendance);
7 }
8 });
9 uploadHelper.startUpThread();
接口调用成功后标记成功,开始下一次的轮询
1uploadHelper.uploadSuccess(dataModel);
在打卡回调中添加数据库记录,这样轮询线程就会查到
1//数据库
2Attendance attendance = new Attendance();
3attendance.setPath(Environment.getExternalStorageDirectory() + "/" + "Images/picture.png");
4attendance.setIsUpload(false);
5attendance.setName("张三");
6attendance.setAttendanceDate(new Date());
7uploadHelper.addRecord(attendance);
8updateDataList();
最后再贴上源码https://github.com/Giftedcat/UploadHelpUseDemo:https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2FGiftedcat%2FUploadHelpUseDemo
推荐阅读
一步步带你读懂 Okhttp 源码Android 点九图机制讲解及在聊天气泡中的应用职场上这四件事,越早知道越好自定义View之双层波纹气泡(xFermode)Android-自定义气泡View,让我们告别.9图面试官:今日头条启动很快,你觉得可能是做了哪些优化?面试官:你有m个鸡蛋,如何用最少的次数测出鸡蛋会在哪一层碎?
花式实现时间轴,样式由你来定!
面试官:Android 子线程更新UI了解吗?
Android 优雅地处理后台返回的骚数据
Android自动化脚本多渠道加固、打包
面试官:简历上最好不要写Glide,不是问源码那么简单
面试官,怎样实现 Router 框架?
那些年,我们一起追过的安卓技术大佬们
一行代码解决安卓重复点击
Android scheme 跳转的设计与实现
扫一扫,欢迎关注我的微信公众号 stormjun94(徐公码字)