为什么攻城狮论坛老是误解意思,还是我说的不够清楚

跟老公说话他一直都是误会我的意思是代沟吗?越想说清楚就越说不清楚,然後呢俩人也都是比较强势,都不_百度知道
跟老公说话他一直都是误会我的意思是代沟吗?越想说清楚就越说不清楚,然後呢俩人也都是比较强势,都不
意低头,咋办啊?担心会伤害对方的感情!
我有更好的答案
说明他心思比较重,老是把你的意思想偏了,这种事情,怎么说的,你应该找个时间,两个人心平气和的沟通一下,心里有什么怨恨,有什么误解,大家敞开心扉的说出来。至于以后怎么相处,你们也好好的谈谈,两个人重在沟通
采纳率:82%
为您推荐:
其他类似问题
代沟的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。跟老公总是沟通不畅,他总听不懂我说话的意思,误解我说话的意思,是没有文化程度的原因还是头脑迟钝的问_百度知道
跟老公总是沟通不畅,他总听不懂我说话的意思,误解我说话的意思,是没有文化程度的原因还是头脑迟钝的问
跟老公总是沟通不畅,他总听不懂我说话的意思,误解我说话的意思,是没有文化程度的原因还是头脑迟钝的问题?
我有更好的答案
你文凭高功底深厚,说起话来就像教授。他当然听不懂啦
采纳率:50%
你若想过的幸福你就迁就他喽……他的水平低于你你又不迁就他肯定没有幸福可言……
那是挑刺儿
说的慢点,清晰点就好
迟钝的问题可能
其他10条回答
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。十年攻城狮----我眼中的IT行业
上世纪90年代,在那个互联网兴起的年代,搞IT,特别是软件编程,网页设计,还有后来的FLASH等动漫设计,给人的是一种高大上的感觉,不是说行业多牛逼,而是工资确实是高,在我这个外行人看来,这一种在中国算是新兴的行业,充满了神秘感,觉得这才是未来的高科技行业,所以当年读书时就涌起了以后工作就要搞编程,觉得这是一个朝九晚五,对着屏幕打打字,写写代码,就能够拿高薪,放假就可以去旅游的工作。要知道当时随便搞台现在看来已经是古董的电脑都要万元。说起哪个同学家里有台电脑,那个自豪感比现在哪个同学买了新车还要高不少。随着WIN95的发布,WIN98的一统浆糊,随着第一个OICQ号码的申请,慢慢的毕业后就固执的走了这么一条路子。当拿着软件攻城狮的证书,想要去展示才华时,却发现,互联网那个七彩的泡沫在阳光下消失了,当年网页改个字都算钱的年代说过去就过去了,随便会写写代码就7、8K的年代也忽然间没了,就连OICQ打了几次仗后都变成了QQ,这时才发现,原来这就是IT,更新换代快得在你眨个眼的时间就过去了。还在津津乐道当年罗马复兴、红色警戒的时候,却蓦然发现,现在已经流行起魔兽了,当属于我的雷神之锤的余热还在心头,大街小巷已经响起了CS的枪声。意气风发忽然间就变成了对未来的迷惘,充满了恐惧,这就是我想要的东西吗?没办法了,像本狮子这种新三无人员(无爹拼,无背景,无资金)的社会主义接班人,只能是硬着头皮走进这个当年充满了向往的IT行业。闲话就不说太多了,先说说在这个行业10几年的一些经验或者是经历吧,有些确实不是什么经验,只不过多吃了几年饭,可能还不比不上新进几年的师弟师妹们理解透彻。说什么好呢?那先说一下这10几年的薪资变化吧,可能大家对这个很感兴趣,不过可能令大家失望了,因为比起天涯上我的朋友、我的同学之类的低不少,拖了社会主义建设的后腿。也进不了那些在天涯响当当的大企业,可能是我能力有限吧。但我只能在我所处的阶层开始爬了,至于能爬多高,虽知道呢。本狮子当年确实老实人一枚,一步步走过来,没有运气,没有贵人相助,没有意外之财,总之一切意外一切机遇都与我无关,有的只是一步一个脚印,可能注定不能有所作为了,太过按部就班,太过依赖于父母的教导,穷人的文化总是会传承的,就好像富人的文化会传承一样。有时候确实是这样,一个人的出身,可能会约束了你的行为,从而限制了你的思维,紧跟着就是眼界不够开阔,到最后导致的就是社会上所有的机遇,你都没有胆量去尝试,一切对你来说都是陷阱,还是按部就班,这样安全,但是却不知道这才是温水煮青蛙的开始。所以说富人战胜法律,穷人却败给道德,穷确实是有根源的。孰是孰非,我也不清楚了。不过有一点可以肯定的,有钱与否,与你是否觉得幸福无关。
好了言归正传,第一份工作,试用期三个月,工资1.5K。广东二线城市。工资应该是很低了。时间21世纪刚开始没多久。当时的感觉就是,刚好够花,试用期三个月基本全部花光,前提是公司提供了宿舍,还包了一半的电费。周末还可以和同学吃吃喝喝,唱唱K,当时钱确实见花。转正之后,因为刚毕业,怕人家不要,心里没底,没怎么谈,招我的领导说加到2.5K。就这样签了3年合同,至于当年是怎样开始这个写代码的生活就差不多忘记了,只记得几个同住宿舍要好的同事,每周都轮流做东,出去吃一顿好的大餐,然后去超市买一大堆饮料,饼干,只记得只要给200块钱,超市的小车子基本上装满。天啊,那是一个怎样的年代。由于公司是每年都谈加薪的,由于去年业绩不好,没谈,我不知道别人有没有谈,公司这一年也走了不少人,后来我才明白行业流动性,根本原因是工资低。但是我本着自己是新人的原则,先做事,反正还年轻,只要是不太过刻薄,我还是能够理解公司的做法。和现在我招的新人相比,我都当时不知道会有这样的想法。鄙视一下自己,有时候应该对自己有点信心,因为当时对自己确实没什么信心,其实,到了今天很多事情才恍然大悟,也许是经历过了才能够更好理解这个社会。这个慢慢再说吧。2年合同之后,由于第一年没有谈工资,第2年满了之后,领导直接跟我说,加到3.7K左右,反正不到4K。当时,觉得自己出去也难找工作,也答应了。第三年满了之后要续约了,公司给我开的资薪是4.3K左右吧。总之,这三年就这么糊里糊涂的过去了,一个人赚一个人花。也没什么职业规划,如果重新来过,我想对新人说,真的需要做好你自己的人生规划,不是职业规划,是彻底做好人生规划,当然,好多人是很早就领悟了,我是一个后知后觉的人,领悟什么东西都很慢,但我只能是慢慢的去做,慢慢去领悟。
7年程序员,脚印.
.。。。原来是新帖
三年合同期满,和公司续约2年,这个在IT行业估计很少见了,在一家软件公司做这么多年,有些比我早进公司的同事,当时世道好,听说很多都5K以上工资了,就算是早进一年,有些比我后进一年的,也敢和公司要5K,要不就辞职走人,当时5K,确实是一个不错的价格了。当然不要用2012年之后的价格来比。当然,有人达到要求,有人确实是走人了。而我还是默默接受,默默工作。慢慢从一个程序员,到项目负责人,从写代码,到见客户,搞需求,写分析,开演示会议,慢慢的这几年我都走过来了,基本上除了招标文件,一个项目的流程我算是走过了一遍,也是最辛苦的一遍。我不知道那些拿着高薪,或者到其他公司拿着高薪的前同事发展怎么样,只是有时候吃饭的时候听到说,谁谁不做这个行业了,要转行了,然后过几年身边不少同事也转行了。而我还是默默在做,做到这个软件行业的每一个细节,包括拿着标书去招标,还做了很少涉及的监理。到了在这家公司的第7个年头,我才发现,我好像长大了,真的,这种感觉是从来没有过的舒畅,因为整个软件项目工程的所有工作,我都做过了一遍,和客户接触多了,见识也多了,思维也开始活跃了。7年之痒,合同到期后,又是续约。这次我从5.3K,直接要价7k。但是一些所谓的领导觉得,加10%已经很高了,经济开始不景气,公司业绩又不好。总之就是不可能到7K了。不到就算了,反正我不是爱争辩的人,就这样先签了合同5.8K。然后投了一份简历到广州的一个同学所在的公司,因为他们招聘现场维护高级工程师,打听了口风,开8K没问题。于是就去面试了,港企,从面试开始就明显感觉到外企(台企不算,这个有机会说说)对人的尊重,带薪年假(10天起算,就算国家规定5天,很多公司都改了,但是他们还是按照自己一套福利)。这个确实是之前这家公司没得比的(是沪企,在广东的分公司规模还可以)。由于福利太好了,又担心开8k谈不下去,于是在工资一栏填写了7.5K。可能我太过小心了。最后人事经理问我7K行不行,我已经降了,所以就咬定7.5k。一个高工,7.5K,在广州不知道什么概念,人事经理只是循例问问,就说可以了,当然我心里还是怕她觉得我开高价了。就这样,敲定了一份7.5K的工作,回去旧公司递交了辞职信。当然我也很感恩公司这6、7年给我的工作机会,没有这几年的磨练和经历,也不可能有其他公司看上你,因为人家看上你的就是你的工作经验。但是做了7年才6K不到,这也是我走的最终原因,如果当时他开7K给我,可能外面8K我都不会去,毕竟人是有感情的。
在新公司开始了第一年的维护工作,一年之后,该项目没了。不能在现场,需要回广州上班了。第二年,公司加工资,接近8K了。然后第三年再加工资大概接近8.5K吧。港企文化就是每年会加6%左右的工资,让员工抵御通货膨胀,但是,如果是8年前,这很好了,但是2010年之后,这种加幅对于我们的通货膨胀率来说,真的不足够,但是公司福利好,人员还算稳定吧,除了做了2年的程序员对工资不满意流动大,一般级别高的都很少流动。离开这家公司除了是工资很难往上涨之外,还有就是职位也很难往上升,就算是平移也不容易,因为太稳定了,早到的人已经占位了。还有一点就是社会太浮躁了,外面房价和物价的升幅,基本上把我工作差不多10年的工资涨幅给抹平了。这段时间物联网开始火了起来,有一家物流公司说和政府合作搞物联网之类的,当然主要是做项目给自家用。我开价12K。就这样工作10年,终于过万了。我还记得当年刚工作时的QQ签名:高辛工作,月入过慢。在最近这2年,很多小企业,创业型企业找我做项目经理,技术总监之类的工作,职位名字倒是吓人,谈的时候说得好像明天自己就是下一个淘宝,下一个腾讯,资金后台有多牛B,但是一谈到工资待遇,听到超过10K都面有难色。就算有些后来实在找不到人的,给我来电说,这次肯定过万了,我也只是笑笑,没理他了。心态忽然平和好多。现在也离开当时给我过万工资的企业了。休息一段时间后,还是在软件行业做技术经理,管理一个技术部门,手下几个项目经理,月薪15k。工资高吗?不算高,不算很低,反正不是很忙,我能够接受,因为,现在确实不能够每晚都加班了,超过10点半需要睡觉了,工资以后可能还会高,但是身体没了就没了,人活着并不是为了工资。
自言自语的说了这么多,竟然有两个广告,记得05、06年之前的帖子不到10层楼,估计广告都不屑一顾。有一段时间,广告是检验帖子的唯一标准,扯远了,看来生意确实不好做啊,谢谢以上几位朋友的光顾了。
我不知道还能坚持多久,所以有空就写写代码,或者想想项目,当然,都是为自己写的,因为10年过去了,我终于明白了什么是人生规划。就算企业开20K给你,可能身体上也是吃不消的。先想好以后的路怎样走下去,等待机会吧,虽然我一直缺少运气,估计也不会等到贵人相助,只能自救了,或者下一个10年再回首的时候,我现在的手下都转行了,希望我还在坚持吧。可能到时候值钱的并不是我做了多少年,写了多少代码,有多少行业的软件项目经验,而是我经历了20年IT行业发展历程,看遍了各种兴衰。20年可能很短,但是对于IT行业来说,可能就真的算得上是一个历史了。给自己一个目标,如果10年后还在这个行业,到时候再来吹吹牛皮。接下来说说这些年本狮子对这个行业的一些看法吧,算是自己的一些体会。接触过好多创业型的老总,都是头脑发热,想赚快钱,以为搞软件,搞平台,搞运营很赚钱,然后一头钻进去,然后很多都是亏得一塌糊涂。然后就销声匿迹,然后继续又有一批后起之秀崛起,做移动互联网,做手机APP,物联网,不亦乐乎。就这样热点过去一个又一个,时代不停更新换代,可能不变的就是此时此刻的心情吧。IT虽然说是产生奇迹的地方,除非有新的模式,新的技术,否则想在里面分一杯羹,其实也和其他行业差不多,可能比其他行业机会还要小,因为这个本身就是一个很烧钱的行业。看看滴滴和快滴为了抢占市场数以亿计地烧。不过就算有大财团持续给你烧钱,成功也并不是一定的,因为抢占用户这东西,不是说烧钱就可以了,很多东西大家用习惯了,除非有利可图,否则谁都不会不用QQ跑去用其他即时通讯软件。但是你总不能烧钱吧,当你一停止烧钱,用户可能马上就负增长了。接下来就乱吹一通吧,有人看再决定说些什么,不知道是否有人想了解软件这个行业的吗,这里除了加班,除了没MM,其实还有很多梦想的。
我写程序有三年多了,人比较浮躁,感觉写程序发不了财,现在一边写程序一边搞实体生意,等生意稳定了就转行,看到你做了这么年,很是佩服,坚持也许也能成功,但是很多人更喜欢走捷径
楼主应该是安分且容易满足的人,IT就是要跳槽,往大企业跳
我写程序有三年多了,人比较浮躁,感觉写程序发不了财,现在一边写程序一边搞实体生意,等生意稳定了就转行,看到你做了这么年,很是佩服,坚持也许也能成功,但是很多人更喜欢走捷径===========================================================================浮躁确实不适合做程序。写程序不能发财,所以还是需要自己找出路,在公司我不写程序了,但是下班我还是会写,把自己的想法、觉得有机会的一些软件构思,写出来,看是不是一条出路吧,实体确实也难,这么多年,实体,我已经回不去了,再也回不去了,现在只能是向马云同志学习了。
楼主应该是安分且容易满足的人,IT就是要跳槽,往大企业跳=====================================================================愿闻其详,我也想不停的跳,先把头衔搞大一点,把工资平台再提高一点,希望有一天会能跳出个百万年薪。不过如何实现,是否需要贵人相助?心里没底,在这里抛砖引玉了,如果有老狮子走过这条路,希望指点指点。
很多老板上网见到别人运营的项目或者网站都有的功能,他以为很容易就可以拿过来实现,然后依瓢画葫芦,到最后整个项目延期,或者失败了,才发现原来这样不行,还是需要请个懂的人回来协助管理,这还是算清醒的,有些死不认错的,只认为是大家做得不好,到最后只能是把自己做死,公司关门了事。我遇到过一个老总,都是其他行业赚了好多钱,开分公司,搞软件,搞运营。招10个攻城狮,两个个项目经理就开干。前期半年投资50多万,其他费用不清楚不说,单单说软件项目的投资,时间到,结果项目经理还是拿不出能够运行的项目出来。他马上就跳起来,老子都投那么多钱了,竟然泡都不冒一个,确实,软件行业就是这样,不得道,不要说泡,屁可能都没一个。一个软件不是你看见别人那样做可以赚钱,自己按照葫芦画瓢,山寨一个就可以的,有些行业业务的处理,精细到数据库的设计、程序架构的设计、导致你事务的处理等等都需要对该行业的了解,就算你画一个淘宝出来,可能一运行,每隔几天页面都可能会不定时的报错,安全性先不说,单单是保证每个页面,每个按钮点击都不报错,这已经很了不起了,这并不是你请10几个人就能够搞掂的。除了程序设计,测试也是一个过不去的坎。很多年轻的项目经理,一看业务逻辑,拍着胸口说,3个月基本搞定。基本搞定?那是搞定还是搞不定?我记得刚出来搞需求的时候,公司严格要求,不要和客户说基本这个字眼,能做好就说能做好,不够时间做好就说不行,需要多长时间等等。基本这个词基本上是等于搞不定。所以很多老总放了几十万前期,时间一到,问项目负责人,负责人就说,当初想不到这个业务逻辑的复杂性,没想到里面还有这么多系需要考虑,设计还需要修改一下,可能还需要3个月。天啊,如果你是老总,听到这样的话,你怎么想?以前刚开始说的软件工程就好像是建一栋大楼,需要规划,需要设计,需要打好基础(软件架构、数据库设计等)。就算后期修改了,最起码不能够动最根本的东西(地基打好了,不是说想盖多少层就盖多少层的)。但是到今天,发现软件工程就好像是园林设计,需要不停的修剪,当你剪出一匹马,客户可能会说,原来我想要的是一只牛,你只能再次修剪,当牛快要成型了,开完会,客户说,还是改成羊吧。到最后实在剪不下去了,客户可能说,那就先修剪成一只鸭吧。吐血了吧?刚开始以为编程序很困难,到后来发现做设计才是重点,接触客户了,才发现原来需求才是一道坎,正所谓:为系统而生,为框架而死,为bug奋斗一辈子! 下联:吃符号的亏,上大小写的当,最后死在需求上。
当攻城狮们日夜加班,终于完成所有功能,拿给客户一看。客户大骂,这根本不是我想要的! 攻城狮只能是大骂做设计的:我们这么辛苦,你是怎么设计的,做出来了,才说不是这样,设计要修改? 做设计的只能大骂做需求调研的:妈的,什么烂需求,我当时可是按照你的需求说明书去设计,明明是这样子的。最后做需求的只能是骂销售了:这能怪我吗?当时做需求的时候已经说好的,那销售为了签合同,竟然额外答应客户这么要求,这个我怎么解决? 销售业在那里大骂:老子起早贪黑,喝得胃出血,才能把合同拿下,你们这班整天坐在空调房间的高材生竟然一点都不体谅,竟然拿出这么烂的系统给客户。怎么做事情的,不就答应客户加多点功能而已,这都搞不定。我要是签不到合同,大家都喝西北风。一个循环下来,谁都有难处,谁都有道理。如果领导是外行的,不是干软件工程出身的,那么他就不了解这个行业的特性,有些领导知道自己不熟悉,就会给熟悉的人处理,如果遇上啥事都要管的领导,而又不能够公平处事的,那么大家都自求多福吧,因为他一管,肯定带上自己的角度去看问题,不知道怎样打破这个循环,不知道从哪里入手才能正式解决问题。最后的结果最差的是,项目不做,解散团队。比较差的是找另外项目继续做下去,如果领导有点实力的,只能是出面摆平客户了,项目延期继续搞下去。 这种情况,估计做了多年的老狮子深有体会了。如何带好一个团队?如何让大家都理解别人的难处?如何处理好出现的问题?都是很多搞软件老板面对的问题,所以总是有技术经理、技术总监、部门经理等等很多听起来不一样,其实工作内容差不多的职位,总的来说,就是需要你管理好整个部门的技术架构,分配好项目经理干活,处理好各种可能出现的问题等等。
处理客户团队问题、客户问题,领导可能还会站在你的角度考虑,或者帮你出面摆平。但是如果老总有问题,那可真是考验你的智商、情商了。之前的老总要做一个类似百度文库之类的系统,搞好了,他觉得自动生成方面有点慢,也不象百度那样好用,有些文档格式也不能自动转换,他就打开百度文库,指着说,我就要你们做成这样子,不用自己想,照抄就是。为什么不行呢?天啊,这可怎么解释,需要老总明白我们投入的人力、资金远远不能和百度相提并论,公司的服务器运行的速度和百度能比吗?人家投入多少人力资源去做一个文库,况且百度每天还投入多少资金去维护,投入多少人员在后台做前期准备工作包括资料的收集、格式的转换等。 当然以上我是明白,但是老总不明白,他以为点一下按钮就可以实现的东西为什么做起来就这么复杂。只能是用最平和的语言,最容易理解的例子去让他明白。如果实在是不讲理的领导,只能尽人事了,听天命。举例子、打比喻,说就容易,能把人说明白就不容易。没做程序员之前以为数学要牛B才行,现在看来一个优秀的软件攻城狮,需要好的文学功底和演讲技巧,当然好的逻辑是必需的。
信息化不是自动化。这个是很多客户,甚至是程序员有时都搞不清的。
不错,写的很好曾经也是个码农
真冷清,看来月薪没有几十k,是不能在经坛混啊。大家来都是想赚快钱,这种十几年磨一剑,一步一脚印的做法是否有点落后呢。有时我都在反省。
10年前说信息化系统,现在都开始说移动互联网了,感觉还是很多客户不知道啥事信息化,特别是一些国企的和政府的人员,跟他们打了10年交道,但是不要以为私企的就很好,私企的一些人素质更低,有时候可能连电脑都不一定会弄,这个确实是这个社会的现象。有时候和他们打交道,更加不讲道理,这个只是一定比例,当然也有很牛逼的人在私企混得很不错。又扯远了。言归正传,当年,甚至是现在,说到信息化,大部分客户以为就是用电脑办公,并且工作量还不能比我拿笔和纸的时候要多,最极端的,见过一个客户对我说:不是按一下按钮就可以把工作做好了吗?要输入这么多数据?你们收了几百万项目款,就不能一个按钮给我搞定?还要我打字?我哪会打字,唉,天啊,这就是做软件工程的悲哀。如果客户电脑不能开机,不能上网,反正啥不行,他们都会叫你过去,然后说:什么,你们不是修电脑的吗?难道你们连些简单的东西都搞不定吧?简直是目瞪口呆。
信息化不是自动化,信息化系统不一定能够减轻每个人的工作量,有些客户觉得,当年我拿个笔对着本子打钩,比在电脑上输入快多了,一些窗口申请书的填写,申请方填完,还需要我们录入电脑多麻烦,以前盖个章留个底就可以了,电脑就不能够点个按钮把这些东西都完成?这是很多在开始信息化过程中遇到的一些问题。问题虽然很小,但是也能够看出很多人对信息化的一些误解,以为上电脑了,喝茶的时间就多了。电脑其实没那么智能化和自动化,那么我们为什么还需要行业软件呢?试想一下,如果你每天在本子打钩,虽然很快,如果我让你找出10年前、8年前、6年前某个月,或者某日的记录,你是否需要翻箱倒柜的找你的本子呢?如果需要把某些记录形成报表给某些人查看,你是否需要日夜加班找好文件去搞报表呢?如果很多东西只是留个纸质文件底,不录入电脑,那么要查找某年某月某日某人是否申请过,那么估计你需要在档案室里面呆上一天,如果找一个人还好,如果上面需要你找100个,1000个人的资料,这时候你就会想,如果可以输入名字点击按钮就出来,那多好啊。这么说,估计大家都能够明白什么是信息化了吧,为什么做软件绕不开数据库,因为数据库才是核心,软件只是把你日常的办公流程放电脑上,最终目的是更好的收集数据,以达到数据共享,查看、统计、归档、历史统计等等以前需要大量人员完成的工作。所以办公软件,行业软件可能并不够智能,但是在收集好数据后,确实能带来实实在在的信息,这些信息可能对录入的人没有任何用处,也会增加某些数据收集人的工作量,但是却对整个企业,单位、团体的后续发展和工作分析带来好处。所以就不难理解,为什么领导对企业、单位上信息化系统一般都支持,这个是因为他们确实看到大信息量数据带来分析的好处,也可以使他们对整个企业的数据分析,后续的发展规划带来数据支持。确实,如果你是最前线的数据录入人员,可能觉得这种信息化系统没啥好处,只能使你工作量增加了,因为你根本体会不到,后期做报表人员的辛苦,体会不到老板经常看到错误统计数据的苦恼。
大家还在看&figure&&img src=&https://pic3.zhimg.com/v2-b96b80b37d1d20faf5a36_b.jpg& data-rawwidth=&784& data-rawheight=&436& class=&origin_image zh-lightbox-thumb& width=&784& data-original=&https://pic3.zhimg.com/v2-b96b80b37d1d20faf5a36_r.jpg&&&/figure&&p&今天来讲讲推送这件小事,事虽小,要做好却不容易。&/p&&blockquote&&p&推送难,难于上青天。&/p&&/blockquote&&p&我们在讨论 Android 手机上的推送时,大多数情况是在说集成第三方推送,因为即使是像微信这样的大厂,也需要厂商加到启动白名单里才能保持在线。&/p&&p&iOS 手机使用 &b&APNs(&/b&Apple Push Notification service)进行推送,而 Android 手机,也是有 &b&GCM&/b&(Google Cloud Messaging)作为 Google 官方的推送支持的,但是在国内需要翻墙才能使用,并且需要手机安装了 Google Service ,条件比较苛刻。&/p&&p&这样一来,国产手机的推送就成了个问题,也带了机会。&/p&&p&微信由于有国际版,将 GCM 作为辅助公共通道,但仅用于激活微信自己的 Push 通道,并没有通过 GCM 来传递数据,这点也是为了复用心跳的优化策略和数据处理逻辑。&/p&&p&GCM 最新版本叫 &b&FCM&/b&(Firebase Cloud Messaging)&/p&&h3&&b&推送的实现方式&/b&&/h3&&p&总结一下几种推送实现方式,其中有些我们只要了解即可,因为属于历史解决方案,现在已经被废弃掉了。&/p&&p&&strong&1. 轮询&/strong&&/p&&p&客户端定期询问服务器有没有新的消息,这种方式最大的缺点就是&strong&性能&/strong&和&strong&实时性&/strong&的矛盾,轮询时间过长和过短都不好。&/p&&p&&strong&2. 短信&/strong&&/p&&p&这种方式还没出生就不被允许了,首先运营商不会配合,其次拦截手机短信本身就是一个高危权限,大多数用户不会买单。&/p&&p&&strong&3. 长连&/strong&&/p&&p&目前最通用的方案,客户端与服务端建立 TCP 长连,定时发送心跳包保活,有新消息时服务端通过该长连通道进行推送。&/p&&p&这里再简单说明一下长连和心跳包。&/p&&p&&strong&长连接&/strong&就是建立连接之后,双方互相发送数据,,发完了也不主动断开连接。&/p&&p&但是在某些情况下长连会断开,问题就在断开这件事上,而且这件事必须是由客户端知道,因为客户端是可以重连服务器的,服务器却没法再联系上客户端。这样才确定了&strong&心跳包&/strong&必须由客户端发给服务器。所以心跳包的作用就是告诉服务端客户端还活着,如果服务端挂了,客户端能知道,所以&strong&保活&/strong&说的是保持两边都活着。&/p&&p&上面说的某些情况中, &strong&NAT 超时&/strong&算是一个典型的例子。&/p&&p&因为 IPv4 的 IP 量有限,运营商分配给手机终端的 IP 是运营商内网的 IP,手机要连接 Internet ,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机可以跟 Internet 的服务器通讯。大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断。所以长连接心跳间隔必须要&strong&小于&/strong& NAT 超时时间(aging-time),如果超过老化时间不做心跳, TCP 长连接链路就会中断,服务器就无法发消息给客户端,只能等到客户端下次心跳失败后,重建连接才能取到消息。&/p&&p&有了长连,即使在休眠模式下,有推送消息过来,也能唤醒 Android 系统,这是由系统机制决定的,我们这里只要知道结论就好。&/p&&p&想要了解更多的可以去看文末的&b&参考资料&/b&。&/p&&h3&&b&推送的指标&/b&&/h3&&p&在接入推送服务时有几个核心指标需要考量:&/p&&p&&strong&1. 在线率&/strong&&/p&&p&在线率 = 在线用户数 / 总用户数&/p&&p&推送服务后台保持在线的方法&/p&&ul&&li&Push 进程常驻后台,需要用户手动让应用常驻&/li&&li&共享连接通道的方式,比如极光或者个推,通过共享连接,当应用有推送到达时,唤起该应用&/li&&/ul&&p&显然,后者在体验上更加接近 GCM 。&/p&&p&&strong&2. 到达率&/strong&&/p&&p&到达率 = 实际到达数 / 目标用户数&/p&&p&在线数 -& 目标用户数 -& 成功下发数,如果后端的计算或调用出现问题这两个数据就会不准确&/p&&p&在线数 -& 实际到达数 -& 展示数,数据收到后,是否展示要看用户有没有打开该应用的允许通知的开关,可以通过如下方法判断&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&notificationManagerCompat.areNotificationsEnabled();
&/code&&/pre&&/div&&p&&strong&3. 耗电量&/strong&&/p&&p&耗电量受到很多方面的影响,如果收到推送比较多,打开应用比较频繁,耗电量自然也会上去不少,但这个用户是可以接受的。以下几个耗电量的因素用户是比较反感的:&/p&&ul&&li&应用间互相唤醒产生的耗电,因为这个耗电是别的应用的,用户本来没有意图要去打开&/li&&li&错误重试造成的耗电,重试策略的优化包括重试时间的累加和重置&/li&&/ul&&h3&&b&推送选型&/b&&/h3&&p&上面提到,我们这里聊的推送,是&strong&第三方推送&/strong&,那有开发者要问了,为什么不自己做推送?自己做不是不行,但需要考虑几个问题:&/p&&ul&&li&开发成本问题, ROI 是否可以接受&/li&&li&如果不加入白名单,那么一旦应用被彻底杀掉,是没人给你吟唱复活魔法(&strong&互相唤起&/strong&)的&/li&&/ul&&p&第三方推送主要有厂商推送和非厂商推送&/p&&ul&&li&华为、小米、魅族推送&/li&&li&个推、极光、友盟&/li&&li&阿里、腾讯、百度&/li&&/ul&&p&其中,选型的几个因素&/p&&ul&&li&厂商推送&strong&通知&/strong&是否系统通道(所有厂商支持)&/li&&li&厂商推送&strong&透传&/strong&是否系统通道(仅魅族)&/li&&li&非厂商推送的市场占有率(影响共享连接&strong&互相唤起&/strong&的概率)&/li&&/ul&&p&如何在 Android 手机中查看某个应用使用的是什么推送?&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&adb shell dumpsys activity services | grep igexin
&/code&&/pre&&/div&&figure&&img src=&https://pic1.zhimg.com/v2-a658c8ae5f28dac28cb4_b.jpg& data-rawwidth=&1332& data-rawheight=&686& class=&origin_image zh-lightbox-thumb& width=&1332& data-original=&https://pic1.zhimg.com/v2-a658c8ae5f28dac28cb4_r.jpg&&&/figure&&p&可以看到,这几个应用都在使用个推&/p&&p&大众点评、宝宝树、饿了么、滴滴、简书、领英、 WPS Office 、格瓦拉。&/p&&h3&&b&推送接入&/b&&/h3&&p&&b&如何解耦&/b&&/p&&p&由于各个推送 sdk 接口定义不同,为了减少耦合,我们采用多 &strong&module&/strong& 的形式进行接入。&/p&&ul&&li&app&/li&&li&jikepush&ul&&li&PushServiceImpl&/li&&/ul&&/li&&li&push_厂商1&ul&&li&PushPlatformImpl&/li&&/ul&&/li&&li&push_厂商2&ul&&li&PushPlatformImpl&/li&&/ul&&/li&&li&push_非厂商&ul&&li&PushPlatformImpl&/li&&/ul&&/li&&li&jikecore&ul&&li&PushService&/li&&li&PushPlatform&/li&&/ul&&/li&&/ul&&p&在 app 层通过注册的方式添加需要的 &strong&PushPlatform&/strong& ,之后通过 &strong&PushService&/strong& 接口来进行调用,具体的启动和切换的实现放在 PushServiceImpl 。&/p&&p&其实大部分推送平台的接口标准都差不多,无非是命名上有差异,所以我们用 PushPlatform 这个接口来屏蔽这种差异。&/p&&p&对于推送启动和切换的操作,放在 PushService 中。&/p&&p&当启动某一个推送服务的时候,就关掉其他的推送服务,后台始终只保持一个推送服务。&/p&&p&&b&registeration id&/b&&/p&&p&通常我们启动一个推送服务后,会收到一个 registeration id(以下简称 reg id),用这个 reg id 和我们自己的服务器进行绑定。&/p&&p&这里有个需要注意的地方,绑定的操作我们需要调用2次。&/p&&ul&&li&after PushService.start() 因为已经接收到 reg id 后&strong&有些推送不再触发&/strong& receive reg id&/li&&li&after receive reg id &strong&首次&/strong&启动推送是&strong&异步&/strong&收到 reg id 的&/li&&/ul&&p&收到 reg id 之后,&strong&推送 sdk&/strong& 会自己保存下来以便下次使用,但有时候我们使用 sdk 的方法获取的时候无法获取到,究其原因是 reg id 的保存不是我们自己做的,因此, reg id 这么重要的东西我们自己也要存。&/p&&p&&b&推送需要的系统权限&/b&&/p&&p&推送 sdk 需要获取手机的 imei 号作为合成 reg id 的必要元素,需要以下两个权限&/p&&ul&&li&Manifest.permission.READ_PHONE_STATE &/li&&li&Manifest.permission.WRITE_EXTERNAL_STORAGE&/li&&/ul&&p&启动推送服务的时候需要判断权限。&/p&&p&&b&推送的切换策略&/b&&/p&&p&建议选择手机 &strong&rom&/strong& 而非手机型号作为切换条件,这样可以解决部分用户刷机的问题,比如 Nexus 手机刷了个 MIUI 的情况。&/p&&p&获取到 rom 信息后,有3种推送切换策略&/p&&p&&i&策略一&/i&&/p&&p&客户端根据 rom 信息自动选择使用哪个推送&/p&&ul&&li&优点:无后端工作量,不需要切换&/li&&li&缺点:一旦某个推送挂了一天,无法临时切换到其他推送&/li&&/ul&&p&&i&策略二&/i&&/p&&p&客户端上报 rom 信息,后端选择使用哪个推送&/p&&ul&&li&优点:灵活切换推送&/li&&li&缺点:切换推送重新绑定 reg id 有个时间差&/li&&/ul&&p&&i&策略三&/i&&/p&&p&使用推送 sdk 自己的集成方案,当 sdk 自己的推送服务离线时,切换到厂商推送&/p&&ul&&li&优点:最大程度保证推送的稳定性&/li&&li&缺点:集成方案本身的不稳定性影响了推送的稳定性&/li&&/ul&&p&&b&推送类型&/b&&/p&&p&推送类型分为通知和透传&/p&&p&&i&通知&/i&&/p&&ul&&li&厂商到达率有优势&/li&&li&开发成本较高,需要适配不同厂商的接口标准&/li&&/ul&&p&&i&透传&/i&&/p&&ul&&li&可以自己解析、展示、跳转,灵活性高&/li&&li&开发成本较低,适配一次就够(通常通过 json )&/li&&li&一些厂商的透传到达率没有厂商优势&/li&&/ul&&p&&b&集成方式&/b&&/p&&p&一般我们集成推送 sdk 有两种集成方式&/p&&ul&&li&maven 集成&/li&&li&手动集成&/li&&/ul&&p&从维护的角度来说, maven 集成的维护成本要小于手动集成,但是我这里还是推荐手动集成,主要有以下几个原因。&/p&&p&maven 集成的方式通常 sdk 会要求使用 manifest placeholder 的方式进行 appid appkey appsecret 的注入,但是这种方式需要在 app 层的 build.gradle 去注入,比较耦合。&/p&&p&maven 集成还有一个缺点,准确来说这是 sdk 开发商的问题,总会打包一些我们不需要的资源文件,其实我只需要一个 jar 包而已,并不是整个 aar 啊。&/p&&p&手动集成第一次写 manifest 比较麻烦,但是后面只要替换 jar 和 so 文件就好了,因为 manifest 一般不经常变化,除非有重大版本更新。&/p&&h3&&b&推送的展示&/b&&/h3&&p&接下来就要说说通知 &strong&Notification&/strong& 了,这个东西经过厂商的各种定制,适配起来也有不少麻烦。&/p&&p&&b&厂商的推送样式差异&/b&&/p&&p&部分厂商&/p&&ul&&li&不支持 &strong&NotificationCompat.BigTextStyle&/strong& (这都能不支持)&/li&&li&不支持 &strong&NotificationCompat.MediaStyle&/strong& (这个还可以理解)&/li&&li&不支持 &strong&Action Button&/strong&&/li&&li&不支持 &strong&Ticker&/strong&&/li&&li&自定义样式&strong&高度限制&/strong&&/li&&/ul&&p&&b&原生系统 Android 版本的推送样式差异&/b&&/p&&ul&&li&&strong&4.x&/strong& large icon 需要是方的&/li&&li&&strong&5.x 6.x&/strong& 由 &strong&setColor&/strong& 设置底色和 &strong&small icon&/strong& 配合形成 large icon&/li&&li&&strong&7.x &/strong&&strong&setColor&/strong& 影响标题颜色&/li&&/ul&&p&&b&通知的跳转&/b&&/p&&ul&&li&&i&透传:&/i&采用 &strong&Url&/strong& 方式进行跳转&/li&&li&&i&通知:&/i&采用 &strong&Intent&/strong& 参数的方式进行跳转&/li&&/ul&&p&推送这件小事就说到这里了。&/p&&h2&&b&展望未来&/b&&/h2&&p&最近,由&strong&泰尔实验室&/strong&牵头的安卓统一推送研讨会正在进行中,&strong&即刻&/strong&上有一个&strong&“&a href=&https://link.zhihu.com/?target=http%3A//m.ruguoapp.com/topics/58c0be0acb018e%3Fusername%3D069C7356-DD07-41AA-BB6D-06021FFF2E4D& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&安卓推送服务统一进展&/a&”&/strong&的提醒,我们一起关注安卓推送生态的变化吧。&/p&&blockquote&&p&用一句广告语描述厂商和 app 的相爱相杀:你好,我也好。&/p&&/blockquote&&h3&&b&参考资料&/b&&/h3&&p&&a href=&https://link.zhihu.com/?target=http%3A//www.jianshu.com/p/ed7& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Android推送技术研究&/a&&/p&&p&&a href=&https://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzAwNDY1ODY2OQ%3D%3D%26mid%3Didx%3D1%26sn%3D4ebe4bebab594& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Android微信智能心跳方案&/a&&/p&&br&
今天来讲讲推送这件小事,事虽小,要做好却不容易。推送难,难于上青天。我们在讨论 Android 手机上的推送时,大多数情况是在说集成第三方推送,因为即使是像微信这样的大厂,也需要厂商加到启动白名单里才能保持在线。iOS 手机使用 APNs(Apple Push Notif…
&h4&先看看这些程序员技能树,你掌握或了解哪些?OMG竟然有么多~~~震精!震精!!!&/h4&&figure&&img src=&http://pic1.zhimg.com/v2-553ea2ead3eb82e29e05c_b.png& data-rawwidth=&372& data-rawheight=&656& class=&content_image& width=&372&&&/figure&&figure&&img src=&http://pic2.zhimg.com/v2-94b5bbaa4f51_b.png& data-rawwidth=&370& data-rawheight=&815& class=&content_image& width=&370&&&/figure&&figure&&img src=&http://pic2.zhimg.com/v2-b6e8e017ea95_b.png& data-rawwidth=&370& data-rawheight=&706& class=&content_image& width=&370&&&/figure&&p&这是从450家企业的招聘信息中统计而来,相对来说还是比较真实的,虽然有些公司的招聘要求万年不变,但还是可以大致反应企业的招聘要求的。&/p&&p&尽管Struts2漏洞频出,但是由于政府、银行以及传统企业遗留项目大部分还是采用Struts2的,所以还是占有一定市场,但绝壁不会增长。新兴互联网公司,一般来说主要是Spring家族居多,spring、spring Mvc以及Spring Boot 出现的频率较多。&/p&&p&从图中可以看出,分布式服务框架应用也是大部分企业招聘的必要条件了,阿里系的Dubbo名列前茅。相应的分布式应用程序协调服Zookeeper也出现在其中。&/p&&p&时下很流行的RESTful架构,准确的来说它是一种标准。也是很多企业考察的对象。&/p&&p&以下是出现次数超过100的一些技能,大家可以做一个参考。&/p&&blockquote&&p&Spring 299 &br&MySQL 290 &br&JavaScript 216&br&Linux 165&br&J2EE 151&br&设计模式 148&br&Struts2 138&br&Hibernate 132&br&Mybatis 130&br&jQuery 128&br&HTML 127&br&TOMCAT 117&br&iBatis 103&br&CSS 103&br&redis 102&br&多线程 102&br&dubbo 47 (绝壁不是打酱油的)&/p&&/blockquote&&p&相信每个程序员、或者说每个工作者都应该有自己的职业规划,问一下自己对编程到底持有的是一种什么样的态度,是够用就好呢还是不断研究?&/p&&p&小编对问题中的答案进行了精选,姿势准备好大图如下:&/p&&p&&b&社区昵称 似水的流年 的精彩回答:&/b&&/p&&p&java,php。这些排第一的除了还没用分布式的框架,其他的都在用,还是linux大法好&br&&/p&&figure&&img src=&http://pic4.zhimg.com/v2-75bd236c4cc_b.jpg& data-rawwidth=&1024& data-rawheight=&644& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&http://pic4.zhimg.com/v2-75bd236c4cc_r.jpg&&&/figure&&br&&p&&figure&&img src=&http://pic1.zhimg.com/v2-5969dbd3f6f8bf524d06da2aa98b5970_b.png& data-rawwidth=&2220& data-rawheight=&10114& class=&origin_image zh-lightbox-thumb& width=&2220& data-original=&http://pic1.zhimg.com/v2-5969dbd3f6f8bf524d06da2aa98b5970_r.png&&&/figure&&b&社区昵称 &/b&&b&阿狸小狐&/b&&b& 的精彩回答:&/b&&br&&/p&&p&JAVA核心技术总结&br&&/p&&figure&&img src=&http://pic3.zhimg.com/v2-554ecb1fd82f51a751f2_b.jpg& data-rawwidth=&1724& data-rawheight=&2328& class=&origin_image zh-lightbox-thumb& width=&1724& data-original=&http://pic3.zhimg.com/v2-554ecb1fd82f51a751f2_r.jpg&&&/figure&&p&J2EE技术总结&br&&/p&&figure&&img src=&http://pic1.zhimg.com/v2-0eabd97086bdcd76a57edccc4f7157e0_b.jpg& data-rawwidth=&1337& data-rawheight=&1603& class=&origin_image zh-lightbox-thumb& width=&1337& data-original=&http://pic1.zhimg.com/v2-0eabd97086bdcd76a57edccc4f7157e0_r.jpg&&&/figure&&p&工作和学习总结&br&&/p&&figure&&img src=&http://pic2.zhimg.com/v2-24df831f42bd20e721e50b5baa1b3361_b.jpg& data-rawwidth=&905& data-rawheight=&842& class=&origin_image zh-lightbox-thumb& width=&905& data-original=&http://pic2.zhimg.com/v2-24df831f42bd20e721e50b5baa1b3361_r.jpg&&&/figure&&p&大数据相关技术总结&br&&/p&&figure&&img src=&http://pic2.zhimg.com/v2-e800f8b1d226bcf71e3a6910204fdb19_b.jpg& data-rawwidth=&1057& data-rawheight=&729& class=&origin_image zh-lightbox-thumb& width=&1057& data-original=&http://pic2.zhimg.com/v2-e800f8b1d226bcf71e3a6910204fdb19_r.jpg&&&/figure&&p&&b&社区昵称 &/b&&b&happycc&/b&&b& 的精彩回答:&/b&&br&&/p&&p&正在使用的&/p&&p&Spring框架&br&Spring框架是一个分层架构,有7个定义良好的模块组成&br&spring模块构建在核心容器智之上, 核心容器定义了创建、 配置、和管理bean的方式&br&组成spring框架的每个模块(或组件)都可以单独存在, 或者与其他一个或多个模块联合实现&/p&&p&模块如下:&/p&&p&复制代码&br&1--核心容器&br&核心容器提供spring框架的基本功能,核心容器的主要组件是BeanFactory, 他是工厂模式的实现. &br&BeanFactory使用控制反转(IOC)模式将应用程序的配置和依赖性与实际的应用程序代码分开&/p&&p&2--Spring上下文&br&是一个配置文件,该配置文件向spring框架提供上下文信息&/p&&p&3--Spring AOP&br&通过配置管理特性,Spring AOP 模块直接将面向切面(方面)编程功能集成到spring框架中&/p&&p&4--spring DAO&br&JDBC DAO抽象层提供了有意义的已成层次结构, 可用该结构管理异常处理和不同数据库抛出的错误信息,极大的降低了异常代码数量&/p&&p&5--Spring ORM&br&spring框架插入了若干个ORM框架, 从而提供了ORM的对象工具,其中包括了Hibernate, Mybatis&/p&&p&6--Spring Web&br&web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供上下文&/p&&p&7--Spring MVC&br&该框架是一个全功能的构建web应用程序的MVC实现. 通过策略接口,MVC框架变成高度可配置的. MVC容纳了大量视图技术. 其中包括JSP、Velocity和POI&br&复制代码&br&Spring 框架的好处&/p&&p&spring是最大的工厂&br&spring负责业务逻辑组件的框架和生成, 并管理业务逻辑组件的生命周期&br&spring可以生产所有实例, 从控制器、 业务逻辑组件、 持久层组件&br&Spring特点&/p&&p&复制代码&br&1--降低了组件之间的耦合性, 实现了软件各个层之间的解耦&br&2--可以使用spring容器提供的服务, 如: 事务管理, 消息服务&br&3--容器提供单例模式支持&br&4--容器提供AOP技术, 利用它很容易实现权限拦截, 运行期监控&br&5--容器提供了众多的辅助类, 能加快应用的开发(org.springframework.jdbc.core.JDBCTemplate 等)&br&6--spring对主流的应用框架提供了集成支持, 例如: hibernate,JPA, Struts, Mybatis(IBatis)&br&7--Spring属于低侵入式设计, 代码污染度极低&br&8--独立于各种应用服务器&br&9--spring的DI机制降低了业务对象替换的复杂性&br&10--spring的高度开发性, 并不强制应用完全依赖于spring, 开发者可以自由选择spring的部分或者全部&/p&&br&&p&&b&社区昵称 小崽崽 的精彩回答:&/b&(小崽崽同学,你确定不是来拉仇恨的嘛?这是有关java的问答啊....这篇评论火了,可以点击链接查看:&a href=&http://link.zhihu.com/?target=https%3A//yq.aliyun.com/roundtable/50380& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&作为一名合格的JAVA程序员需要点亮那些技能树?-聚能聊-云栖社区-阿里云&/a&)&br&&/p&&p&PHP才是世界上最好的语言,看我大PHP技能树&br&&/p&&figure&&img src=&http://pic3.zhimg.com/v2-8a8f2ef56f6b687b0cb1b2ae_b.jpg& data-rawwidth=&813& data-rawheight=&895& class=&origin_image zh-lightbox-thumb& width=&813& data-original=&http://pic3.zhimg.com/v2-8a8f2ef56f6b687b0cb1b2ae_r.jpg&&&/figure&&br&&figure&&img src=&http://pic2.zhimg.com/v2-80cbe3f4e77f2aa0d4ff1511aaf3b179_b.png& data-rawwidth=&1396& data-rawheight=&3268& class=&origin_image zh-lightbox-thumb& width=&1396& data-original=&http://pic2.zhimg.com/v2-80cbe3f4e77f2aa0d4ff1511aaf3b179_r.png&&&/figure&&br&&h4&各位攻城狮们在评论中聊聊你们的看法&/h4&&h4&你所掌握的语言是什么?又是如何点亮自己的技能树的?&/h4&&h4&或是准备点亮哪些技能树?精彩评论可以获得云栖大会套装(2016款云栖大会纪念版T恤衫、纪念版金色徽章、纪念版帽子)&/h4&
先看看这些程序员技能树,你掌握或了解哪些?OMG竟然有么多~~~震精!震精!!!这是从450家企业的招聘信息中统计而来,相对来说还是比较真实的,虽然有些公司的招聘要求万年不变,但还是可以大致反应企业的招聘要求的。尽管Struts2漏洞频出,但是由于政…
&figure&&img src=&https://pic2.zhimg.com/v2-ecb6deb640a5a9daaf3bf_b.jpg& data-rawwidth=&1092& data-rawheight=&600& class=&origin_image zh-lightbox-thumb& width=&1092& data-original=&https://pic2.zhimg.com/v2-ecb6deb640a5a9daaf3bf_r.jpg&&&/figure&这篇论文 &a href=&https://link.zhihu.com/?target=https%3A//static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/45530.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Deep Neural Networks for YouTube Recommendations&/a& 是google的YouTube团队在推荐系统上DNN方面的尝试,发表在16年9月的RecSys会议。虽然去年读过,一方面因为这篇paper的来源于youtube团队的工业实践,G家的东西,非常值得好好研究下;另一方面,目前正在公司推进的项目对该论文有参考(both method and insight),也正准备在team内部分享下,因此整理下论文精读笔记。(PS:为方便阅读,下文以第一人称代替作者)&p&虽然国内必须翻墙才能登录YouTube,但想必大家都知道这个网站。基本上算是世界范围内视频领域的最大的网站了,坐拥10亿量级的用户,网站内的视频推荐自然是一个非常重要的功能。本文就focus在&b&&u&YouTube视频推荐的DNN算法,文中不但详细介绍了Youtube推荐算法和架构细节,还给了不少&/u&&/b&&b&&u&practical lessons and insights,很值得精读一番&/u&&/b&。下图便是YouTube APP视频推荐的一个例子。&/p&&p&&figure&&img src=&https://pic2.zhimg.com/v2-f03b9d3ac0cb6a7c5d9ababbdbaa68b7_b.jpg& data-rawwidth=&1028& data-rawheight=&878& class=&origin_image zh-lightbox-thumb& width=&1028& data-original=&https://pic2.zhimg.com/v2-f03b9d3ac0cb6a7c5d9ababbdbaa68b7_r.jpg&&&/figure&在推荐系统领域,特别是YouTube的所在视频推荐领域,主要面临三个挑战:&/p&&ul&&li&&b&规模大&/b&:用户和视频的数量都很大,只能适应小规模数据集的算法就不考虑了。&/li&&li&&b&更新快&/b&:youtube视频更新频率很高,每秒有小时级别的视频上传,需要在新发布视频和已有存量视频间进行balance。更新快(实时性)的另一方面的体现是用户实时行为切换很快,模型需要很好的追踪用户的实时行为。&/li&&li&&b&噪音&/b&:噪音主要体现在用户的历史行为往往是稀疏的并且是不完整的,并且没有一个明确的ground truth的满意度signal,我们面对的都是noisy implicit feedback signals。噪音另一个方面就是视频本身很多数据都是非结构化的。这两点对算法的鲁棒性提出了很高的挑战。&/li&&/ul&&p&之所以要在推荐系统中应用DNN解决问题,一个重要原因是google内部在机器学习问题上的通用solution的趋势正转移到Deep learning,系统实际部署在基于tensorflow的Google
Brain上。&/p&&br&&p&&b&一、系统概览&/b&&/p&&p&在工业界工作的同学对下图的系统划分并不陌生。整个推荐系统分为candidate generation(淘宝称为Matching,后面用Matching代替)和Ranking两个阶段。Matching阶段通过i2i/u2i/u2u/user profile等方式“粗糙”的召回候选商品,Matching阶段视频的数量是百级别了;Ranking阶段对Matching后的视频采用更精细的特征计算user-item之间的排序分,作为最终输出推荐结果的依据。&/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-533f102bd97b2b8cdf25639cfb0ab3e9_b.jpg& data-rawwidth=&910& data-rawheight=&686& class=&origin_image zh-lightbox-thumb& width=&910& data-original=&https://pic1.zhimg.com/v2-533f102bd97b2b8cdf25639cfb0ab3e9_r.jpg&&&/figure&之所以把推荐系统划分成Matching和Ranking两个阶段,主要是从性能方面考虑的。Matching阶段面临的是百万级视频,单个视频的性能开销必须很小;而Ranking阶段的算法则非常消耗资源,不可能对所有视频都算一遍,实际上即便资源充足也完全没有必要,因为往往来说通不过Matching粗选的视频,大部分在Ranking阶段排名也很低。接下来分别从Matching和Ranking阶段展开介绍。&/p&&br&&p&&b&二、Matching&/b&&/p&&p&&b&2.1 问题建模&/b&&/p&&p&我们把推荐问题建模成一个“超大规模多分类”问题。即在时刻&img src=&https://www.zhihu.com/equation?tex=t& alt=&t& eeimg=&1&&,为用户&img src=&https://www.zhihu.com/equation?tex=U& alt=&U& eeimg=&1&&(上下文信息&img src=&https://www.zhihu.com/equation?tex=C& alt=&C& eeimg=&1&&)在视频库&img src=&https://www.zhihu.com/equation?tex=V& alt=&V& eeimg=&1&&中精准的预测出视频&img src=&https://www.zhihu.com/equation?tex=i& alt=&i& eeimg=&1&&的类别(每个具体的视频视为一个类别,&img src=&https://www.zhihu.com/equation?tex=i& alt=&i& eeimg=&1&&即为一个类别),用数学公式表达如下:&/p&&p&&figure&&img src=&https://pic4.zhimg.com/v2-adde74b978b971e588ce0b_b.jpg& data-rawwidth=&1030& data-rawheight=&112& class=&origin_image zh-lightbox-thumb& width=&1030& data-original=&https://pic4.zhimg.com/v2-adde74b978b971e588ce0b_r.jpg&&&/figure&很显然上式为一个softmax多分类器的形式。向量&img src=&https://www.zhihu.com/equation?tex=u%5Cin+R%5EN& alt=&u\in R^N& eeimg=&1&&是&user, context&信息的高纬“embedding”,而向量&img src=&https://www.zhihu.com/equation?tex=v_%7Bj%7D%5Cin+R%5EN& alt=&v_{j}\in R^N& eeimg=&1&&则是视频 j 的embedding向量。所以DNN的目标就是在用户信息和上下文信息为输入条件下学习用户的embedding向量&img src=&https://www.zhihu.com/equation?tex=u& alt=&u& eeimg=&1&&。用公式表达DNN就是在拟合函数&img src=&https://www.zhihu.com/equation?tex=u+%3D+f_%7BDNN%7D%28user_info%2C+context_info%29& alt=&u = f_{DNN}(user_info, context_info)& eeimg=&1&&。&/p&&p&而这种超大规模分类问题上,至少要有几百万个类别,实际训练采用的是Negative Sampe,类似于word2vec的Skip-Gram方法,类似我专栏的第一篇文章 &a href=&https://zhuanlan.zhihu.com/p/?refer=deeplearning-surfing& class=&internal&&DNN论文分享 - Item2vec: Neural Item Embedding for Collaborative Filtering&/a& 的item-embedding用的方法。&/p&&br&&p&&b&2.2 模型架构&/b&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-7f97ddd46e3a54a5d64a_b.jpg& data-rawwidth=&1590& data-rawheight=&998& class=&origin_image zh-lightbox-thumb& width=&1590& data-original=&https://pic2.zhimg.com/v2-7f97ddd46e3a54a5d64a_r.jpg&&&/figure&整个模型架构是包含三个隐层的DNN结构。输入是用户浏览历史、搜索历史、人口统计学信息和其余上下文信息concat成的输入向量;输出分线上和离线训练两个部分。&br&&p&离线训练阶段输出层为softmax层,输出2.1公式表达的概率。而线上则直接利用user向量查询相关商品,最重要问题是在性能。我们利用类似局部敏感哈希(Locality Sensitive Hashing,不展开介绍了,感兴趣的同学可以读读这篇论文 &a href=&https://link.zhihu.com/?target=http%3A//papers.nips.cc/paper/2666-an-investigation-of-practical-approximate-nearest-neighbor-algorithms.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&An Investigation of Practical Approximate Nearest Neighbor Algorithms&/a&)的算法为用户提供最相关的N个视频。&/p&&p&&b&2.3 主要特征&/b&&br&&/p&&p&类似于word2vec的做法,每个视频都会被embedding到固定维度的向量中。用户的&b&&u&观看视频历史&/u&&/b&则是通过变长的视频序列表达,最终通过&b&&u&加权平均(可根据重要性和时间进行加权)&/u&&/b&得到固定维度的watch vector作为DNN的输入。&br&&/p&&p&&b&除历史观看视频外的其他signal:&/b&&/p&&p&其实熟悉Skip-Gram方法的同学很容易看出来,2.1把推荐问题定义为“超大规模多分类”问题的数学公式和word2vec的Skip-Gram方法的公式基本相同,所不同的是user_vec是通过DNN学习到的,而&u&&b&引入DNN的好处则是任意的连续特征和离散特征可以很容易添加到模型当中&/b&&/u&。同样的,推荐系统常用的矩阵分解方法虽然也能得到user_vec和item_vec,但同样是不能嵌入更多feature。&br&&/p&&p&主要特征:&/p&&ul&&li&&b&历史搜索query&/b&:把历史搜索的query分词后的token的embedding向量进行加权平均,能够反映用户的整体搜索历史状态&br&&/li&&li&&b&人口统计学信息&/b&:性别、年龄、地域等&/li&&li&&b&其他上下文信息&/b&:设备、登录状态等&/li&&/ul&&p&&u&&i&“Example Age” (视频上传时间)特征&/i&&/u&&/p&&p&视频网络的时效性是很重要的,每秒YouTube上都有大量新视频被上传,而对用户来讲,哪怕牺牲相关性代价,用户还是更倾向于更新的视频。当然我们不会单纯的因为一个视频新就直接推荐给用户。&/p&&p&因为机器学习系统在训练阶段都是利用过去的行为预估未来,因此通常对过去的行为有个隐式的bias。视频网站视频的分布是高度非静态(non-stationary)的,但我们的推荐系统产生的视频集合在视频的分布,基本上反映的是训练所取时间段的平均的观看喜好的视频。因此我们我们把样本的 “age” 作为一个feature加入模型训练中。从下图可以很清楚的看出,加入“example age” feature后和经验分布更为match。&figure&&img src=&https://pic2.zhimg.com/v2-83f523875baab074b340b6ccea2eba02_b.jpg& data-rawwidth=&992& data-rawheight=&594& class=&origin_image zh-lightbox-thumb& width=&992& data-original=&https://pic2.zhimg.com/v2-83f523875baab074b340b6ccea2eba02_r.jpg&&&/figure&&/p&&br&&p&&b&2.4 label and context selection&/b&&/p&&p&在有监督学习问题中,最重要的选择是label了,因为label决定了你做什么,决定了你的上限,而feature和model都是在逼近label。我们的几个设计如下:&/p&&ul&&li&&b&使用更广的数据源&/b&:不仅仅使用推荐场景的数据进行训练,其他场景比如搜索等的数据也要用到,这样也能为推荐场景提供一些explore。&/li&&li&&b&为每个用户生成固定数量训练样本&/b&:我们在实际中发现的一个practical lessons,如果为每个用户固定样本数量上限,平等的对待每个用户,避免loss被少数active用户domanate,能明显提升线上效果。&/li&&li&&b&抛弃序列信息&/b&:我们在实现时尝试的是去掉序列信息,对过去观看视频/历史搜索query的embedding向量进行加权平均。这点其实违反直觉,可能原因是模型对负反馈没有很好的建模。&/li&&li&&b&不对称的共同浏览(asymmetric co-watch)问题&/b&:所谓asymmetric co-watch值的是用户在浏览视频时候,往往都是序列式的,开始看一些比较流行的,逐渐找到细分的视频。下图所示图(a)是hled-out方式,利用&u&&b&上下文信息&/b&&/u&预估中间的一个视频;图(b)是predicting next watch的方式,则是利用&b&&u&上文信息&/u&&/b&,预估下一次浏览的视频。我们发现图(b)的方式在线上A/B test中表现更佳。&u&&i&而实际上,传统的协同过滤类的算法,都是隐含的采用图(a)的held-out方式,忽略了不对称的浏览模式。&/i&&/u&&/li&&/ul&&figure&&img src=&https://pic2.zhimg.com/v2-4cfa7addb31147_b.jpg& data-rawwidth=&1674& data-rawheight=&482& class=&origin_image zh-lightbox-thumb& width=&1674& data-original=&https://pic2.zhimg.com/v2-4cfa7addb31147_r.jpg&&&/figure&&p&&b&2.4 不同网络深度和特征的实验&/b&&/p&&p&简单介绍下我们的网络构建过程,采用的经典的“tower”模式搭建网络,基本同2.2所示的网络架构,所有的视频和search token都embedded到256维的向量中,开始input层直接全连接到256维的softmax层,依次增加网络深度(+512--&+1024--&+2048--& ...)。&/p&&br&&figure&&img src=&https://pic3.zhimg.com/v2-1da8c98bc45a4_b.jpg& data-rawwidth=&914& data-rawheight=&338& class=&origin_image zh-lightbox-thumb& width=&914& data-original=&https://pic3.zhimg.com/v2-1da8c98bc45a4_r.jpg&&&/figure&下图反映了不同网络深度(横坐标)下不同特征组合情况下的holdout-MAP(纵坐标)。可以很明显看出,增加了观看历史之外的特征很明显的提升了预测得准确率;从网络深度看,随着网络深度加大,预测准确率在提升,但继续增加第四层网络已经收益不大了。&br&&figure&&img src=&https://pic4.zhimg.com/v2-5b6bf21518fc5cfad04c1d0_b.jpg& data-rawwidth=&896& data-rawheight=&826& class=&origin_image zh-lightbox-thumb& width=&896& data-original=&https://pic4.zhimg.com/v2-5b6bf21518fc5cfad04c1d0_r.jpg&&&/figure&&p&&b&三、Ranking&/b&&/p&&p&Ranking阶段的最重要任务就是精准的预估用户对视频的喜好程度。不同于Matching阶段面临的是百万级的候选视频集,Ranking阶段面对的只是百级别的商品集,因此我们可以&u&&i&使用更多更精细的feature&/i&&/u&来刻画视频(item)以及用户与视频(user-item)的关系。比如用户可能很喜欢某个视频,但如果list页的用的“缩略图”选择不当,用户也许不会点击,等等。&/p&&p&此外,Matching阶段的来源往往很多,没法直接比较。Ranking阶段另一个关键的作用是能够把不同来源的数据进行有效的ensemble。&/p&&p&在目标的设定方面,单纯CTR指标是有迷惑性的,有些靠关键词吸引用户高点击的视频未必能够被播放。因此设定的目标基本与期望的观看时长相关,具体的目标调整则根据线上的A/B进行调整。&/p&&p&&b&3.1 模型架构&/b&&/p&&p&Ranking阶段的模型和Matching基本相似,不同的是training最后一层是一个weighted LR层,而serving阶段激励函数用的是&img src=&https://www.zhihu.com/equation?tex=e%5E%7Bx%7D+& alt=&e^{x} & eeimg=&1&&,具体在3.3阐述。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-33ff42f50e617e03ef659bd_b.jpg& data-rawwidth=&1560& data-rawheight=&804& class=&origin_image zh-lightbox-thumb& width=&1560& data-original=&https://pic4.zhimg.com/v2-33ff42f50e617e03ef659bd_r.jpg&&&/figure&&p&&b&3.2 特征表达&/b&&/p&&br&&p&&b&a). Feature Engineering:&/b&&/p&&p&尽管深度学习在图像、语音和NLP等场景都能实现end-to-end的训练,没有了人工特征工程工作。然而在搜索和推荐场景,我们的很难吧原始数据直接作为FNN的输入,&u&&i&特征工程仍然很重要&/i&&/u&。而特征工程中最难的是如何建模用户时序行为(&b&&i&temporal sequence of user actions&/i&&/b&),并且关联这些行为和要rank的item。&/p&&p&我们发现&b&&u&最重要的Signal是描述用户与商品本身或相似商品之间交互的Signal&/u&&/b&,这与Facebook在14年提出LR+GBDT模型的paper(&a href=&https://link.zhihu.com/?target=https%3A//pdfs.semanticscholar.org/daf9/ed5dc6c6bad6b8dd.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Practical Lessons from Predicting Clicks on Ads at Facebook&/a&)中得到的结论是一致的。比如我们要度量用户对视频的喜欢,可以考虑用户与视频所在频道间的关系:&/p&&ul&&li&&b&数量特征&/b&:浏览该频道的次数?&/li&&li&&b&时间特征&/b&:比如最近一次浏览该频道距离现在的时间?&/li&&/ul&&p&这两个连续特征的最大好处是具备非常强的泛化能力。另外除了这两个偏正向的特征,用户对于视频所在频道的一些PV但不点击的行为,即&b&负反馈Signal同样非常重要&/b&。&br&&/p&&br&&p&另外,我们还发现,把Matching阶段的信息传播到Ranking阶段同样能很好的提升效果,比如&u&推荐来源和所在来源的分数&/u&。&/p&&p&&b&b). Embedding Categorical Features&/b&&br&&/p&&p&NN更适合处理连续特征,因此&u&稀疏的特别是高基数空间的离散特征&/u&需要embedding到稠密的向量中。每个维度(比如query/user_id)都有独立的embedding空间,一般来说空间的维度基本与log(去重后值得数量)相当。实际并非为所有的id进行embedding,比如视频id,只需要按照点击排序,选择top N视频进行embedding,其余置为0向量。而对于像“过去点击的视频”这种multivalent特征,与Matching阶段的处理相同,进行加权平均即可。&/p&&p&另外一个值得注意的是,同维度不同feature采用的相同ID的embedding是共享的(比如“过去浏览的视频id” “seed视频id”),这样可以大大加速训练,但显然输入层仍要分别填充。&/p&&br&&p&&b&c). Normalizing Continuous Features&/b&&/p&&p&众所周知,NN对输入特征的尺度和分布都是非常敏感的,实际上基本上除了Tree-Based的模型(比如GBDT/RF),机器学习的大多算法都如此。我们发现归一化方法对收敛很关键,推荐一种排序分位归一到[0,1]区间的方法,即&img src=&https://www.zhihu.com/equation?tex=%5Cbar%7Bx%7D%3D%5Cint_%7B-%5Cinfty+%7D%5E%7Bx%7Ddf++& alt=&\bar{x}=\int_{-\infty }^{x}df
& eeimg=&1&&,累计分位点。&/p&&p&除此之外,我们还把归一化后的&img src=&https://www.zhihu.com/equation?tex=%5Cbar%7Bx%7D+& alt=&\bar{x} & eeimg=&1&&的根号&img src=&https://www.zhihu.com/equation?tex=%5Csqrt%7Bx%7D+& alt=&\sqrt{x} & eeimg=&1&&和平方&img src=&https://www.zhihu.com/equation?tex=x%5E%7B2%7D+& alt=&x^{2} & eeimg=&1&&作为网络输入,以期能使网络能够更容易得到特征的次线性(sub-linear)和(super-linear)超线性函数。&/p&&br&&p&&b&3.3 建模期望观看时长&/b&&/p&&p&我们的目标是预测&u&&b&期望观看时长&/b&&/u&。有点击的为正样本,有PV无点击的为负样本,正样本需要根据观看时长进行加权。因此,我们训练阶段网络最后一层用的是 weighted logistic regression。&/p&&p&正样本的权重为观看时长 &img src=&https://www.zhihu.com/equation?tex=T_%7Bi%7D& alt=&T_{i}& eeimg=&1&&,负样本权重为1。这样的话,LR学到的odds为:&/p&&p&&figure&&img src=&https://pic3.zhimg.com/v2-4b76c85fb3_b.jpg& data-rawwidth=&1316& data-rawheight=&142& class=&origin_image zh-lightbox-thumb& width=&1316& data-original=&https://pic3.zhimg.com/v2-4b76c85fb3_r.jpg&&&/figure&其中&img src=&https://www.zhihu.com/equation?tex=N& alt=&N& eeimg=&1&&是总的样本数量,&img src=&https://www.zhihu.com/equation?tex=k& alt=&k& eeimg=&1&&是正样本数量,&img src=&https://www.zhihu.com/equation?tex=T_%7Bi%7D& alt=&T_{i}& eeimg=&1&&是第&img src=&https://www.zhihu.com/equation?tex=i& alt=&i& eeimg=&1&&正样本的观看时长。一般来说,k相对N比较小,因此上式的odds可以转换成&img src=&https://www.zhihu.com/equation?tex=E%5BT%5D%2F%281%2BP%29& alt=&E[T]/(1+P)& eeimg=&1&&,其中&img src=&https://www.zhihu.com/equation?tex=P& alt=&P& eeimg=&1&&是点击率,点击率一般很小,这样odds接近于&img src=&https://www.zhihu.com/equation?tex=E%5BT%5D& alt=&E[T]& eeimg=&1&&,即期望观看时长。因此在线上serving的inference阶段,我们采用&img src=&https://www.zhihu.com/equation?tex=e%5E%7Bx%7D& alt=&e^{x}& eeimg=&1&&作为激励函数,就是近似的估计期望的观看时长。&br&&/p&&p&&b&3.4 不同隐层的实验&/b&&/p&&p&下图的table1是离线利用hold-out一天数据在不同NN网络结构下的结果。如果用户对模型预估高分的反而没有观看,我们认为是预测错误的观看时长。weighted, per-user loss就是预测错误观看时长占总观看时长的比例。&/p&&p&我们对网络结构中隐层的宽度和深度方面都做了测试,从下图结果看增加隐层网络宽度和深度都能提升模型效果。而对于1024--&512--&256这个网络,测试的不包含归一化后根号和方式的版本,loss增加了0.2%。而如果把weighted LR替换成LR,效果下降达到4.1%。&/p&&p&&figure&&img src=&https://pic4.zhimg.com/v2-05b935a5fba84dac4f575dd679ddd66a_b.jpg& data-rawwidth=&942& data-rawheight=&472& class=&origin_image zh-lightbox-thumb& width=&942& data-original=&https://pic4.zhimg.com/v2-05b935a5fba84dac4f575dd679ddd66a_r.jpg&&&/figure&&b&四、总结&/b&&/p&&p&虽然早就读过这篇文章,但是精读之后,发现新收获仍然不少。对于普通的学术论文,重要的是提供一些新的点子,而对于类似google这种工业界发布的paper,特别是带有practical lessons的paper,很值得精读。另外一点就是,论文中提到的一些insight和我们在淘宝商品搜索排序场景的一些insight非常的契合,读来别有感觉。&/p&&p&最后安利下我们team的招聘,对淘宝搜索排序感兴趣的同学欢迎邮件我 qingsong.,来淘宝,一起成长!&/p&
是google的YouTube团队在推荐系统上DNN方面的尝试,发表在16年9月的RecSys会议。虽然去年读过,一方面因为这篇paper的来源于youtube团队的工业实践,G家的东西,非常值得好好研究下;另一方面,…
&figure&&img src=&https://pic1.zhimg.com/v2-f73c03c748ef5cfc10f2f066ed99abcb_b.jpg& data-rawwidth=&1280& data-rawheight=&725& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic1.zhimg.com/v2-f73c03c748ef5cfc10f2f066ed99abcb_r.jpg&&&/figure&&blockquote&Android 技术文章精选第195期:每天为您精选国内外优秀的 Android 技术分析文章。&/blockquote&&p&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s/w76l1fpbsEyWoowytDj0iw& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&1、FlexboxLayout 帮助您完成聪明的 UI 布局&/a&&/p&&p&去年 Google 官方 在 Google I/O 上发布了 ConstraintLayout,在构建复杂布局的同时能够让视图层级得到精简,后来开源了 FlexboxLayout,使得 Android 里的 CSS Flexible Layout 模块也能拥有同样强大的功能。本文通过讲解几个小案例来展示 FlexboxLayout 的优越性。&/p&&p&FlexboxLayout 可以理解为高级的 LinearLayout ,因为这两个布局都将其子视图按序排列。二者之间的重要差异在于 FlexboxLayout 具有 “换行” 的特性。&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//www.diycode.cc/topics/683& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&2、加速 Android Studio 的构建速度,如何把编译时间从 130 秒降到 17 秒&/a&&/p&&p&作者动机:公司的项目代码比较多,每次调试改动java文件后要将近2分钟才能跑起来,实在受不了。在网上找了一大堆配置参数也没有很明显的效果, 尝试使用instant run效果也不怎么样,然后又尝试使用freeline编译速度还可以但是不稳定,每次失败后全量编译很耗费时间,既然没有好的方案就自己尝试做。&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//www.diycode.cc/news/2156& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&3、通过 Cache-Control、Last-Modified 和 Etag 优化客户端缓存&/a&&/p&&p&日常开发中,为了不让用户等得着急,或多或少都会用到 Cache。对于一个有着固定链接的图片资源而言,我们可以简单地将其存储起来,以供后续的访问。但对于那些 Uri 一致,但内容可能随时变化的情形而言,就显得有些不太合适了。&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//www.diycode.cc/news/2157& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&4、ProGuard 又搞了个大新闻&/a&&/p&&p&今天被ProGuard坑的不是混淆API导致的BUG,这货在之前相当长的一段时间里一直相安无事,最近突然又搞了个大新闻,而且问题排查起来相当蹊跷、诡异。&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//weishu.me//dive-into-art-hello-world/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&5、ART深度探索开篇:从Method Hook谈起&/a&&/p&&p&&a href=&http://www.zhihu.com/people/63e1f52a1935d0ecb3e7& data-hash=&63e1f52a1935d0ecb3e7& class=&member_mention& data-editable=&true& data-title=&@weishu& data-hovercard=&p$b$63e1f52a1935d0ecb3e7&&@weishu&/a&
分享从Method Hook开始了解热修复。 &/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//www.diycode.cc/news/2159& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&6、定制触摸反馈:RippleDrawable&/a&&/p&&p&为了更好的在5.0及以上设备上使用波纹效果,简单跟大家聊下RippleDrawable的正确打开方式,如何方便快捷的定义不同的触摸反馈的范围以及波纹扩散的颜色,最后聊下5.0以下设备上的兼容方案。&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/Krupen/AutoplayVideos& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&7、AutoplayVideos:视频随着滚动自动播放和暂停,基于RecyclerView实现&/a&&/p&&br&&h2&课外话题&/h2&&p&&a href=&https://www.zhihu.com/question/& class=&internal&&典型的「学生思维」有哪些?&/a&&/p&&p&RT。&/p&&blockquote&&p&喜欢这期 Android 技术文章精选么?喜欢的话,不妨点个赞 吧!&/p&&/blockquote&
Android 技术文章精选第195期:每天为您精选国内外优秀的 Android 技术分析文章。去年 Google 官方 在 Google I/O 上发布了 ConstraintLayout,在构建复杂布局的同时能够让视图层级得到精简,后来开源了 FlexboxL…
1. 請別人幫忙(發文件等等)&br&At your convenience, would you please send me.....&br&最後加上Thank you for your assistance.&br&&br&2. 尋求意見:&br&Our team would appreciate your insights/input on.....&br&&br&Due to the short time frame for this proposal, prompt reply is greatly appreciated. &br&&br&3. 取消會議:&br&I want to be mindful of your time and we don’t have any u therefore I suggest that we cancel/reschedule today's meeting. If you disagree or need assistance, please let us know.&br&&br&My apologies for the late notice, but i need to reschedule tomorrow's call. There remain a few open items we need to address, therefore i will send out a new invite once we agree upon a time.&br&&br&4. 對方發郵件問問題時,回答完加上:Hope this answers your question. Let me know if further detail/explanation would be helpful.&br&&br&5. 會議總結:&br&Thank you for making time on a very busy Friday afternoon to join our discussion. i hope we were able to provide clarity on......Attached is a summary of what we discussed today.&br&&br&6. 道歉:&br&My sincere apology for this u I will address to my team immediately.&br&Again,please accept my most sincere apology.&br&&br&7. 跟客户分享项目进展以后,建议电话详谈&br&Once these final steps are finished, I would suggest having a brief call to discuss our findings and recommendations for next steps.
Would you please provide a few times the week of XXX that work within your schedule and I will send the calendar invite?&br&&br&8. 文件打了草稿,请求上司过目&br&Attached is the drafted xx file. It is still a work in process but I would like to see if anything immediately stood out to you as odd or worthy of follow-up.&br&&br&9. 分享2个不错的automatic reply,去旅游或者外地开会的时候可以用:&br&&p&Thank you for your e-mail. I will be out of the office on vacation from XXX - XXX with no access to e-mails. I apologize for any delay in response to your e-mail. I will respond to your e-mail as quickly as I can when I return to the office on Monday, April 18th. Thanks!&/p&&br&&p&Thank you for your e-mail. I am out of the office in meetings on XXX and XXX with limited access to e-mail. If you need immediate assistance, please contact me via my mobile phone.
Thank you!&/p&&br&10. 指点下属&br&Thanks for preparing the XXX. I made the following updates to the question responses.
We can discuss my thought process when I am in the office on Monday.
&br&&br&XXX, good job! I have reviewed the XXX documents and have the following review comments:&br&1...&br&2....&br&(将做好的文件交给老板检查以后,通常会有Review Comments,就是列出需要改的部分)&br&&br&11. 邮件问好 (美国人好喜欢用hope 哈哈)&br&周一/二可用:&br&I hope that your week is off to a great start.
&br&Hope you had a great weekend.&br&万能的:&br&Hope you’re well/Hope you are doing well.&br&I hope this message finds you well.&br&&br&PS. If you like this answer, if not, don't. I REALLY don't give a damn of your opinion.&br&&br&以上
1. 請別人幫忙(發文件等等) At your convenience, would you please send me..... 最後加上Thank you for your assistance. 2. 尋求意見: Our team would appreciate your insights/input on..... Due to the short time frame for this proposal, promp…
&p&移动GPU和桌面GPU最核心的差别在于渲染流程不同。目前主流的移动GPU,无论ARM、高通还是Imagination,其GPU都是TBR(Tile Based Rendering)。而桌面GPU,无论NVIDIA、AMD还是Intel,都是Immediate Rendering. 下面我就来说说什么叫TBR,什么叫Immediate Rendering。&/p&&p&说在前面:
从opengl定义的GPU pipeline来看,一帧3D场景是通过以下几个过程渲染出来的。&/p&&p&“Vertex前端”(负责准备数据和Vertex Shader指令)-&&Vertex Shader&(计算定点位置,颜色,纹理坐标,光照,等相关工作)-&&Primitive Assembly&(负责组装图元,比如三角形; 坐标系变换,物体坐标-&世界坐标-&透视变换-&屏幕坐标;视锥剪裁;Culling正反面选择)-& “Rasterizing”(光栅化,就是将立体场景投影到二维屏幕的过程)-&&Early Z/S&(前期depth和stencil测试,决定一个fragment是否被渲染,从而降低后期fragment shader的负担)-&&Fragment Shader&(对一个fragment,即像素,进行渲染。可能涉及到读取纹理texture。)-&&Post Z/S&(后期depth和stencil测试,有些应用在fragment shader中可能会改变该像素的深度值)-&&Blending&(将此次渲染结果和之前的渲染结果进行混合)。&/p&&br&&p&1. Immediate Rendering&/p&&p&Ok,说到这所谓的Immediate Rendering,就是将一个图元(最常见的是三角形),从头到尾走完整个Pipeline,中间没有停止。这种结构,控制简单,容易实现。问题是在做blending的时候需要从存储单元中不断读回之前render的结果,可想而知在绘制一个大的场景时这个带宽消耗是比较大的。&/p&&p&那为什么桌面GPU会采用这个架构。首先,历史原因,最开始设计opengl pipeline的人,正是这些设计桌面GPU的大咖们。不过,最重要的一点是,桌面GPU都是有自身显存的,它不需要通过系统总线从系统的DDR memory中读回数据。所以开销比较小,是完全可以接受的。但移动端的处理器(基本是可以认为都是ARM处理器)都是统一寻址的。所有的IP都是使用统一的DDR存储空间,这样读回Pixel进行blending就变成了一件非常奢侈的事情。它会严重占用系统带宽,不但功耗提升,而且会影响整个SOC的处理能力(可以想象北京上海的堵车场景)。为了解决这个问题TBR便应运而生了,下面该TBR出场了。&/p&&p&
2. TBR&/p&&p&TBR是Tile Based Rendering的缩写。首先来认识一个概念Tile。什么是Tile,你可以把它看成一小块屏幕区域。比如一个屏幕的分辨率为256x256,假定一个tile的大小是16x16,那么这个屏幕可以看成是由16x16个Tile组成。TBR的精髓就是一个Tile一个Tile的渲染。这样只需要给GPU配上一块很小的片上cache(足够装下一两个Tile的内容就行),就能实现高效的blending。那么,问题来了,根据前面讲述的GPU pipeline来看,只有在光栅化的时候才能知道每一个tile中包含的fragment,如何才能做到一个tile画完再画另一个tile呢。这里就需要一种机制将整个场景的图元信息(最主要的是位置)都保存下来,并且能在做光栅化时快速的检索出属于这个Tile的图元。所以所有的移动GPU中都会有Tiler这个模块,这在桌面GPU中是没有的。每个厂家的Tiler实现都是机密,这里不予讨论。我们只要知道Tiler能接收vertex shader的运算结果,并在光栅化之前,选出属于特定tiler的图元就行了。有了Tiler,这个GPU Pipeline就被分为了两部分,一个场景中所有的vertex计算都在光栅化之前完成,最后再一次性raster一个Tile。这样做还有一个好处就是,可以更有效的在early z中剔除被遮挡的像素,降低了fragment shader的负载。&/p&
移动GPU和桌面GPU最核心的差别在于渲染流程不同。目前主流的移动GPU,无论ARM、高通还是Imagination,其GPU都是TBR(Tile Based Rendering)。而桌面GPU,无论NVIDIA、AMD还是Intel,都是Immediate Rendering. 下面我就来说说什么叫TBR,什么叫Immediate Re…
国内真正做过游戏AI的很少,说概念的人很多,所以看了半天离实际编码还是很远,不知道该怎么入手,因为国内游戏主要以MMO和卡牌为主,RTS比较少,体育竞技类游戏更少,没几个真正写过强AI代码的。而从AI的难度上来看,是:MMO & FPS & RTS & 体育竞技。作为实际开发过AI的人,拿一份五年前的代码,以最难的体育竞技类游戏为例,来科普一下,什么叫做游戏团队策略,什么叫做分层状态机?具体该如何落地到代码?如果你能实现体育竞技的AI,那即时战略只是小事一桩。&br&&br&硬派游戏AI,不是虚无缥缈的神经网络,用神经网络其实是一个黑洞,把问题一脚踢给计算机,认为我只要训练它,它就能解决一切问题的懒人想法。更不是遗传算法和模糊逻辑,你想想以前8位机,16位机上就能有比较激烈对抗的足球游戏、篮球游戏,那么差的处理器能做这些计算么?&br&&br&硬派游戏AI,就是状态机和行为树。状态机是基本功,行为树可选(早年AI没行为树这东西,大家都是hard code的)。大部分人说到这里也就没了,各位读完还是无法写代码。因为没有把最核心的三个问题讲清楚,即:&b&分层状态机&/b&、&b&决策支持系统&/b&、以及&b&团队角色分配&/b&。下面分类介绍:&br&&br&&b&何为分层状态机?&/b&&br&&br&每个人物身上,有三层状态机:基础层状态机、行为层状态机、角色层状态机。每一层状态机解决一个层次的复杂度,并对上层提供接口,上层状态机通过设置下层状态机的目标实现更复杂的逻辑。&br&&ul&&li&基础状态机:直接控制角色动画、提供基础动作实现,为上层提供支持。&br&&/li&&li&行为状态机:分解动作,躲避跑、直线移动、原地站立、要球、传球、射球、追球、打人、跳。&br&&/li&&li&角色状态机:实现更复杂的逻辑,比如防射求、篮板等都是由N次直线运动+跳跃或者打人完成。&br&&/li&&/ul&&figure&&img src=&https://pic4.zhimg.com/402bcf0e16bb_b.jpg& data-rawwidth=&542& data-rawheight=&264& class=&origin_image zh-lightbox-thumb& width=&542& data-original=&https://pic4.zhimg.com/402bcf0e16bb_r.jpg&&&/figure&每一层状态机都是通过为下一层状态机设定目标来实现控制(目标设定后,下层状态机将自动工作,上层不用关心动画到底播到哪了,现在到底是跑是跳),从而为上层提供更加高级拟人化的行为,所有状态机固定频率更新(如每秒10次),用于判断状态变迁和检查底层目标完成情况。最高层的角色状态机的工作由团队AI来掌控,即角色分配的工作。而行为状态机以上的状态抉择,比如回防,到底是跑到哪一点,射球,到底在哪里起跳,路径是怎样的,则由决策支持系统提供支持。&br&&br&&b&何为决策支持系统?&/b&&br&&br&状态机为角色的大脑,而决策支持系统是眼睛和耳朵,常见的工具有势力图(Influence Map)和白板(相当于不同角色间喊话),其中势力图比较常用,篮球游戏AI势力图可以用下面几张图表示:&br&&figure&&img src=&https://pic2.zhimg.com/45a8bff67eb5be884cb3e9_b.jpg& data-rawwidth=&620& data-rawheight=&229& class=&origin_i}

我要回帖

更多关于 90后攻城狮 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信