《Clean Architecture》读书笔记 - 业务逻辑
背景读了 Martin大叔的 《Clean Architecture》,对其中第20章 业务逻辑 ,记录下自己的理解。 业务逻辑 业务逻辑就是程序中那些真正用于赚钱或省钱的业务逻辑与过程。 如我做的直播类应用,用户送礼给主播,然后直播间播放礼物特效。这就是业务赚钱的一个核心逻辑。这就叫“关键业务逻辑”。这个过程中处理的一些数据,如礼物id,数量,价格,收礼对象等,就是“关键业务数据”。这两者是紧密相关的,很适合放在同一个对象中处理,这种对象就称为“业务实体(Entity)”。 业务实体 业务实体这种对象中包含了一系列用于操作关键数据的业务逻辑。这些实体对象要么直接包含关键数据,要么可以很容易地访问这些数据。业务实体的接口层则是由那些实现关键业务逻辑、操作关键数据的函数组成的。 如 频道...
LifyCycle 的思考
LifyCycle 的思考 大纲google 的LifeCycle、 livedataglide里的 lifeCycleListener 也是一样的实现分析下原理,对比下两者。自己的组件怎么使用这个东西 Android architecture components在包 android.arch.lifecycle 包下新增了一些组件,几个核心的包括 LifeCycle, LiveData, ViewModel我们先重点关注下 LifeCycle开头的这几个。Interfaces:LifecycleObserverLifecycleOwnerLifecycleRegistryOwner Classes: 处理生命周期LifecycleLifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this...
一个有趣的需求实现过程:人脸表情包制作
需求产品有个需求是使用用户上传的照片,自动生成目前比较火的表情包,如下图: 技术点 人脸识别,这是购买别人的SDK实现的啦 。 图像的处理,抠图、图像变换、裁剪、叠加到背景等。 实现过程简单分析了下,要实现这个效果,也有几个关键点要处理好: 图像灰度、亮度、对比度的调整 脸部区域扣取和边缘模糊 当然,如果要进一步优化下去,也有很多的细节了: 人脸方向和背景不一致,则需要调整 人脸背景色和表情背景色不一致的情况,要调整; 人脸图像大小和位置也需要调整。。。先从基础的这几个点介绍下吧。 图像效果处理这里我使用了GPUImage的滤镜,可以很方便的对原图进行处理。GPUImageGrayscaleFilter GPUImageContrastFilter GPUImageBrightnessFilter 组合使用这三个滤镜,完成灰度、对比度、亮度的调整即可。 脸部区域扣取和边缘模糊 计算脸部区域合适的Path根据识别SDK给出的人脸五官部位的特征点,来构造一个脸部五官区域的Path。这个Path的计算也经历了几个尝试,主要以两眉和嘴的坐标点来计算,最后的方案是...
通过flatmap组合多个SqlBrite的QueryObservable 使用的问题
阅读背景SqlBrite 是Square公司提供的一个数据库轻量级的封装框架。提供了RxJava的Observable风格的DB操作接口,其中一个特性是 其query操作得到的QueryObservable会一直保持对该次查询的表后续变更的事件的订阅,后续针对同一张(或多张)表的变更,均会再次发射数据给它的Subcriber,从而可以方便的实现界面的更新。 自定义的词汇含义: 订阅链、事件流: 这是指任意个Observable组合后,最终被某个Subscriber订阅时,所确定的一条订阅关系链。如: 12345 ObservableA.flatMap(ObservableB) .flatMap(ObservableC) .subscribe(new Subscriber<T>() {...} 问题背景我们最近的一个项目中使用了SqlBrite + SqlDelight框架...
修复一例 BlockingQueue.poll 导致的线程While循环无限执行占用cpu的bug
起因基于部分用户反馈使用我们的app时,玩游戏过程中会有卡顿现象出现,从而进行cpu使用率排查。 发现问题今天先操作进入一个房间后,使用android的traceview跟踪了一段2s左右的cpu使用数据,然后通过traceview对其进行分析。 如图一所示,左边列出了该时间段内的线程,右边则图形化的显示了它们的cpu使用情况。很直观的能够发现,”GroupMsgTransport”这个线程几乎一直在占用cpu,比main线程还多的多。所以首先引起怀疑。 再进一步查看详细的cpu使用情况,发现占用cpu time最多的几项都是在对一个BlockingQueue的操作,选择这些行之后,也定位到了 “GroupMsgTransport”线程。说明这条线程一直在对Queue执行poll操作。通过在代码中搜索关键字,查找到了这个罪魁祸首。 定位原因最终定位到这段问题代码: 123456789101112131415@Override public void run() { ...
切换到Hexo + GithubPages
博客之前用的是sina的SAE + press,也一直还不错。其实最早一开始用的是AWS的EC2,但连接速度实在太慢,才换到SAE的。然后参加活动获得了一些云豆,本以为够用蛮久的,结果最近一两个月,突然的访问把云豆都用光了。于是,就打算切换到githubpages上,昨晚在网上看了下hexo来搭建博客,看上去蛮不错的,于是就切换过来了。这次应该就不怕流量用完了,而且hexo的使用也蛮方便的,网上的各种资料也挺多,感谢这些作者,给大家带来了便利。
MultiTypeListViewAdapter Android ListView 多type的Adapter封装
MultiTypeListViewAdapter 是什么?MultiTypeListViewAdapter,顾名思义。其封装了多type下的Adapter的编程模式,通过对每种type统一接口,利用多态的方式,将type的实现从Adapter中抽离出来。Adapter只需面向统一接口,所以可以提供一个通用实现,实现代码不再变动。而会变动的每个type对应的item实现,则由使用者自己去实现。对扩展开放,对修改封闭。 同时,由于每个type的item均被抽离出来了。相当于复用的粒度为每个type item,可以根据需要,动态地选择合适的item去添加到adapter中。提高了代码复用,每个人编写维护好自己的item即可,避免了多人合作时都去修改Adapter,容易造成冲突。 另外,由于ViewHolder 模式的规范,MultiTypeListViewAdapter也同时封装了ViewHolder模式。常见的ListView Adapter 实现先看一下常见的ListAdapter...
android 子线程中更新界面?被ProgressBar给迷惑了
在看apidemos的例子RetainedFragement时,看到在Thread中执行了 这么一句 1mProgressBar.setProgress(progress); 且执行正常,progressbar确实一直在更新。顿觉疑惑,View在更新时,会检查当前线程是否是创建view所在的线程(即UI线程),若不一致,则会抛出异常的。 in ViewRootImpl.java 中: 123456void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); ...
如何获取 Gopro 视频流
前言:最近的工作在研究gopro的视频流如何获取,通过搜索资料,以及对gopro app的抓包分析,得出了以下经验。这次的分析过程也体会到抓包分析的好处,以后还应进一步学习如何用好抓包工具。 如何获取Gopro的视频流以下的这些url会随gopro的型号版本而有所不同,需要自己抓包分析确定。 gopro提供了wifi和hdmi的视频输出,目前研究的是wifi输出。通过对gopro app抓包分析,和网上搜索的资料,整理出以下方法: 先通过gopro app完成和gopro的蓝牙配对,配置好wifi热点,并开启wifi热点; 手机切换至gopro的热点网络,在 udp://:8554 上开启监听。 发送http get request( http://10.5.5.9/gp/gpExec?p1=gpStreamA9&c1=restart),gopro即开始向手机的 8554 端口发送数据。手机即可在udp 8554端口收到数据。 通过抓包分析,gopro app会定期(1次/s)发送心跳请求,维持连接。udp...
组合还是继承
如题,每天在“面向对象”的我们,也常常遇到这个选择吧。刚好看书书读到这个话题,就记录下阅读的理解。 继承要慎用,其使用场合仅限于你确信使用该技术有效的情况。一个判断方法是,问一问自己是否需要从新类向基类进行向上转型。如果是必须的,则继承是必要的。反之则应该好好考虑是否需要继承。——《java编程思想 第四版》 p140 复合优于继承 与方法调用不同的是,继承打破了封装性。换句话说,子类依赖于其超类中特定功能的实现细节。 只有当子类真正是超类的子类型时,才适合用继承。换句话说,对于两个类A和B,只有当两者之间确实存在“is-a”关系的时候,类B才应该继续类A。 为了避免这种脆弱性,可以用复合和转发机制来代替继承,尤其是当存在适当的接口可以实现包装类的时候。包装类不仅比子类更健壮,而且功能也更加强大。 ——《Effective Java》 item.16 在平时工作过程中,我自己也是更多选择组合而不是继承。但也没有个明确清晰的判断标准。和同事交流时,虽然也推荐多用组合,但也说不出个具体的缘由。平时主要是开发android...