热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

手把手带你撸一个校园APP(六):失物招领二手交易模块

代码经过简单的整理,已经放到Github上了。https:github.comzhengweichaoHevttc回首来看,代码质量一般,

代码经过简单的整理,已经放到Github上了。https://github.com/zhengweichao/Hevttc
回首来看,代码质量一般,里面也有各种逻辑问题,还望各位看官海涵。接下来有时间的话,会逐步进行优化。如果对你有帮助,还望可以给个star,不胜感激。


前言

在校园生活中,存在着各种各样的信息差。也正因为这些信息差的存在,经常让校园同学们面临各种各样的问题。比如丢东西的找不到东西,捡到东西的找不到失主等等。其中最为突出的莫过于 【失物招领】及【二手交易】了。
校园作为一个比较特殊的地点,大家的素质以及诚信度普遍高于其它地方。“科师有约” 校园APP致力于减少校园信息差的存在,让校园生活更简单。

科师有约 只是一个美好的想法,并将部分功能从技术上进行简单实现。在实际生活中并未推广开来使用,在此权当抛砖引玉之用。还是希望学弟学妹们可以做出真正的产品,并在校园生活中得以应用。

本项目基于Bmob进行开发,很多地方需要Bmob相关知识。大家如果没了解过的话,可先自行查看 Bmob开发文档 。

系列文章:

Github地址: 科师有约校园APP

  1. 手把手带你撸一个校园APP(一):项目简介
  2. 手把手带你撸一个校园APP(二):应用启动和欢迎页面
  3. 手把手带你撸一个校园APP(三):用户模块(登录注册等)
  4. 手把手带你撸一个校园APP(四):APP框架及功能设计
  5. 手把手带你撸一个校园APP(五):新闻页面中心模块
  6. 手把手带你撸一个校园APP(六):失物招领&二手交易模块
  7. 手把手带你撸一个校园APP(七):图说校园模块
  8. 手把手带你撸一个校园APP(八):校园通讯录模块
  9. 手把手带你撸一个校园APP(九):课程表模块(模拟登陆爬取教务处课程信息)
  10. 手把手带你撸一个校园APP(十):APP通用模块(更新,意见反馈等)

实现效果

【失物招领】:
分为 寻物启事(找东西的)+ 失物招领(找失主的)
【二手交易】:
分为 淘点宝贝(想买东西的)+ 换点银子(想卖东西的)。效果图与失物招领类似

在这里插入图片描述

分析

失物招领与二手交易,两个模块从整体逻辑上来说基本一致。因为我们只做简易实现,所以就两个模块就不再区分讲解(下简称 “需求” )。
(当然,这里还可以做很多很多优化,本文后面【未来可做的优化】部分会进一步讲解)
需要实现功能如下:

  1. 发布需求(含 图片压缩及上传)
  2. 需求列表展示
  3. 需求详情展示
  4. 沟通联系(简化为 拨打电话)

其中需求列表的展示页面,与 新闻中心模块 使用的技术代码基本相同。想了解的可以再退回去看 上篇文章。

数据库设计

(因两模块基本逻辑相似,仅就失物招领模块开讲)
为了使数据区分的更清楚,设计数据库时,将 “失物招领” 与 “寻物启事” 分别设置为两个表。其中的字段名称设计等均相同。字段如下:

字段名描述类型是否主键
objectId事件id号String
title事件标题String-
tel联系方式Number-
author发布人String-
content事件详细描述String-
isOver事件处理状态Boolean-
createdAt事件发布时间Date-

(大家也可以设置为一个表,其中另外加一个字段进行区分)

安卓实现


发布需求

此处应用的技术都比较简单。发布需求 其实就是简单的数据库的增加操作。带图片的需求需要再做一下进一步的处理(图片压缩以及上传)

发布无图片的需求

LoseItem bean = new LoseItem();
MyUser user = BmobUser.getCurrentUser(MyUser.class);
bean.setAuthor(user.getUsername());
bean.setContent(loseDesc);
bean.setTel(loseTel);
bean.setTitle(loseTitle);
bean.save(new SaveListener<String>() {&#64;Overridepublic void done(String objectId, BmobException e) {if (e &#61;&#61; null) {ToastUtil.show(LoseAddActivity.this, "发布成功", Toast.LENGTH_SHORT);LoadDialog.dismiss(LoseAddActivity.this);startActivity(new Intent(LoseAddActivity.this, LoseActivity.class));finish();} else {ToastUtil.show(LoseAddActivity.this, "发布失败&#xff0c;请稍后再试", Toast.LENGTH_SHORT);LoadDialog.dismiss(LoseAddActivity.this);}}
});

发布有图片的需求

现在手机像素一般都很高&#xff0c;所以一个图片好几MB 的情况也很常见。直接上传的话&#xff0c;会极大浪费用户流量以及文件存储空间。所以需要对图片进行压缩处理后再上传。
所以发布有图片的需求需要拆分为以下 4 步来进行。

1. 选择图片
选择图片部分使用了 廖子尧 大神的 imagepicker 库。完全仿微信UI&#xff0c;实现了拍照、图片选择&#xff08;单选/多选&#xff09;、 裁剪 、旋转 等功能。

Github : imagepicker
作者&#xff1a;廖子尧 jeasonlzy

大神的文档写的十分详尽&#xff0c;集成方法我就不再赘述了。核心代码如下&#xff1a;

// 设置 图片选择器 相应参数
ImagePicker imagePicker &#61; ImagePicker.getInstance();
imagePicker.setImageLoader(new GlideImageLoader()); //设置图片加载器
imagePicker.setShowCamera(true); //显示拍照按钮
imagePicker.setCrop(true); //允许裁剪&#xff08;单选才有效&#xff09;
imagePicker.setSaveRectangle(true); //是否按矩形区域保存
imagePicker.setSelectLimit(maxImgCount); //选中数量限制
imagePicker.setStyle(CropImageView.Style.RECTANGLE); //裁剪框的形状
imagePicker.setFocusWidth(800); //裁剪框的宽度。单位像素&#xff08;圆形自动取宽高最小值&#xff09;
imagePicker.setFocusHeight(800); //裁剪框的高度。单位像素&#xff08;圆形自动取宽高最小值&#xff09;
imagePicker.setOutPutX(1000); //保存文件的宽度。单位像素
imagePicker.setOutPutY(1000); //保存文件的高度。单位像素// ...省略其它代码// 开始选择图片
List<String> names &#61; new ArrayList<>();
names.add("拍照");
names.add("相册");
showDialog(new SelectDialog.SelectDialogListener() {&#64;Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {switch (position) {case 0:// 直接调起相机ImagePicker.getInstance().setSelectLimit(maxImgCount - selImageList.size());Intent intent &#61; new Intent(LoseAddActivity.this, ImageGridActivity.class);intent.putExtra(ImageGridActivity.EXTRAS_TAKE_PICKERS, true); // 是否是直接打开相机startActivityForResult(intent, REQUEST_CODE_SELECT);break;case 1://打开选择,本次允许选择的数量ImagePicker.getInstance().setSelectLimit(maxImgCount - selImageList.size());Intent intent1 &#61; new Intent(LoseAddActivity.this, ImageGridActivity.class);intent1.putExtra(ImageGridActivity.EXTRAS_IMAGES, images);startActivityForResult(intent1, REQUEST_CODE_SELECT);break;}}
}, names);

2. 图片压缩
图片压缩部分采用了 Luban&#xff08;鲁班&#xff09; —— Android图片压缩工具&#xff0c;仿微信朋友圈压缩策略。
作者采用逆向推算&#xff0c;效果已经很接近微信朋友圈压缩后的效果。
&#xff08;再次踩在了巨人的肩膀上……&#xff09;

Github : Luban&#xff08;鲁班&#xff09;
作者&#xff1a; Curzibn

核心代码如下&#xff1a;

Luban.with(LoseAddActivity.this).load(paths) // 传入要压缩的图片列表.ignoreBy(100) // 忽略不压缩图片的大小.setTargetDir(getPath()) // 设置压缩后文件存储位置.setCompressListener(new OnCompressListener() { //设置回调&#64;Overridepublic void onStart() {// 开始压缩 ...}&#64;Overridepublic void onSuccess(File file) {// 压缩成功 ...}&#64;Overridepublic void onError(Throwable e) {// 当压缩过程出现问题时调用}}).launch(); //启动压缩

3. 图片上传
这里是按照Bmob官方代码来写的。详情可见 Bmob文件管理 。

BmobFile.uploadBatch(filePaths, new UploadBatchListener() {&#64;Overridepublic void onSuccess(List<BmobFile> files, List<String> urls) {// 上传图片成功//1、files-上传完成后的BmobFile集合&#xff0c;是为了方便大家对其上传后的数据进行操作&#xff0c;例如你可以将该文件保存到表中//2、urls-上传文件的完整url地址}&#64;Overridepublic void onError(int statuscode, String errormsg) {// 上传图片失败LoadDialog.dismiss(LoseAddActivity.this);}&#64;Overridepublic void onProgress(int curIndex, int curPercent, int total, int totalPercent) {}
});

需要注意的是 上传多张图片&#xff0c;onSuccess 会多次调用 。别忘了做相应处理。

4. 发布需求
和发布无图片需求代码基本一致&#xff0c;只不过多了一句设置图片的代码。

LoseItem bean &#61; new LoseItem();
// ... 省略其它代码
bean.setPic(files.get(0));bean.save(new SaveListener<String>() {&#64;Overridepublic void done(String objectId, BmobException e) {// ... 省略其它代码}
});

至此&#xff0c;失物招领 & 二手交易模块基本完成。

然而整个流程中还有很多可以优化的地方&#xff0c;作者大概率没有时间和精力去做这部分了。
特将这部分内容整理如下&#xff0c;若他人有类似需求&#xff0c;以望能有所启迪或帮助。

未来可做的优化

简而言之&#xff0c;就是 提升平台能力

因两个模块逻辑相似性较高&#xff0c;故此处以【失物招领】为例&#xff1a;
在一个完整的过程中&#xff0c;总共存在3方&#xff1a;丢东西的&#xff0c;捡东西的&#xff0c;平台。

本文上面已经讲解了最基础简易的沟通流程&#xff1a;

  1. 丢东西的 在平台发布 寻物启事&#xff1b;捡东西的看见 --> 私下联系&#xff1b;
  2. 捡东西的 在平台发布 失物招领&#xff1b;丢东西的看见 --> 私下联系&#xff1b;

这种方式固然简单粗暴&#xff0c;但是显得不太灵活。
身为平台&#xff0c;应该发挥出平台更大的能力。那么应该从哪里开始入手呢&#xff1f;

校园是一个很特殊的地方&#xff0c;这里的失物招领有许多特殊之处&#xff0c;总结一下不难发现&#xff1a;

  1. 用户群体&#xff08;学生&#xff0c;教职工&#xff0c;家属楼住户&#xff09;绝大多数都接受过高等教育&#xff0c;文化素质较高&#xff0c;认知较为统一&#xff1b; &#61;&#61;> 【其它用户捡到后&#xff0c;有较大概率归还】
  2. 用户活动范围较为一致&#xff0c;活动区域较为封闭&#xff1b; &#61;&#61;>【用户丢失物品&#xff0c;较大概率被其它校园用户捡到】
  3. 用户捡到或丢失的物品有较高重复性&#xff08;校园卡&#xff0c;身份证&#xff0c;课本&#xff09;&#xff1b; &#61;&#61;> 【物品上一般带有 失主信息&#xff0c;可以通过实名信息直接锁定失主】
  4. 根据院系&#xff0c;专业&#xff0c;班级等&#xff0c;很容易找到相关实名用户。 &#61;&#61;> 【根据附属信息&#xff0c;很容易找到某人或其朋友同学】
  5. 有很多人捡到东西后&#xff0c;会交给专门的组织或个人&#xff08;失物招领协会&#xff0c;门卫&#xff0c;校园卡服务中心等&#xff09;。 &#61;&#61;> 【可以集中起来这些地方的信息&#xff0c;统一处理】

综上所述&#xff0c;未来如果有学弟学妹想做这部分&#xff0c;按个人看法&#xff0c;可做的优化如下&#xff1a;

  1. 加强用户实名认证操作&#xff0c;仅限实名认证用户使用APP。
  2. 定期收集整理线下失物招领信息&#xff0c;录入线上系统。
  3. 线上系统运用实名信息匹配失主并通过推送私信等方式进行联系&#xff08;保证用户隐私的前提下进行&#xff09;。
  4. 对线上信息进行匹配以及相似内容匹配操作&#xff0c;以优化处理双方都发布了信息的情况。


至此&#xff0c;本文内容全部完毕&#xff0c;项目中大量依赖或采用了第三方项目的代码。在此向各位有分享精神的大佬们致敬&#xff01;

如果本文对你有所帮助&#xff0c;还望可以随手赏一个点赞哈 ~ ~


推荐阅读
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • Oracle10g备份导入的方法及注意事项
    本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
author-avatar
王漻_957
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有