證悟、佛心與凡夫心 讀記《西藏生死書》

我們雖然也想佛陀一般具有佛性,卻未認出來,因爲它被我們的凡夫心包得密不透風。試著觀想這裏有一隻花瓶,瓶内的空間與瓶外的空間一模一樣,卻被脆弱的瓶壁分隔。我們的佛心被包在凡夫心的瓶壁内。儅我們證悟時,就好像花瓶破成碎片,“裏面”的空間與“外面”的空間結合爲一。它們合而爲一。當下我們才發現,它們從未分離也并無二緻,他們是永遠相同的。

 


摘自《西藏生死书》

索甲仁波切
郑振煌 译

 

BootstrapValidator 页面验证多个form

只做记录,没什么技术含量。

每个页面多个form,没问题,form id不同,name不同,然后“标识”不同,所谓标识就是放一个<input type=”hidden” 指定比如name=”type” ,那么多个form在action到同一个method的时候,就使用type判断当前提交的是哪个form;那bootstrapValidator里绑定的内容如下:

第一行jQuery选择器匹配所有form并添加bootstrapValidator,然后post时使用this传递form data,其他的form处理都一样,就四酱。

去年的新年愿望,实现了吗?

      地球再度绕着太阳运行到了一个固定位置。为了让这一刻具备仪式感,人类名之为“新年”,定了些固定的庆祝仪式,吃饺子喝酒,放烟火办晚会,在微信上互发复制来的祝语和表情,以及,自欺欺人地立志实现几个新年愿望。

我握拳,下定决心,前年许下而去年没做的愿望,绝不能拖到明年,今年一定要实现。

最简单有时又最奢侈的愿望,是保持呼吸,不要断气。除此外,最常见的愿望有四——减肥、戒烟、还清债务,和亲友共度更多时间。

然而,大概只有十分之一的人能达成愿望。英国赫福郡大学的心理学者理查德·魏斯曼 (Richard Wiseman)研究3000 人后发现, 88%的决心最终失败。决心湮没在时光里,就像石子沉没在长河中,激起的涟漪只是一瞬,此后河水汤汤,依然如故。

这次必须不一样!我决心打破“无志之人常立志”的怪圈,成为“有志之人立长志”。不过首先,我要搞清楚,为什么我去年的新年志向没有实现?

失败原因一:许下的愿,不是真正志向

你以为你想要的就是你所需要的吗?

很多时候,你并不知道什么能让自己幸福。

中大奖等于变幸福?菲利普 •布里克曼(Philip Brickman )的研究显示,彩票大奖得主的幸福程度很快就归于平常。好天气能让人心情舒畅?丹尼尔 •卡尼曼(Daniel Kahneman) 发现,阳光明媚的加州人,和天气一般的美国中西部人,其生活满意度大抵相当。买下这样商品就能让我更快乐?结果商品在墙角积灰,而瘪瘪的钱包令人郁郁不乐。

“不快乐往往不是缘于我们没能得到想要的,而是缘于我们不想要我们真正喜欢的。”哈佛心理学家丹尼尔·吉尔伯特(Daniel Gilbert)如是说。他和心理学家蒂莫西·威尔逊(Tim Wilson)曾找来一群美国助理教授(assistant professor),问他们一个简单的问题,“你认为,拿到终身教职对你的幸福有多大影响”?

所有助理教授都认为,会影响深远。他们遥想未来,若能拿到铁饭碗,自己肯定日日笑口常开,走路带风。若拿不到,自己必然天天愁眉不展,惨淡度日。

后续追踪发现,教授们错了。在未来几年里拿到终身教职的,和未拿到终身教职的,主观幸福程度相差无几——即使智力出类拔萃,也不太擅长预测“什么能让自己更幸福”。吉尔伯特和威尔逊为此造了个新词——“错误渴求( miswanting)”,专指“错误预测了自己的需求,错误地估计了自己要得到什么才会快乐,因而做出了差劲的决策。”

当你不太费力就能实现愿望时,问题一般不大,无非是“得到了却发现不过如此 ”。但当你许下的愿望需要付出很多才能实现时,你就会在付代价时踟蹰犹豫,不断拖延,或者干脆只是将这个愿望挂在嘴上,一点不开展积极行动。

解决方案一:连问自己五次,“为什么我想要”

有个简单办法,能帮你找出潜藏在心中的真正愿望。

先写出自己心目中的愿望,接着自问“为什么我想要这个?” 得到答案后,继续追问“为什么这么想?” 如此连续发问,一般5次内即可发现你真正的渴望。

也许你第一个自然浮出的愿望是“戒烟”,但不要止步于此,要继续追问下去——为什么想戒烟?因为希望更健康。为什么希望更健康?因为健康可以活得长久。为什么想要活久一点?因为想多照顾家人一段时光。为什么想多照顾家人?因为我想成为负责的人……

很多戒烟的人之所以失败,是因为他们错误地估计了自己的愿望——或许你不想戒烟,你真正想要的,是成为家人的可靠支撑。在“吸烟”和“不吸”之间,你会选择能带来快感的吸烟。然而,当你将“烟”视为自己照顾家人的阻碍时,你会选择“照顾家人”。村上春树一度日抽60支烟,后来戒烟,不是因为他厌倦了烟草,是因为他发觉写小说需要体能,于是决心锻炼,于是开始跑步,于是渴望跑得更多——而烟草,作为跑步的阻碍,就被自然而然地放弃了。

失败原因二:四类愿望,注定无法实现

一个典型的的新年愿望是这样的——

“我希望新年里,事业上个新台阶,财富多个数量级,全家和睦亲密,故旧健康平安,多联系老友,多认识新友,行万里路,读万卷书,看尽佳片,吃遍美食,到了年末还要瘦上二十斤! ”

四个字总结——这不科学。问题在哪 ?

一,愿望不要太多。多到记都记不住,时间不够分配,谈何实现?

二,愿望不要自相矛盾。有的职业,注定无法天天和家人相处。要甩肉,就得泪别诸多美食。想健康,就得关掉电视放下书,甩开膀子迈开腿。

三,愿望不要太难。从难度来说,愿望应该尽量设成“有难度,但努力后很可能达成 ”。 最难实现的目标是什么? Daniel Kahneman认为,是“在演员之路上大获成功”。不过,假如这恰是你的心之所向,祝你新年好运。

四,愿望不要太大。大到任何一项拿出来,都必须投入大量时间精力。

作家 Nigel Marsh说,“平衡工作和家庭很简单,只要我不工作就得了。”他辞职,赋闲一年,专职陪妻子和四个儿子。“当然了,”他补充说,“在缺钱的时候,这招不怎么好用。”
大部分人没有余闲去享受这种奢侈。也就是说,我们未来一年里的将近三成时间已经卖给了买家——不信就把工作合同拿出来多看几遍。

还有四成时间也有了去处,吃喝拉撒睡。人要正常运作,就得满足基本需求。

然后,我要在剩下的三成时间里,用我软弱的意志力,驱动我迟缓的身体,完成彩衣娱亲呼朋引伴环球旅行看书看电影山珍海味锻炼减肥……请容我再说一遍——这不科学。

那么,如果我们只许一个新年愿望。有没有“最好的新年愿望 ”呢?

解决方案二:愿望一个足矣,养成“楔石习惯”

楔石,是拱桥顶部的一块石头,这块石头是整个架构保持稳定的关键所在。当查尔斯·杜希格 (Charles Duhigg)创造出“楔石习惯(keystone habits)” 这个词时,他指的是一种关键习惯,它能改变大脑的神经模式,能促成其他好习惯蓬勃生长,能引发链式反应,令你的生活发生巨变。

楔石

习惯很重要。改变习惯,就能改变行动。改变行动,就能改变最终的结果。一次行动看似微不足道,但你若能从天天下午自动吃蛋糕,变成天天下午自动去慢跑,一年内体型就会出现巨大区别。

每天大概 45%的行动不是出自“决定” ,而是出自 “习惯” 。决定出自前额叶皮质( prefrontal cortex),懂理性,能自省。习惯出自基底核 (Basal Ganglia),被线索触发,受欲望支配。明明想去别处,却惯性地走了每天上班的路,这就是习惯给你导的航。习惯帮我们不假思索地料理诸多日常琐事。没有习惯,大脑很快会不堪重负。然而,将重责大任托付给习惯也有坏处 ——有时我们的理性下了决心,而习惯往往拒绝配合。

习惯是顽固的,但同时,习惯也是可以被改动、消灭、创造的——你必须对这点抱有信心,事实上,你必须对这点抱有近乎盲目的信仰。这是改变的关键之一。

什么是典型的楔石习惯?

一是锻炼。

锻炼能改变你的体型,改变你的大脑 ——包括供血、神经递质和营养因子,另外,锻炼还能改变你的自我认知。你将把自己视为一个有自制力的人 ——毕竟,你都能定期运动了!一旦人们开始锻炼,他们不但身材变好了,分心减少了,而且拖延症往往得到大幅改善——连每天洗碗的时间都提前了 23分钟。

二是记录。

记录是一种提醒,提醒你注意到 “我正在做什么”。记录可以用于回顾,反省“我都做了些什么 ”。另外,一旦养成记录的习惯,在行动开始就有一种清晰的自我意识,因此后续的行为和决策也会受到影响。

2009年,美国国立卫生研究院( NIH)找来1600 名肥胖者,要求他们试着记录自己吃下的每样东西 ——哪怕一周只记一天也成。六个月后,那些养成了记录习惯的人,减去的重量是未记录者的两倍。原因很简单,记录这个动作,能帮助发现自己的习惯,再也不会 “不知不觉地吃下大量食物 ”。通过天天记录,有些人发现自己会在上午 10点吃上一块小甜饼,在睡前一小时吃掉一袋薯片。现在,他们决定事先做好准备。此后,在同样的时刻,他们习惯性地伸手——拿到并吃掉的是一个苹果。

如果你渴望减重,就记录你吃的每一样东西。如果你总是入不敷出,就记录你的每一项花费。如果你总不知道 “时间都到哪去了”,就记录自己每时每刻的行为( Rescuetime、atimelogger、爱今天 )。如果你想修正自己的一个不良习惯,就记录你每次 “犯老毛病” 时的时间、地点、自己情绪、周围有什么别人、之前自己刚刚做了什么。这五样记录能帮助发现,是什么线索触发了你 “走老路” 的习惯。

最后还有一点很重要,不论你选择养成什么楔石习惯,都记得给你的新好习惯设计一个仪式化的结尾 ——我们需要仪式。仪式提供一种即时的回馈,让你感到所做的一切收到了回报。这个仪式可以是一个动作,一块糖果,甚至只是在行事历上的一个五角星标记——只要简单易行、能令你感到愉悦就行。别小看这点奖赏,它将决定你能否养成习惯。而一旦养成楔石习惯,你就能说服自己,我可以改变,我可以有更大的改变。

失败原因三:障碍出现,未曾备好对策

你必须意识到一点,在养成习惯的过程中,你一定会失败的——不止一次。

当你在新年假期里压力全无地计划着 “来年我要这么这么做”时,你已经忘了,一旦假期结束,你立刻会进入与此刻完全不同的状态 ——

现实是什么?现实是体力有限。精力有限。脑力有限。斯坦福的神经经济学教授巴巴·希夫( Baba Shiv)证明,如你需要费心记住一个 7位数字,你在挑选食物时就更容易选择巧克力蛋糕,而非水果沙拉——就好像我们一天能干的 “好事” 有个上限。一旦到了这个限度,你就只想抽根烟来杯酒吞下一桶炸鸡腿,然后摊在床上刷手机刷到睡着。

现实是,改变很难。养成好习惯很难。做正确的事很难。传说养成一个习惯需要 21天—— 错,许多人需要的时间远不止此。 2009年,英国伦敦大学学院的一项研究发现,养成一个习惯最短需要 18天,最长则花了差不多8个半月。

现实是,我们不喜欢改变,事实上,我们抵触改变,哪怕我们明知这改变对我们有益。我们还是会故态复萌,一次,一次,又一次。 80%的戒烟者在成功戒烟前,会复吸 8到10 次。

我们失败。这很正常。致命的是我们对于失败的反应 ——我们选择自毁,因为我们被失败压垮,我们相信自己无法改变,只能顺从本能的渴望。我们习惯偷懒,习惯放弃,习惯对自己失望,习惯了设定目标又从不达到,最后索性习惯了没有目标。我们告诉自己,人生就是这么丧,我就是这么烂,放弃吧,我将躺在泥潭中,边下沉,边宣布星空只是幻象。

怎么办?首先,你得接受“倒退”是进步的一部分。你得相信,一次失败不代表你达不到你的目标。如果我在成功之前需要失败 100次,那么现在,就只剩下 99次。

此外,你还需要一个预先定好的 “失败应对方案”。

解决方案三: WOOP,假如遇到障碍A,我就执行计划B

比方说,你的愿望是 “我要每天早上晨跑一小时 ”。

你闭目想象,闹钟一响,自己掀被而起,套进跑鞋,冲出家门,沐浴在金色阳光中,呼吸着清冷透亮的空气,你像羚羊在非洲草原上奔跑,啊,奔跑。

想象结束,你感觉棒极了。

事实上,这样的 “成功幻想” 一次就能降低血压 5毫米汞柱,简直堪称无毒无害无副作用的舒缓放松良方。

一切都好,除了一点 ——这种幻想对你实现愿望只有阻碍,毫无帮助。

当你在想象中已经体验过了成功的甘美,何必还在现实中为之辛苦拼搏呢?纽约大学的心理学家加布里埃尔 •奥丁根(Gabriele Oettingen)发现,学生在对学业进行乐观幻想后,在未来一周内反而会减少投入学业;那些对自己的自制力最有信心的减重女士,偏偏是一年后减重最少的人。

别做梦了,醒醒吧。对比一下美好理想和现实中的重重阻碍,通过这种对比,找出克服障碍、接近理想的道路。这种方法,叫“ WOOP”。

WOOP分四步。

一、愿望( Wish),别等了,现在就抓张白纸,写下一个对你深具意义、具体可执行的愿望——譬如说,每天早晨晨跑一小时。

第二步,想象成果( Outcome),想象达到目标后你将如何从中获益——譬如说,好看,不抑郁,治疗拖延症。在未来的懈怠时刻,你就可以翻出这三条,提醒自己当初许愿的初心。

第三步是真正难点——寻找障碍( Obstacle)。你可能前一晚睡不着觉,第二天起不了床。可能你明明打算跑步,起床后却不知不觉刷了一小时手机。可能窗外北风呼啸,而你发现自己瞬间皈依了回笼教。没准你跑了两天就感冒,再跑一周已濒危。或许你挣扎半响垂死病中惊坐起,却发现窗外白茫茫一片雾霾已爆表……

第四步,计划( Plan)。计划必须是如下形式 ——“假如处在X 状况下,我就采取 Y行动”。假如我睡不着,我就闭眼平躺练习冥想。假如我起不了床,我就告诉自己,我可以做到。假如空气糟到不适合跑步,我就在室内进行力量训练。假如我觉得不想跑步,我对自己说, “这是我发自内心的愿望”…… 诸如此类。

针对不同的障碍,你可以做出一张张 WOOP小卡片,存在电脑里,写在本子中,最重要的,是牢记在心底。在一些困难的抉择时刻,在一些不确定的时刻,我们会忘记自己的理想和初衷,你需要一次次地自动提醒自己,我的心愿是什么,我想去到的地方在哪里,这一年,我一定能养成我的楔石习惯,而更大的改变也将近在咫尺,不再遥不可及。

参考资料

  1. Duhigg, Charles. The power of habit: Why we do what we do in life and business. Vol. 34. No. 10. Random House, 2012.
  2. Kahneman, Daniel. Thinking, fast and slow. Macmillan, 2011.
  3. Lehrer, Jonah. How we decide. Houghton Mifflin Harcourt, 2010.
  4. Oettingen, Gabriele. Rethinking positive thinking: Inside the new science of motivation. Penguin, 2014.
  5. O’Connor, Richard. Rewire: Change Your Brain to Break Bad Habits, Overcome Addictions, Conquer Self-destructive Behavior. Penguin, 2014.
  6. Evans, Olga, and Andrew Steptoe. “Social support at work, heart rate, and cortisol: a self-monitoring study.” Journal of occupational health psychology 6.4 (2001): 361.
  7. Lally, Phillippa, et al. “How are habits formed: Modelling habit formation in the real world.” European Journal of Social Psychology 40.6 (2010): 998-1009.
  8. Shilts, Mical Kay, Marcel Horowitz, and Marilyn S. Townsend. “Goal setting as a strategy for dietary and physical activity behavior change: a review of the literature.” American Journal of Health Promotion 19.2 (2004): 81-93.

作者:游识猷
链接:http://www.guokr.com/article/441938/
来源:果壳
本文版权属于果壳网(guokr.com,微信公众号:Guokr42)
【禁止二次转载,如需转载请联系sns@guokr.com 】

初识野狗(WildDog)之数据增删改查 – 野狗REST api使用

野狗云
野狗实时通讯云

试用了一下野狗云,感觉好到非常。这种开发方式对传统数据库(sql)必然造成很大影响(程序狗一定要居安思危),或者说新的云时代真正来临了。

我所理解的野狗云,就是云端的数据库,但不是传统的mysql,oracle,sqlserver,而是基于key-value存储的文档数据库,或者叫no-sql?不知道这样说准不准确。访问方式基于的http协议,get、post、put、delete等(当然有验证机制)。这样来讲,我们就可以通过其他的url访问工具,例如curl进行数据的增删改查了,官方的文档正是这样写的。

官方文档中使用REST方式操作数据同样使用的是curl工具,感觉写的不是很详细。

今天使用了postman模拟http请求野狗数据的整个过程,包括增加、追加、更新、删除、查询数据的简单操作(不要问我为什么把顺序写成这样),记录一下。

概念:
数据,或者说一张表,野狗中都叫做节点,可以看下野狗的基础概念文档

先来个官方的简短说明,数据操作包含以下五种请求类型:

方法 说明
PUT 向指定 节点写入数据。若此节点已存在数据,会覆盖原有数据。
POST 向指定节点添加 子节点。子节点的 key 自动生成并保证唯一。
PATCH 更新指定子节点。
DELETE 删除指定节点。

增加数据(节点):
使用http请求put方式,请求https://wild-sheep-1485.wilddogio.com/movie.json上面的movie.json就是节点名称,将创建一个名为movie的节点,如下图:

postman请求http put方法为野狗云增加数据
postman请求http put方法为野狗云增加数据(左边是野狗后台,右边是postman)

需要注意的是Headers中要增加Content-Type=application/json键值对,并且Body选项卡要设置raw格式,点击Send将创建movie节点,并为其增加一个movie1的子节点(一条数据),可以看到使用了两个字段(节点,一切皆节点)name和actor。注意:put操作会先清空指定节点,再写入数据。

追加数据(这个非常有必要说明)
传统的sql中插入数据不管表里有没有数据,只要闭着眼睛执行insert into行了。那么既然put操作会先清空指定节点,然后再写入数据,那么我追加数据的时候总不能先把以前的数据取出来,然后再加上一条,然后再put吧(对不对,讲道理嘛)。所以搞了半天,弄明白追加数据是这样的,如图:

野狗云api使用http patch追加数据
野狗云api使用http patch追加数据

可以看到这次使用的patch方法,节点名称movie.json等都没有改变,就为movie增加了一个movie3子节点,并且actor写成了集合形式。

更新数据
更新数据与追加数据一样,也是使用的patch方法,如图:

野狗api使用http patch更新指定节点
野狗api使用http patch更新指定节点

比如我要更新movie节点下movie3的name(从铁达尼号变成泰坦尼克号),就要使用patch方式,注意请求的地址(野狗中叫路径)

删除数据
比如要把上图中的actor中的0(迪卡普里奥删掉),那么需要执行delete请求,请求地址为:https://wild-sheep-1485.wilddogio.com/movie/movie3/actor/0.json(可以看到节点查找方式,即路径名称),删除之后的节点为:

野狗云http delete删除节点
野狗云http delete删除节点

查询数据
你以为查询数据最简单了?Oh no,虽然执行get是很简单,比如获取所有的数据(节点),我又新增了user节点和数据:

野狗云api使用http获取所有节点
野狗云api使用http获取所有节点

注意路径是以 .json结尾,标识获取所有节点,若要获取某个确定的节点,只需指定节点名即可,比如user.json

查询数据官方还支持orderBy和过滤等操作,暂时没详细看传送门。
先写到这里,感谢野狗两位大牛 @六金、@董笑飞的热心解答。

学习新知识是自我蜕变的过程,如果你在刻标记的地方捞剑,你可能捞到的不是剑 (:P

技术知识积累分享, 应用地址未打码, 请勿黑 .
原创文章,转载请注明出处与本文章链接 https://lison.cc/?p=590

Solidworks PDM: 如何查找PDM文件在服务器中的物理路径

PDM允许用户在使用它的文档节点(vaults)管理各种各样类型的文件,并且通过EPDM接口可以方便的查找和修改这些文件。但是作为EPDM文档管理员的你可能想要得到EPDM文件的真实物理路径(资源定位符路径,例如:C:/new.txt),用来找回丢失的文件,或者其他目的。要找到他们并不是很困难,只需要在SQL中执行以下几个步骤。

现在我们来假设一下在文档节点中有一个名为:170-012-011.sldprt的文件,我们想知道它具体存在于哪个文档目录中。需要在SQL中查询Documents表。

打开SQL Server Management Studio,连接好SQL实例。执行下面的select语句.

会得到如图的结果:

查询Documents表语句的返回结果截图
查询Documents表语句的返回结果截图

我们来看下查询语句,我们从Documents表(FROM Documents)查询了document ID字段(SELECT Document ID),并且把查询到的Document ID转换成了一个16进制值(CONVERT(varbinary,DocumentID) as ID_Hex_Value)(稍候我们会看到为什么要这样做),然后还有一个文件名,Filename字段(where Filename like’170-012-011%‘

现在有趣的来了,EPDM如何知道文件的具体位置呢? 可以看到Document ID:3228的16进制值是C9C。现在把C9C组成一个8位数字,左边空白补0,就变成了00000C9C。那么我们要查找的文件目录就是:<vault name>\C\00000C9C。’\C\’定义了文件存储在名称为C的目录中,而00000C9C则是子目录的名称,如图。
文件节点存储一级目录截图 screen-shot-2015-02-05-at-2-30-49-pm-1024x559

然后打开目录就能看到。通常目录里会有一个index.xml文件。

screen-shot-2015-02-05-at-2-19-35-pm-1024x142

然后要查找的170-012-011.sldprt文件就是 00000001.SLDPRT。要验证是否正确的话,就打开index.xml可以看到filename。
epdm-archive-directory-2

ok,就是这样,要注意的是,不要手动修改这些文件,这样会对数据库产生影响。

本文翻译自:CAPUniversity
《How To Find Your Enterprise PDM Files Within the Archives Directory》

The Gift – Gregorian

不知道是宗教乐还是教堂乐,不知不觉已repeat几十遍。
不管了,让我的翻译水平来抹杀一下经典。

Masters of Chant Chapter IV

Forgive is a word that I am learning
我正在学习“原谅”这个词

If only to pass the time
如果只通过过去的时间

I love you for all your weakness
我爱你爱所有你喜欢的东西

I love you for all your lies
我爱你爱你所有的谎言

Will you grow
你是否会成长

Will you understand
你是否会明白

The damage you caused in time
现在你造成的伤害

The past is behind we are facing
我们面对的过去已过去

A punishment for the crime
为罪恶接受的惩罚

The gift you gave me
你给我的礼物

Our sweet encounter
我们邂逅的甜蜜

Became so fragile and flow with the night
变得如此脆弱然后随夜晚流走

I will be witness
我将见证
I will not falter
不会害怕
Till we are risen again to the light
直到我们再次升华

Would you forgive me
你会原谅我吗
My heart was broken
我的心已经碎了
But I will mend I will be as before
但我会修补它我会跟以前一样
Just give me one chance
请给我一次机会
To make it better
让它变得更好
Uhh let me be yours
让我成为你的

Without you I’m weak and I’m listless
没有你我是脆弱,我是颓废的
Without you I find I’m blind
没有你我发现我是盲目的

I watch you alone are you dreaming
我看到你一个人你梦见
Of happines left behind
被我们扔下的幸福了吗
Do you drift in your heart at night
夜晚你的心在游荡吗
Walk through the rooms of your mind
经过你心神的房间
Open the door I’ll be waiting
打开门我会在等待
Remember this is your life
记住这就是你的人生

The gift you gave me
Our sweet encounter
Became so fragile and flew with the night
I will be witness
I will not falter
Till we are risen again to the light

Would you forgive me
My heart was broken
But I will mend I will be as before
Just give me chance
To make it better
Uhh let me be yours

The gift you gave me
Our sweet encounter
Became so fragile and flew with the night
I will be witness
I will not falter
Till we are risen again to the light

Would you forgive me
My heart was broken
But I will mend I will be as before
Just give me on chance
To make it better
Uhh let me be yours

使用Netty进行Android与Server端通信实现文字发送接收与图片上传 – 原创

ANOTHER TITLE:

Let’s use netty to achieve text send and receive and  image transfer to server based on android and jdk1.7

就让我来Rap<MC Hotdog>,使用netty进行安卓端发送接收文字,并且附带发送图片功能,折腾了几天的netty总算有点眉目了,做下记录。

需求是安卓端拍照上传到服务器,服务器返回上传成功或失败bla bla bla,需求比较简单。最初使用的传统的post加multipart/form-data,一般的手机照片大小1-2M,测试没问题,但实际情况是有的用户使用3G网络,有的4G,有的WIFI还有的使用2G,网络环境稍微有点差的上传图片时间持续到十多分钟(我都不好意思说了),然后想到了使用socket,然后google到了netty,有的大神说这样的需求没必要上netty啊,其实我就是想通过这个需求学习下关于socket,关于netty,关于channel,关于byte[],关于NIO,多学习点总是没坏处的,后面我也可以牛逼点说玩过高性能基于事件的异步网络框架了。

刚开始直接啃的netty.io的document,照葫芦画瓢抄完了TimeServer之后就满世界的google其他的netty知识,比较零散,然后入手了《Netty权威指南第二版》,啃了几章之后怎么也是TimeServer,不过对NIO一些基本组件有了一个初步的认识。

OK,入正题,我要实现一个Demo,就说是个Netty的聊天室吧(群聊,没有单聊的功能,demo味儿十足),不过客户端换成了安卓,一个服务器对多个客户端,所有数据经过服务器端,要定义中间信息交换组件。关于Google的Protobuf还有MessagePack和JBoss Marshalling这些编解码中间件都没有玩过,似乎有点看不懂,我的需求很简单,如下图(抱歉键盘党多年手已废掉,可能只有我自己看得懂):

Echo-Server、Echo-Pojo、Lets's Chat Relationship

一共包含三个对象:

Echo-Pojo,信息交换中间对象,用于Android端与Server端封装byte[]之后的序列化对象。

Let’s Chat,安卓客户端,构建EchoMessage或EchoFile对象,然后发送到channel;EchoMessage与EchoFile用于服务端判断信息对象的类别。

Echo-Server,服务端。ChannelRead时判断信息对象类型,决定是广播到所有用户还是保存文件。

对于ByteBuf对象一直没有弄很明白,所以上述也就没有使用。

来张安卓端(小米PAD)Let’s Chat的运行截图:

Let's Chat小米Pad运行截图
Let’s Chat小米Pad运行截图

三星手机Let’s Chat运行截图:

Let's Chat三星手机运行截图
Let’s Chat三星手机运行截图

服务端(Echo-Server)的运行截图:

Echo-Server输出日志与说明截图
Echo-Server输出日志与说明截图

上传的文件:

QQ截图20160518132859

文件名格式为:Build.MANUFACTURE+UUID.randomUUID()+”.jpg”,第二张图片为12.9M,上传时间六七秒钟,应该还有优化的空间。

Echo-Pojo的代码就不截图了,直接下载查看就可以,或者也可以继续扩展,目前只是图片跟文字。

上述功能一共分为三个程序,Echo-Pojo信息交换对象使用eclipse-Mars2开发,Echo-Server使用Intellij idea开发,Let’s Chat使用Android Studio2,有点蛋疼,但好在实现了功能,中间折腾的很多,尤其公司电脑跟家里电脑jdk不一致,一个1.8,一个1.7,因为这个出了很多莫名的错误,也浪费了很多时间,中间的各种折腾各种烦躁就不记录了。

代码注释比较少,也有很多废弃的没有删掉,只是实现了功能可以运行,没有做完全整理,有问题可以直接回复或者@EMAIL ME

借鉴刘源的NettyFileTransfer,只是我把客户端修改成了Android,然后Netty版本我用的是4.0.36Final,感谢大神。

剩下的就是把功能揉进项目里了,Keep Fighting !

项目开源地址:https://github.com/LisonLiou/netty-learning.git

Android解决:The content of the adapter has changed but ListView did not receive a notification

项目中的错误,记录一下。

完整的错误信息如下:

大意是说adapter内容已改变,但listview未收到通知,上下文不同步了。

精简一下,我有两个ActivityA和ActivityB。首先打开ActivityA,显示一个列表(listView),然后点击一个按钮startActivityForResult打开了B,B中添加了信息提交后setResult到A。B负责添加数据,添加完数据回到A,通知A重新load一遍远端数据,没问题(不要问我为什么要重新load一遍)。

在Activity A中单独起了一个线程去处理任务(请求远端service获取数据),handler收到message之后启动这个线程t,然后Activity A又startActivityForResult了另一个Activity B(这时候ActivityA已经onPause了,但是线程依然在运行,而且还在handler的callback队列中),当Activity B处理完逻辑setResult给Activity A(并且把自己给finish掉),需要让ActivityA重新请求service数据,也就是说线程t要重新运行一次,这时候handler里面已经有线程t这个对象了,然后就导致了上述的错误(好像这么说很牵强啊),参照CSDN牛人的文章,还是线程与上下文的事。

解决办法,在ActivityA的onPause将线程t从handler的callback中移除(然后handler再次收到同样的请求service的message时会重新将此线程t加入到callback队列中),如下:

 

ActivityA的完整代码如下:

贴首歌在:

新解:

还是上面的错误信息,注意这句:

确保adapter的内容不要在后台线程中修改,只能从UI线程中修改。而我的代码是直接message交给handler去处理的,难道这也算后台线程?于是想到了Runnable对象,它是依附于UI线程的,然后使用了handler.post(new Runnable())的方法,测试成功。