摘要:自上次发文章之后已经过了个月了,我也在月号结束了一个人的旅行历时天回到了深圳,专心于完成这个全端项目的客户端开发,终于在月号版上线,月号上线到。当前项目已经完全实现自动部署。
「daza.io」是一款基于技能树(正在实现)的技术内容聚合应用,根据你的技能对内容进行筛选,让你在这个信息过载的时代里更高效地获取你所需的内容。
自上次发文章之后已经过了2个月了,我也在11月19号结束了一个人的旅行(历时59天)回到了深圳,专心于完成这个全端项目的客户端开发,终于在12月2号 iOS 版上线 AppStore ,12月7号 Android 上线到 GooglePlay。
最初我将 iOS 版定价为1元,但是后来和一朋友聊天时聊到这个项目能为用户提供什么价值的问题,后来想想目前这个项目能给用户提供的价值是有限的,所以就调为免费的了。
访问网站https://daza.io
https://api.daza.io
获取源码Star ! Star ! Star !
daza-backend
daza-frontend
daza-ios
daza-android
应用截图获取Android 的界面布局与 iOS 版基本保持一致,但均采用了原生的控件实现,这里就不放截图了。
快速获取(自动识别系统):
http://a.app.qq.com/o/simple....
已上架多个国内主流应用市场
一些小技巧设计以下是我觉得比较值得分享的小技巧。
对于我来说 UI 才是最头痛的,在没有设计师帮忙的情况下一切都得自己来了,下面是我在做 UI 时的一些经验。
选用成熟的配色方案
使用相同风格的图标(尽量使用比较全的图标库)
尽量保持简洁的界面设计(实用至上)
与系统风格保持一致
合适的字体尺寸以及边距等
设计要符合使用场景(很多使用侧边栏导航的应用就是反面教材)
参考资源我在项目里使用了 Material Design 提供的配色(Blue Grey)和图标,在两个系统上看起来都非常的和谐。
https://material.io/icons
https://material.google.com/s...
第三方服务使用第三方服务就是为了减少研发成本,但一定要慎重选用。下面介绍这个项目使用的一些第三方服务。
DaoCloud
> 使用了 Docker 镜像构建,自有主机功能。 > 当前项目已经完全实现自动部署。
阿里云
> 使用了 ECS 云主机
七牛云
> 使用了 云存储,免费 SSL 证书
云巴
> 使用了推送服务
GrowingIO
> 用于统计
BugHD
> 用于 Crash 收集
AdMob
> 广告API
使用了 REST 风格进行设计,每个接口所返回的数据结构均保持一致。
数据结构示例:
{ "code": 0, "message": "...", "errors": [ { "code": 10000, "field": "user", "message": "用户 不存在。" } ], "pagination": { "total": 10, "per_page": 10, "current_page": 1, "last_page": 1, "from": 1, "to": 10 }, "data": { ... } }
code: 错误码
> 当错误码不为 0 时代表发生错误。
message: 错误消息
errors: 错误列表
> 当发生多个错误时返回错误列表,客户端根据列表返回的进行相应的处理。
pagination: 分页对象
> 仅当 data 字段为数组时才返回。
"total": 总数 "per_page": 每页显示数量 "current_page": 当前页码 "last_page": 最后一页面页码 "from": 开始Id "to": 结束Id
data: 数据(对象 / 数组)
> 在实现时使用泛型对 data 进行处理。
泛型数据处理示例(Java):
public class Result客户端 文章详情(WebView交互){ private int code; private String message; private List errors; private Pagination pagination; private T data; public Result() { } public boolean isSuccessful() { return this.code == 0; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public List getErrors() { return errors; } public void setErrors(List errors) { this.errors = errors; } public Pagination getPagination() { return pagination; } public void setPagination(Pagination pagination) { this.pagination = pagination; } public T getData() { return data; } public void setData(T data) { this.data = data; } } // 当 data 为 User 时的示例 new Result (); // 当 data 为 User 列表时的示例 new Result >();
文章详情页面因为排版相关原因,并没有采用原生的开发方式,而是直接加载一个外部链接
外部链接:
https://daza.io/in-app/articles/{id}
因为 WebView 此时是没有保存用户状态的,所以需要将客户端的用户登录Token相关信息传递给 WebView,即在加载完毕后执行 JavaScript 代码写入。
Java:
// 开启 JavaScript 及 localStorage支持 mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setDomStorageEnabled(true); // 页面加载完毕后将相关数据保存到localStorage里。 public void onPageFinished(WebView view, String url) { String script = "javascript:"; if (Auth.check()) { script += "localStorage.setItem("auth.id", "" + Auth.id() + ""); "; script += "localStorage.setItem("auth.user", "" + Auth.user().toJSONString() + ""); "; script += "localStorage.setItem("auth.jwt_token", "" + Auth.jwtToken().toJSONString() + ""); "; } else { script += "localStorage.clear(); "; } mWebView.loadUrl(script); }
完整代码:
https://github.com/lijy91/daz...
Swift:
func webViewDidFinishLoad(webView: UIWebView) { if (!Auth.check()) { return } let standardUserDefaults = NSUserDefaults.standardUserDefaults() let authId = Auth.id(); let authUser = standardUserDefaults.stringForKey("auth.user") let authJwtToken = standardUserDefaults.stringForKey("auth.jwt_token") var script = "" script += "localStorage.setItem("auth.id", "(authId)"); " script += "localStorage.setItem("auth.user", "(authUser!)"); " script += "localStorage.setItem("auth.jwt_token", "(authJwtToken!)"); " webView.stringByEvaluatingJavaScriptFromString(script) }
完整代码:
https://github.com/lijy91/daz...
支持 DeepLink 后在WebView里直接可以通过自定义的 URL 来打开相应的页面,避免与 WebView 更麻烦的操作。
目前支持的链接:
daza://users/{user_id} daza://topics/{topic_id} daza://articles/{article_id} daza://articles/{article_id}/comments
由于安卓的WebView不支持这个DeepLink,所以需要做一些处理:
public WebViewClient mWebViewClient = new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("daza://")) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); startActivity(intent); return true; } return super.shouldOverrideUrlLoading(view, url); } }关于作者
目前正处于自由职业的状态,如果有API或者客户端的需求欢迎加我微信
捐赠如果你有什么好想法想告诉我,或者想加入讨论组(注明加入讨论组),请加我微信。
如果你觉得我的工作对你有帮助,那你可以为项目捐赠运营费用。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/16567.html
摘要:自上次发文章之后已经过了个月了,我也在月号结束了一个人的旅行历时天回到了深圳,专心于完成这个全端项目的客户端开发,终于在月号版上线,月号上线到。当前项目已经完全实现自动部署。 「daza.io」是一款基于技能树(正在实现)的技术内容聚合应用,根据你的技能对内容进行筛选,让你在这个信息过载的时代里更高效地获取你所需的内容。 自上次发文章之后已经过了2个月了,我也在11月19号结束了一个人...
摘要:另外它还有另外一个作为,为我的其他小项目提供数据。查看文档后端在最终采用之前,我一度已经在使用开发了,但由于考虑到代码被其他项目重用及市场现状,并且上半年负责的项目刚好使用了。 最近三年的工作经历,让我有机会接触到不同技术栈的项目,并且从中积累了不少各个技术栈的开发经验,虽然技术深度不够,但可以用不同技术视角去思考项目的设计和开发,例如:以客户端开发的视角去思考 API 的设计、用客户...
摘要:另外它还有另外一个作为,为我的其他小项目提供数据。查看文档后端在最终采用之前,我一度已经在使用开发了,但由于考虑到代码被其他项目重用及市场现状,并且上半年负责的项目刚好使用了。 最近三年的工作经历,让我有机会接触到不同技术栈的项目,并且从中积累了不少各个技术栈的开发经验,虽然技术深度不够,但可以用不同技术视角去思考项目的设计和开发,例如:以客户端开发的视角去思考 API 的设计、用客户...
摘要:客户端上线各大应用市场随时随地关注开发动态,团队协作各位大神如有兴趣即可关注,没兴趣的看看就好客户端千呼万唤始出来没能在国庆节前和端齐齐出锅,以至于我们每天都收到很多呼唤端的声音,经过这段时间的优化调整,客户端终于诞生和各位小伙伴见面了你可 Coding iOS & Android 客户端上线各大应用市场!随时随地关注开发动态,团队协作!(各位大神如有兴趣即可关注,没兴趣的看看就好^_...
摘要:客户端上线各大应用市场随时随地关注开发动态,团队协作各位大神如有兴趣即可关注,没兴趣的看看就好客户端千呼万唤始出来没能在国庆节前和端齐齐出锅,以至于我们每天都收到很多呼唤端的声音,经过这段时间的优化调整,客户端终于诞生和各位小伙伴见面了你可 Coding iOS & Android 客户端上线各大应用市场!随时随地关注开发动态,团队协作!(各位大神如有兴趣即可关注,没兴趣的看看就好^_...
阅读 2913·2021-10-13 09:40
阅读 1823·2021-09-23 11:20
阅读 1018·2021-09-22 15:09
阅读 2158·2021-08-20 09:38
阅读 2268·2021-08-03 14:03
阅读 630·2019-08-30 15:55
阅读 3242·2019-08-30 12:59
阅读 3401·2019-08-26 13:48