当你遇到一些让你大吃一惊的解决方案的时候你不要惊讶,要学会低头去面试它,解决它。
最近公司项目要做个人脸识别,类似于门禁卡之类的。本来这也没什么,因为我接到任务后第一反应是这样的逻辑: 设备采集图片 --> 设备识别图片是否是人脸 --是人脸> 提交服务器进行身份识别 -> 服务器返回人物身份信息 我觉得这样的逻辑就是有点耗时。 然后根据公司需求是要做百度人脸的本地离线识别,也就是我要把服务器所有的人脸数据都放到本地来。enenen 当时头还是有点大的。 这种方案其实我个人来说是不太赞同的(哈哈哈 主要我懒) 怎么说呢?
如果你用户有一万个 等我同步一万个数据吗 数据更新的及时性
那么我公司的思路是俩个接口解决,第一个接口是获取所有用户数据,第二个是返回更新的数据。 enenen,我又要吐槽了。这个返回更新数据只有一次有效性。然后也没有回调。这样子就会存在问题。
虽然服务器返回的数据都做了验证,但是谁也不能确保这次的数据就更新成功了。好歹也给回调接口回调一下成功与否。
然后言归正传,设备端就是定时任务去请求同步本地数据,对没错就是定时任务。是不是有种当初第一次写通讯的时候的感觉,还不知道webscket是什么。 然后现在请求就跟麻烦,因为我这边请求完图片还要转bitmap,然后转字节,然后提取特征,然后入库。一条数据下来要个五六秒。 有点炸毛,不要说开服务,开线程。 我们要确保前台在识别的时候后台释放百度的人脸识别资源,给予最大程度的宽容。 所有我们要做的事情就是这样的 第一 保证循环的同步性,里面有许多异步操作,我们要保证数据一条条的走下去,不要给程序太大压力,我这设备配置也不高。 第二 保证我们能尽快的打断更新让出资源给前台使用 第三 在恢复以后我们要保证和断点续传一样接着刚才的走 真苦逼。。。。
直接说解决方案把,一把辛酸泪。
利用rxjava来解决异步问题 利用一段空代码来解决等待问题 利用标志位来控制是否让出资源 然后网络请求请用自调的,意思就是当访问失败的时候自调一次,更新完成是时候自调一次。
//空跑
private void LoadRunTime() throws InterruptedException {
while (!is) {
Thread.sleep(1000);
}
}
private void UPnext() {
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < dataBeans.size(); i++) {
LoadRunTime();
...
emitter.onNext(i);
}
emitter.onNext(-1);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
if (integer == -1) {
initLicense(MyApplication.getApplication(), new FinishMethod() {
@Override
public void finish() {
...
System.out.println("更新完成");
}
});
}
}
});
}
综上,这种要本地识别的情况还是建议用长连接的解决方案把,挂后台跑浪费性能,而且数据及时性太差,而且如果一次更新太多对程序来说也是压力。