-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
257 lines (243 loc) · 150 KB
/
search.xml
File metadata and controls
257 lines (243 loc) · 150 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[某国际银行开发中心工作体会]]></title>
<url>https://sogary.github.io/2016/08/08/%E6%9F%90%E5%9B%BD%E9%99%85%E9%93%B6%E8%A1%8C%E5%BC%80%E5%8F%91%E4%B8%AD%E5%BF%83%E5%B7%A5%E4%BD%9C%E4%BD%93%E4%BC%9A/</url>
<content type="html"><![CDATA[<p>五月份开始在公司工作到现在,今天在网上看到一篇华为自省的<a href="https://mp.weixin.qq.com/s?__biz=MjM5ODIzNTc2MA==&mid=2660757432&idx=1&sn=d72b38254d7da167bf76af9453519435&scene=1&srcid=0807JMH0sR0F43OnM3ImkJZh&key=8dcebf9e179c9f3aed19604d55d87ae392f21738eee708871e5de308b07599145f5d2e7ff09ee0dca7014611d89aad3e&ascene=0&uin=MTYzMTA0Mjk4MA%3D%3D&devicetype=iMac+MacBookPro11%2C2+OSX+OSX+10.12+build(16A270f)&version=11020201&pass_ticket=lbQBI%2FYT0xEPbDZM7%2BvOlKdBKKeZrvufiR8xlVmt7incnKzHuyV8OmhcJEZHDSkq" target="_blank" rel="external">文章</a>,感觉这公司有过之而无不及。文章我就不再累赘了,所有提到的点这里都有,而且技术更落后,管理更臃肿。</p>
<p>银行业控制的技术公司一般都会有各种各样的问题,因为银行有强大的资本后盾做支撑,所有东西都需要把风险降到最低,在互联网飞速发展的时代,银行业的技术根本没可能跟上技术潮流,也没必要跟上技术潮流。资本的强大一方面给技术公司一个强大的后盾,也在另一方面拖了技术发展的后退。乌龟🐢拖着重重的壳怎么可能跑得快。</p>
<a id="more"></a>
<h5 id="这种技术公司是时代的产物,但是很快会消亡">这种技术公司是时代的产物,但是很快会消亡</h5><p>在计算机技术的蛮荒时代,主流技术掌握在少数公司手上,普通公司需要进入技术领域门槛和成本太高,外包定制技术和购买产品服务成为市场主流。经过一段时间的技术发展和普及,技术的使用门槛不断降低,大量人才的出现,除了爆发一批互联网公司之外,有实力的行业也开始增设自己的技术部门和技术子公司。这家银行的技术子公司应该就是这个时代的产物。计算机技术的普及使各种产业能够更好地提高生产力,使传统公司有一定程度的飞跃。</p>
<p>计算机技术的发展速度简直是疯狂,不断有新技术颠覆和取代旧的技术,越来越多细分领域的出现对技术人才和公司管理的要求越来越高。要掌握新技术解放新的生产力,必须要随时调整公司策略。很多企业虽然有技术部门,但是一直固步自封,无办法自我颠覆,技术部门就会慢慢衰落。很多公司有自身的考虑,例如成本投入和风险控制等,颠覆总是无办法实现。时间越长,积累的问题会越来越多,旧的技术无办法满足新的需求和业务,最终可能会被抛弃或者推倒重来。华尔街很多资本巨头也在敬畏技术,但是资本的力量太大,华尔街和银行不会这么轻易倒闭,利用资本可以为自己翻身,买一个新的公司或者重新建立一个新的公司也不是大问题。</p>
<p>虽然银行根本不用非常担心技术发展这类事情,但是考虑到受雇佣的我们自身,在这种旧技术的熏陶下,如果我们没能跟上时代的脚步,最终我们还是会被资本无情抛弃。</p>
<h5 id="管理确实是难点">管理确实是难点</h5><p>管理的难点主要是文化差异和地域差异导致的。其他行业总是没有对互联网有深入的理解,所以管理起来效率相当低。了解银行业务需求和互联网开发的人才很少,而且新的技术部门肯定是由原有的高管做监管。最终,管理人员不懂技术,一线技术人员又是一些三流人员。在消耗巨大的沟通成本之后做出来的东西也是辣🐔。</p>
<p>跨国的沟通管理确实是非常耗费资源,而且没有非常好的解决方案。各地的作息时间差异导致沟通成本巨大,而且没有办法随时面对面交流会,会导致对事情理解有一定的偏差,最后偏差放大会影响整个项目。这边银行居然把核心技术团队分散在世界各地,这样的沟通想要完成一个好的平台简直是天荒夜谈。我个人觉得除了必要的精简团队可以分散在世界各地外,主要的核心团队应该在同一个地方。我们可以参考所有世界性的互联网公司,没有一个公司是把核心技术团队分散到世界各地的。</p>
<p>一个非常致命的问题,这个公司没有真实团队意识,不鼓励面对面沟通。大量的虚拟团队建立在通话会议和视像会议中,每天上班坐在你隔壁的人有可能几个月都不会跟你说一句话。本来在一起办公的同事也使用成本巨大的沟通方式,可想而知事情的推进效率是有多低。</p>
<p>在低效的协作环境里面,每个个体的能力会变得非常重要,独立完成任务的能力会快速得到提升。但是,这种提升是建立在每个个体都是积极面对事情的基础上。大部分人在这种情况都会堕落,变成一个推卸责任和不愿干活的怪物。这些怪物会逐渐吞噬公司,最终公司走向灭亡。</p>
<h5 id="拥有资本的公司不会失败,失败的只是我们">拥有资本的公司不会失败,失败的只是我们</h5><p>站在公司的角度在看这些问题,对于银行业来说,保证自身的资本力量才是最重要的。粗暴地说,有钱有啥做不了的。技术并不是基本核心,虽然日后会变成资本以外的重点,但是资本可以换来更好的技术。公司只要保证稳健的大额利润,之后的事情有钱可以办到。</p>
<p>对于员工个人,在一个下坡路的公司越走越远,迟早会被公司抛弃。互联网时代的技术变革太快,如果不努力学习新技术,赶上变革的节奏,当公司消亡的时候,自己也会跟着消亡。</p>
<p>有时候我们需要自私一点,公司总是会长远走下去的,但是你不一定能够跟着公司走下去。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[亚洲吃面公司的Email]]></title>
<url>https://sogary.github.io/2016/06/10/%E4%BA%9A%E6%B4%B2%E5%90%83%E9%9D%A2%E5%85%AC%E5%8F%B8%E7%9A%84Email/</url>
<content type="html"><![CDATA[<h1 id="To:_亚洲吃面公司">To: 亚洲吃面公司</h1><h2 id="Title:_工作总结">Title: 工作总结</h2><h3 id="Content:">Content:</h3><p>Hi 吃面公司,</p>
<p>由于我个人对公司理解的局限性,而且在公司的时间有限,我只能以一个技术男的理工科思维去看待公司,以自身和公司的利益去衡量我在公司期间的选择。有很多地方会跟大家理解的不一样,仅仅是想表达一下自己的想法,站在我自己的角度去看这个公司。</p>
<a id="more"></a>
<h4 id="在我眼中这是一家怎样的公司">在我眼中这是一家怎样的公司</h4><p>这个公司主要分为三部分:</p>
<ul>
<li>公司所有资源的连接中心:痞子</li>
<li>围绕设计、品牌创意、活动和线下店面的团队</li>
<li>公司长远战略储备团队</li>
</ul>
<p>痞子是这家公司的灵魂和精神支柱,他是公司的带领者而且是公司所有人的信仰。他身上连接着各种资源:设计创意、投资、餐饮人脉、管理、精神和战略。这是一家很明显是围绕一个核心人物而展开的公司,这个人物可以为公司注入源源不断的能源,使公司不断扩大发展。重点是这个人物是一个非同寻常的人,大家都能够被他的人格魅力所感染。有他的能量支撑,公司必定会越来越壮大。</p>
<p>公司的第二部分可以总结为这个公司的核心人物最为擅长的事情和所能企及的资源所组成的团队。这公司的品牌和设计绝对是业内的佼佼者。从自己最擅长的方面入手创办公司是一个很聪明的做法。通过品牌创意的资源去创办活动,扩大影响力,利用影响力去发展线下店面,线下店面更能够扩大影响力去宣传自己的品牌。这是一个非常良性的循环,而且公司也确实慢慢做到了。逼格的设计和给人印象深刻的活动,只能在这个公司找到了。</p>
<p>第三部分就是为公司长远战略做打算,完成一个较为伟大目标的团队。核心就是负责互联网的团队。这个团队是担负着公司的一个长远战略目标的,而且是消耗团队,前期无办法为公司提供资源和成长的帮助。公司确实是想做一个有趣的事情,使命和道路是没错的,需要的是团队的计划执行和艰苦奋斗。为这个目标去不断地去做事情。</p>
<p>当然我在公司里主要是负责第三部分。作为一个技术男,去执行互联网的具体实现,也是公司未来整个发展的方向。我觉得很荣幸,也谢谢公司一直以来的信任和支持。我也觉得公司的战略方向没有错,确实是可以结合公司实现的一个创新互联网协作模式。</p>
<h4 id="公司的运作模式">公司的运作模式</h4><p>这是一家善于设计、有创意、执行力极强和有长远战略目标的公司,但是公司缺乏短期计划和经验转化能力。公司的设计和创意相信是无容置疑的,绝对是业内顶尖水平。品牌设计和创意活动总是能吸引一大批人的眼球。但是,公司做事情的方式与其它公司有点不一样,公司的事情总是觉得很赶时间,而且不会因为做多了同类型的事情而改善。我觉得一个以核心人物为中心创立的公司,公司会在一定程度上与该人物的特点相似。公司会把人物的资源和优点放大,也一样会把人物的不足放大。</p>
<ul>
<li><p>短期计划和推进。公司应该有长远的目标和计划,但是对于管理者而言,短期的计划才能提高执行的效率。每个团队都必须要有短期的推进计划表,每周对照时间表做总结,尽早发现问题和解决问题。每周的推进会有每周的积累,这样做事就会不慌不忙按部就班。</p>
</li>
<li><p>做事流程的积累。对于每件事情,公司需要总结出一整套对内和对外的流程,并且明文确定下来可以供日后参考。每次做同一件事情可以不断修正改善流程,公司到后面才会越来越高效,不然后面人多了只会越来越乱。</p>
</li>
</ul>
<p>当然,公司的设计和创意积累已经非常丰富,但是那不是做事方法的积累。就像福特创造一台汽车和生产汽车的区别。福特自己创造汽车需要积累很多工程学、动力学和汽车相关的知识,自己才能亲手打造一台车。但是他后来创造的流水线作业去生产汽车,却更像是在管理上的做事方法的积累。这两个问题其实大家都知道,也一直存在在这个公司里面,但是为什么一直改不了呢?我们要看清楚这两个问题出现的原因,我相信大家都想去做这些改变,但是大家都没做或者没做成。</p>
<ul>
<li><p>事情多。由于核心人物的资源丰富,公司可以多点开花地发展,这本来是一件非常好的事情,但是有可能对管理人员和初始员工造成一定的压力,这对初始员工的要求很高。</p>
</li>
<li><p>没有明文规则。我知道公司倡导自由,自由也是这个公司的标志。但是我个人认为,觉对的自由只适用于足够优秀的人物,也就是能够非常清楚地认识到自我和自身所处的环境,对将要做的事情有非常准确的判断并且有非常强大的自制力和执行力的人。我自身不是这样的人,我相信大部分人也不是,但是那些特质是可以培养出来的,只是一定不会是在绝对自由的环境下培养出来。一些明文的规则还是要书面固定下来,有监督执行和奖惩机制,包括时间推荐表、每周总结之类的。</p>
</li>
<li><p>部门之间的协作不力。这里不是说一个部门没有在必要时候帮助另外一个部门,这里是说协作间的问题。例如,新的活动需要用到新的系统,活动中心做计划的时候需要数据中心提供开发计划才能真正落实整个活动安排。数据中心需要与管理人员和品牌中心确定需求,数据中心也需要确定交互,数据中心还需要品牌中心确定设计的时间计划,最后数据中心才能安排出开发计划。这里涉及到3个中心,当其中一个不能确定,就会引发其余两个不能顺利安排事情。事情会进入死循环。这种问题的解决方法其实很简单,每次做这种大事情,找一个人把这个事情的大旗给扛了,啥问题和进度都找他,他再去跟各个部门的人去确认安排,主动组织所有相关部门解决问题。</p>
</li>
</ul>
<h4 id="公司的发展">公司的发展</h4><p>我觉得吃面公司是不简单的公司。不是说这公司现在估值怎样,之后能怎么发展。我觉得是这公司能聚集人,能聚集一批牛人。动画片里面主角虽然很厉害,但是也要能聚集一般牛逼的小伙伴才能打败大Boss。这公司也一样,总是能找到很多的人和资源。终有一天这公司会为大家所熟知。这公司已经走在了社会的前面,高瞻远瞩,等着积累和爆发。</p>
<h4 id="我的选择">我的选择</h4><p>其实我离开的选择基本上是基于我对自身个人价值得失而作出的自私的判断。这个公司给了我一个全新的概念,就是公司未来只是一种组织形式,每个个人的价值才是最宝贵的。个人价值要在社会中才能体现,我自我评价的标尺是自己的家庭和工作。</p>
<p>每个人的一生会有不同的阶段。我给自己定义的是30岁之前的工作都是探索和积累。30岁之前我必须要认清楚自我,我自己是什么,喜欢什么,擅长干什么,哪里的工作比较合适。我不想日后几十年,我做的工作是我不喜欢的。如果我做不喜欢的工作,我肯定不会做好,也肯定不会成功。在这期间,我自己的认知和专业技术也在飞速成长,我感觉到自己的能力和之前有很大的不同,接触到不同的领域的东西对自己的改进和认知非常有帮助。</p>
<p>30岁之前,我尝试了改变技术宅形象去学双节棍和武术,享受无数次上台表演,我尝试了拼全力保送了大学的研究生,我尝试了体制内的大型垄断通讯行业的工作,我尝试了认认真真做一次互联网创业,我尝试了在一个大型传统制造业做智能硬件的行业改造,我尝试了在一家非常有创造力的文创公司做互联网技术,我正在尝试在一家跨国国际金融集团做互联网金融产品。</p>
<p>我选择离开并不是公司对我不好,只是我看清楚了一些东西(包括家庭和工作),对自身价值的再次评价造成了影响,使我重新做出了选择。我觉得公司某一天肯定是会成功的,如果我一直在,我肯定会搭上公司成功的便车。但是,在成功之前,我在公司里面学习到最多的应该是创新品牌、创投和设计方面的东西,而互联网部分需要我重新的管理和制定所有的东西,我不仅仅是执行,我是需要把整个思维和需求进行转化的人,因为公司里面基本没有人知道怎么去做一个App,做App不是想到什么就去写代码这么简单的,而我自己觉得我暂时没有这个能力去做好这个事情同时负责整个开发。需求不断变化会造成开发的成本非常大,开发不是一晚冲刺就能做出来的,最好是需求和设计定稿之后才能进行,粗放式管理不能控制开发过程。</p>
<p>家庭对我的影响也很大,我无办法全身心投入去创业的工作,亚洲吃面公司也是一个创业公司,我知道我必须要投入相当的精力才能做好初始员工的工作,但是对于我来说,工作归根到底是为了家庭,如果在家庭需要我的时候我无法顾及,那工作就失去了原本的意义。而且对于我个人,30岁之前我应该还不会真正停下来,我必须认识更多人,做更多不同的事情,去提升自己的认知。我可以告诉亚洲吃面公司,我走是因为我知道自己想要什么,但是我自己现在还没有能力去做,我要更快地提高我自己,我要去看更多的世界,站在不同的地方去评估自己的能力,等机会来临我会得到我自己想要的。请原谅理科生思维,对于机会成本计算,离开是我计算出来的最优决定。</p>
<p>Best regards,</p>
<p>soGary</p>
]]></content>
</entry>
<entry>
<title><![CDATA[工作和生活的游戏化]]></title>
<url>https://sogary.github.io/2016/04/18/%E5%B7%A5%E4%BD%9C%E5%92%8C%E7%94%9F%E6%B4%BB%E7%9A%84%E6%B8%B8%E6%88%8F%E5%8C%96/</url>
<content type="html"><![CDATA[<p>今天会议的一个有趣的point,稍微记录一下:</p>
<p>很多人人愿意花时间到游戏中却不愿意花时间去更加努力地工作。游戏在人的工作和生活中不是必需的,但是为什么它这么吸引人?</p>
<p>简单来说有八大驱动力:</p>
<ul>
<li>史诗意义与使命感</li>
<li>进步与成就感</li>
<li>创意授权与反馈</li>
<li>所有权与拥有感</li>
<li>社交影响与关联性</li>
<li>稀缺性与渴望</li>
<li>未知性与好奇心</li>
<li>损失与逃避心</li>
</ul>
<a id="more"></a>
<p>人生如戏,戏如人生。我觉得支持我们活着、工作和生活肯定也是这八个驱动力,有一点不一样的是游戏可以删档重来,人生不可以。可以说游戏的试错成本比人生少得多,所以游戏中会可能出现更多的创新和奇怪的东西,而真实世界人们做事都会估算后果才行动,大部分人会用评估出来的最高“期望值”去行动。</p>
<p>其实我们都活在游戏里面,规则的制定者叫政府,我们活在政府的法律规则下,所有人都不能打破这种规则,除非武装起义推翻政权,你成为了规则制定者。</p>
<p>我们想创造一个规则调动起我们的用户,其实我们是在建立一个帝国,我们是政府组织,这涉及到各种各样的规则,但是我觉得可以用一些简单的数学公式去描绘整个帝国的输入输出关系。</p>
<p>我们可以定义一个人在工作中的输入是时间TIME和技术Tech,每个人在社会中想得到的事物基本是钱MONEY、性SEX、爱好INTEREST和时间TIME。用户在使用我们系统的时候,会有以下的系统流程:</p>
<p>TIME+Tech (INPUT) –> 系统 –> MONEY+SEX+INTEREST+TIME (OUTPUT)</p>
<p>我们可以计算用户投入期望和输出期望(期望这里是一个数学概念,我们不需要每次投入产出都按照下面规则,但是一段稍长时间的总体输入输出需要满足下面规则,不懂请百度):</p>
<p>IF OUTPUT >= INPUT<br>THEN 用户会重复使用系统<br>ELSE 用户觉得系统是坑爹的永远不会再来</p>
<p>我们可以用数据来标准杯INPUT和OUTPUT。INPUT简单来说可以是用户的时薪,每个用户都会有工资或者每年的产出利润,划算成为时薪就可以是INPUT。OUTPUT的计算有主观性,除了MONEY和TIME可以计算,SEX和INTERST可以用大量数据做量化,但是不能主观计算。</p>
<p>简单来说,一个用户投入时间和技术到系统,他肯定会期望得到些什么,我们可以提供SEX、MONEY、INTEREST和TIME,通俗来说,平台可以给他YP、赚钱、得到创意和在别的地方省了时间。我们可以用大量的数据来计算这个期望值。一个良性的输入输出系统就像金融系统,资本总是不断壮大的,因为人类的总体生产价值在不断提高,如何做好一个游戏需要一整套想法,但是需要尽快行动以得到反馈。</p>
<p>其实要看这个系统是否健康,就看这个期望值(OUTPUT-INPUT)是不是非负的,我们只要确保这个期望值是非负,用户就会拥戴我们,我们就可以慢慢建立起整个帝国。看似只是一个期望值,但是要做的东西可不是这么简单。</p>
<p>努力吧~骚年。</p>
<p>———————以下是修正部分<br>后台我觉得我们做的事情不是建立一个国家,而是一种宗教信仰。宗教信仰是不是职业,信教的人也是业余信教的,只是这种思维贯穿了他们整个生活和工作。宗教是依靠一种价值观,一个巨大的故事背景,使信徒有使命感,利用教条去约束信徒的行为,并且要求信徒向宗教无私奉献。宗教是利用使命感驱动的,但是我们不是,我们是利用所谓的创造力驱动。我们是否可以建立这种使命感,还是别的东西,因为我觉得创造力始终不是能够使人信仰的东西。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[Retrofit的实现原理(二)]]></title>
<url>https://sogary.github.io/2016/01/28/Retrofit%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86-%E4%BA%8C/</url>
<content type="html"><![CDATA[<p>上篇文章我们已经了解了retrofit的RestAdapter adapter=new RestAdapter.Builder().setEndpoint(url).build()这段代码做了什么。</p>
<p>现在有下面一个接口,<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">SimplePOST</span></span>{</span><br><span class="line"> <span class="annotation">@POST</span>(<span class="string">"/android"</span>) </span><br><span class="line"> <span class="function">Response <span class="title">getResponse</span><span class="params">()</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>这篇我们就来了解下 SimplePOST simplePost= adapter.create(SimplePOST.class)的内部逻辑。</p>
<a id="more"></a>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <T> <span class="function">T <span class="title">create</span><span class="params">(Class<T> service)</span> </span>{</span><br><span class="line"> Utils.validateServiceClass(service);</span><br><span class="line"> <span class="keyword">return</span> (T) Proxy.newProxyInstance(service.getClassLoader(),</span><br><span class="line"> <span class="keyword">new</span> Class<?>[] { service }, <span class="comment">//动态代理</span></span><br><span class="line"> <span class="keyword">new</span> RestHandler(getMethodInfoCache(service)));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> <T> <span class="function"><span class="keyword">void</span> <span class="title">validateServiceClass</span><span class="params">(Class<T> service)</span> </span>{ </span><br><span class="line"><span class="comment">//确保create()参数是一个接口类型,且这个接口没有继承其他的接口.(使用动态代理的前提)</span></span><br><span class="line"> <span class="keyword">if</span> (!service.isInterface()) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(</span><br><span class="line"> <span class="string">"Only interface endpoint definitions are supported."</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (service.getInterfaces().length > <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(</span><br><span class="line"> <span class="string">"Interface definitions must not extend other interfaces."</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>可以发现adapter.create()方法的内部实现是利用动态代理生成了service接口的一个实现类。</p>
<p>根据动态代理的原理. 可以得知调用实现类的方法其实就是调用InvocationtHandler的对应方法。</p>
<p>这里简单介绍下动态代理。(关于动态代理的原理,可以参考其他博客的文章。)</p>
<p>委托类:被代理类即称为委托类。一般不直接调用委托类的方法,而是通过代理类来间接调用。</p>
<p>假定有委托类A,通过动态代理生成了代理类B,生成的时候需要建立一个InvocationHandler H。 实际我们调用代理类B的方法时,方法内部调用的是H的invoke()方法。 而一般H的invoke方法会调用A的同名方法,这样就实现了代理类B功能。</p>
<p>虽然这里是运用了动态代理的技术。但是却和一般的动态代理不一样。 一般的动态代理的InvocationHandler应该通过构造函数中传入委托类A。然后在invoke方法中调用A的方法,但这里是没有委托类的。只是利用动态代理自动生成接口的实现类。</p>
<p>因为java的动态代理是基于接口的,所以retrofit也要求用户自定义的也必须是一个接口。 </p>
<p>注意invocationHandler的invoke()方法执行是在我们调用接口的方法的时候执行的。对于上面的代码就simplepost.getResponse()执行的时候。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="class"><span class="keyword">class</span> <span class="title">RestHandler</span> <span class="keyword">implements</span> <span class="title">InvocationHandler</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Map<Method, RestMethodInfo> methodDetailsCache;</span><br><span class="line"> </span><br><span class="line"> RestHandler(Map<Method, RestMethodInfo> methodDetailsCache) {</span><br><span class="line"> <span class="comment">//一般的动态代理。InvocationHandler构造函数一般要传入委托类。</span></span><br><span class="line"> <span class="keyword">this</span>.methodDetailsCache = methodDetailsCache;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="annotation">@SuppressWarnings</span>(<span class="string">"unchecked"</span>) </span><br><span class="line"> <span class="annotation">@Override</span> <span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object proxy, Method method, <span class="keyword">final</span> Object[] args)</span> </span><br><span class="line"> <span class="comment">//动态代理的方法实现。调用委托类的方法,最终会调用invoke方法。</span></span><br><span class="line"> <span class="keyword">throws</span> Throwable </span>{</span><br><span class="line"> <span class="comment">// If the method is a method from Object then defer to normal invocation.</span></span><br><span class="line"> <span class="keyword">if</span> (method.getDeclaringClass() == Object.class) {</span><br><span class="line"> <span class="comment">//因为接口默认也继承Object。所以接口也有Object中的方法的。 如继承自Object如equals()方法</span></span><br><span class="line"> <span class="keyword">return</span> method.invoke(<span class="keyword">this</span>, args); </span><br><span class="line"> <span class="comment">//这里需要注意下,这里调用的是invocationHandler(H)的方法.一般的动态代理这里应该是调用委托类(A)的方法。</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Load or create the details cache for the current method.</span></span><br><span class="line"> <span class="keyword">final</span> RestMethodInfo methodInfo = getMethodInfo(methodDetailsCache, method); </span><br><span class="line"> <span class="comment">//把method和RestMethodInfo缓存起来。防止重复解析method。(把方法的注解,返回值,同步异步等信息都解析出来储存在RestMethodInfo中。)</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (methodInfo.isSynchronous) { <span class="comment">//同步的方式。</span></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">return</span> invokeRequest(requestInterceptor, methodInfo, args); </span><br><span class="line"> <span class="comment">//核心方法(网络访问)。可以看到retrofit的synchronous类型方法并不是子线程执行的。 所以在Android平台使用同步方式的retrofit的话要在子线程中。</span></span><br><span class="line"> } <span class="keyword">catch</span> (RetrofitError error) {</span><br><span class="line"> Throwable newError = errorHandler.handleError(error);</span><br><span class="line"> <span class="keyword">if</span> (newError == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(</span><br><span class="line"> <span class="string">"Error handler returned null for wrapped exception."</span>, </span><br><span class="line"> <span class="comment">//自定义的ErrorHandler的hanleError()方法不能return null。</span></span><br><span class="line"> error);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> newError; </span><br><span class="line"> <span class="comment">//注意,同步的方式,当遇到错误的时候,会抛出一个RuntimeException。在Android下尽量不要使用同步的方式(因为RuntimeException是不提示用户主动捕捉的)。</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (httpExecutor == <span class="keyword">null</span> || callbackExecutor == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(</span><br><span class="line"> <span class="string">"Asynchronous invocation requires calling setExecutors."</span>);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (methodInfo.isObservable) { <span class="comment">//rx的方式</span></span><br><span class="line"> <span class="keyword">if</span> (rxSupport == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">if</span> (Platform.HAS_RX_JAVA) {</span><br><span class="line"> rxSupport = <span class="keyword">new</span> RxSupport(httpExecutor, errorHandler, requestInterceptor);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(</span><br><span class="line"> <span class="string">"Observable method found but no RxJava on classpath."</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> rxSupport.createRequestObservable(<span class="keyword">new</span> RxSupport.Invoker() {</span><br><span class="line"> <span class="annotation">@Override</span> <span class="function"><span class="keyword">public</span> ResponseWrapper <span class="title">invoke</span><span class="params">(RequestInterceptor requestInterceptor)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> (ResponseWrapper) invokeRequest(requestInterceptor, methodInfo, args);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//同步, Observable方式都不是的话,肯定是异步的方式了。</span></span><br><span class="line"> <span class="comment">// Apply the interceptor synchronously, recording the interception so we can replay it later.</span></span><br><span class="line"> <span class="comment">// This way we still defer argument serialization to the background thread.</span></span><br><span class="line"> <span class="keyword">final</span> RequestInterceptorTape interceptorTape = <span class="keyword">new</span> RequestInterceptorTape();</span><br><span class="line"> requestInterceptor.intercept(interceptorTape);</span><br><span class="line"> </span><br><span class="line"> Callback<?> callback = (Callback<?>) args[args.length - <span class="number">1</span>];</span><br><span class="line"> httpExecutor.execute(<span class="keyword">new</span> CallbackRunnable(callback, callbackExecutor, errorHandler) { </span><br><span class="line"> <span class="comment">//可以看到在Android上异步方式是通过HttpExecutor执行的。是默认子线程执行的。 所以异步方式的retrofit不需要在子线程中执行。</span></span><br><span class="line"> <span class="annotation">@Override</span> <span class="function"><span class="keyword">public</span> ResponseWrapper <span class="title">obtainResponse</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> (ResponseWrapper) invokeRequest(interceptorTape, methodInfo, args);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>; <span class="comment">// Asynchronous methods should have return type of void.</span></span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span><br><span class="line">* Execute an HTTP request.</span><br><span class="line">*</span><br><span class="line">* <span class="doctag">@return</span> HTTP response object of specified {<span class="doctag">@code</span> type} or {<span class="doctag">@code</span> null}.</span><br><span class="line">* <span class="doctag">@throws</span> RetrofitError if any error occurs during the HTTP request.</span><br><span class="line">*/</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> Object <span class="title">invokeRequest</span><span class="params">(RequestInterceptor requestInterceptor,</span><br><span class="line"> RestMethodInfo methodInfo, Object[] args)</span> </span>{</span><br><span class="line"> </span><br><span class="line"> String url = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> methodInfo.init(); <span class="comment">// Ensure all relevant method information has been loaded. --->保证method的参数,返回值,注解都解析完成。 可以得到网络访问的url,header,query,访问方式等信息。</span></span><br><span class="line"> </span><br><span class="line"> String serverUrl = server.getUrl();</span><br><span class="line"> RequestBuilder requestBuilder = <span class="keyword">new</span> RequestBuilder(serverUrl, methodInfo, converter);</span><br><span class="line"> requestBuilder.setArguments(args);</span><br><span class="line"> </span><br><span class="line"> requestInterceptor.intercept(requestBuilder); <span class="comment">//在网络访问之前,执行拦截器的方法。 保证拦截器是最后起作用的。</span></span><br><span class="line"> </span><br><span class="line"> Request request = requestBuilder.build();</span><br><span class="line"> url = request.getUrl();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (!methodInfo.isSynchronous) {</span><br><span class="line"> <span class="comment">// If we are executing asynchronously then update the current thread with a useful name.</span></span><br><span class="line"> <span class="keyword">int</span> substrEnd = url.indexOf(<span class="string">"?"</span>, serverUrl.length());</span><br><span class="line"> <span class="keyword">if</span> (substrEnd == -<span class="number">1</span>) {</span><br><span class="line"> substrEnd = url.length();</span><br><span class="line"> }</span><br><span class="line"> Thread.currentThread().setName(THREAD_PREFIX</span><br><span class="line"> + url.substring(serverUrl.length(), substrEnd));</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (logLevel.log()) {</span><br><span class="line"> <span class="comment">// Log the request data.</span></span><br><span class="line"> request = logAndReplaceRequest(<span class="string">"HTTP"</span>, request, args);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> Object profilerObject = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">if</span> (profiler != <span class="keyword">null</span>) {</span><br><span class="line"> profilerObject = profiler.beforeCall();</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">long</span> start = System.nanoTime();</span><br><span class="line"> Response response = clientProvider.get().execute(request); </span><br><span class="line"> <span class="comment">//调用okHttp或者其他Client进行网络访问。并把返回的数据封装进retrofit的Response中。</span></span><br><span class="line"> <span class="keyword">long</span> elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">int</span> statusCode = response.getStatus(); <span class="comment">//返回码</span></span><br><span class="line"> <span class="keyword">if</span> (profiler != <span class="keyword">null</span>) {</span><br><span class="line"> RequestInformation requestInfo = getRequestInfo(serverUrl, methodInfo, request);</span><br><span class="line"> <span class="comment">//noinspection unchecked</span></span><br><span class="line"> profiler.afterCall(requestInfo, elapsedTime, statusCode, profilerObject);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (logLevel.log()) {</span><br><span class="line"> <span class="comment">// Log the response data.</span></span><br><span class="line"> response = logAndReplaceResponse(url, response, elapsedTime);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> Type type = methodInfo.responseObjectType;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (statusCode >= <span class="number">200</span> && statusCode < <span class="number">300</span>) { <span class="comment">// 2XX == successful request </span></span><br><span class="line"> <span class="comment">//返回码在200到300之间认为是一次成功的网络访问。</span></span><br><span class="line"> <span class="comment">// Caller requested the raw Response object directly.</span></span><br><span class="line"> <span class="keyword">if</span> (type.equals(Response.class)) { </span><br><span class="line"> <span class="comment">//如果方法的返回值类型(封装在responseObjectType)是retrofit的Response的话。 那就不用converter转换。</span></span><br><span class="line"> <span class="keyword">if</span> (!methodInfo.isStreaming) {</span><br><span class="line"> <span class="comment">// Read the entire stream and replace with one backed by a byte[].</span></span><br><span class="line"> response = Utils.readBodyToBytesIfNecessary(response);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (methodInfo.isSynchronous) { <span class="comment">//同步方式</span></span><br><span class="line"> <span class="keyword">return</span> response; </span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> ResponseWrapper(response, response); <span class="comment">//异步的时候返回的是这个。</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> TypedInput body = response.getBody();</span><br><span class="line"> <span class="keyword">if</span> (body == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">if</span> (methodInfo.isSynchronous) {</span><br><span class="line"> <span class="comment">//① 结合下面的② ,</span></span><br><span class="line"> <span class="comment">//返回值类型不同是因为invokeRequest()分别由2个不同的方法调用。</span></span><br><span class="line"> <span class="comment">//①是由 invoke()调用的。</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> ResponseWrapper(response, <span class="keyword">null</span>);</span><br><span class="line"> <span class="comment">//② 的情况是异步的。</span></span><br><span class="line"> <span class="comment">//是由callBack模式中的obtainResponse()中调用的。 </span></span><br><span class="line"> <span class="comment">//下面和上面的返回值类型不同的情况皆是如此</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> ExceptionCatchingTypedInput wrapped = <span class="keyword">new</span> ExceptionCatchingTypedInput(body);</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Object convert = converter.fromBody(wrapped, type); </span><br><span class="line"> <span class="comment">//方法的返回值是非Response。那么由Converter把Response转换成对应的类型。</span></span><br><span class="line"> logResponseBody(body, convert);</span><br><span class="line"> <span class="keyword">if</span> (methodInfo.isSynchronous) {</span><br><span class="line"> <span class="keyword">return</span> convert;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> ResponseWrapper(response, convert);</span><br><span class="line"> } <span class="keyword">catch</span> (ConversionException e) {</span><br><span class="line"> <span class="comment">// If the underlying input stream threw an exception, propagate that rather than</span></span><br><span class="line"> <span class="comment">// indicating that it was a conversion exception.</span></span><br><span class="line"> <span class="keyword">if</span> (wrapped.threwException()) {</span><br><span class="line"> <span class="keyword">throw</span> wrapped.getThrownException();</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// The response body was partially read by the converter. Replace it with null.</span></span><br><span class="line"> response = Utils.replaceResponseBody(response, <span class="keyword">null</span>);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">throw</span> RetrofitError.conversionError(url, response, converter, type, e);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> response = Utils.readBodyToBytesIfNecessary(response);</span><br><span class="line"> <span class="keyword">throw</span> RetrofitError.httpError(url, response, converter, type);</span><br><span class="line"> } <span class="keyword">catch</span> (RetrofitError e) {</span><br><span class="line"> <span class="keyword">throw</span> e; <span class="comment">// Pass through our own errors.</span></span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> <span class="keyword">if</span> (logLevel.log()) {</span><br><span class="line"> logException(e, url);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> RetrofitError.networkError(url, e);</span><br><span class="line"> } <span class="keyword">catch</span> (Throwable t) {</span><br><span class="line"> <span class="keyword">if</span> (logLevel.log()) {</span><br><span class="line"> logException(t, url);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> RetrofitError.unexpectedError(url, t);</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> <span class="keyword">if</span> (!methodInfo.isSynchronous) {</span><br><span class="line"> Thread.currentThread().setName(IDLE_THREAD_NAME);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>对于上面的getMethodInfo()方法, 是把method信息提取出来,封装到RestMethodInfo中。 包括访问方式。Headers,path,参数,返回值等。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">static</span> RestMethodInfo <span class="title">getMethodInfo</span><span class="params">(Map<Method, RestMethodInfo> cache, Method method)</span> </span>{</span><br><span class="line"> <span class="keyword">synchronized</span> (cache) {</span><br><span class="line"> RestMethodInfo methodInfo = cache.get(method);</span><br><span class="line"> <span class="keyword">if</span> (methodInfo == <span class="keyword">null</span>) { </span><br><span class="line"> <span class="comment">//经典的逻辑,如果缓存中有就从缓存中拿,如果没有,就生成一个新的,并且放到缓存中。</span></span><br><span class="line"> methodInfo = <span class="keyword">new</span> RestMethodInfo(method);</span><br><span class="line"> cache.put(method, methodInfo);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> methodInfo;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="title">strong</span>></span>RestMethodInfo<span class="tag"></<span class="title">strong</span>></span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">RestMethodInfo</span> </span>{</span><br><span class="line"> <span class="keyword">final</span> Method method;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">boolean</span> loaded = <span class="keyword">false</span>; <span class="comment">//方法是否已经load过(解析过)</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Method-level details</span></span><br><span class="line"> <span class="keyword">final</span> ResponseType responseType;</span><br><span class="line"> <span class="keyword">final</span> <span class="keyword">boolean</span> isSynchronous; <span class="comment">//方法是同步还是异步</span></span><br><span class="line"> <span class="keyword">final</span> <span class="keyword">boolean</span> isObservable;</span><br><span class="line"> Type responseObjectType;</span><br><span class="line"> RequestType requestType = RequestType.SIMPLE;</span><br><span class="line"> String requestMethod;</span><br><span class="line"> <span class="keyword">boolean</span> requestHasBody;</span><br><span class="line"> String requestUrl; </span><br><span class="line"> Set<String> requestUrlParamNames;</span><br><span class="line"> String requestQuery;</span><br><span class="line"> List<retrofit.client.Header> headers;</span><br><span class="line"> String contentTypeHeader;</span><br><span class="line"> <span class="keyword">boolean</span> isStreaming;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">enum</span> ResponseType { <span class="comment">//方法的返回值是什么类型</span></span><br><span class="line"> VOID, <span class="comment">//void代表没有返回值,-->异步的方式</span></span><br><span class="line"> OBSERVABLE, <span class="comment">//rxjava</span></span><br><span class="line"> OBJECT <span class="comment">//方法的返回值是对象--->同步的方式</span></span><br><span class="line"> }</span><br><span class="line"> RestMethodInfo(Method method) {</span><br><span class="line"> <span class="keyword">this</span>.method = method;</span><br><span class="line"> responseType = parseResponseType();</span><br><span class="line"> isSynchronous = (responseType == ResponseType.OBJECT);</span><br><span class="line"> isObservable = (responseType == ResponseType.OBSERVABLE);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">private</span> ResponseType <span class="title">parseResponseType</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="comment">// Synchronous methods have a non-void return type. </span></span><br><span class="line"> <span class="comment">//同步的方法有一个非void的返回值</span></span><br><span class="line"> <span class="comment">// Observable methods have a return type of Observable.</span></span><br><span class="line"> <span class="comment">//Observable的方法返回值类型应该是Observable</span></span><br><span class="line"> Type returnType = method.getGenericReturnType();</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Asynchronous methods should have a Callback type as the last argument. </span></span><br><span class="line"> <span class="comment">//异步的方法最后一个方法的参数类型应该是Callback。</span></span><br><span class="line"> Type lastArgType = nul;</span><br><span class="line"> Class<?> lastArgClass = <span class="keyword">null</span>;</span><br><span class="line"> Type[] parameterTypes = method.getGenericParameterTypes();</span><br><span class="line"> <span class="keyword">if</span> (parameterTypes.length > <span class="number">0</span>) {</span><br><span class="line"> Type typeToCheck = parameterTypes[parameterTypes.length - <span class="number">1</span>];</span><br><span class="line"> lastArgType = typeToCheck;</span><br><span class="line"> <span class="keyword">if</span> (typeToCheck <span class="keyword">instanceof</span> ParameterizedType) {</span><br><span class="line"> typeToCheck = ((ParameterizedType) typeToCheck).getRawType();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (typeToCheck <span class="keyword">instanceof</span> Class) {</span><br><span class="line"> lastArgClass = (Class<?>) typeToCheck;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">boolean</span> hasReturnType = returnType != <span class="keyword">void</span>.class;</span><br><span class="line"> <span class="keyword">boolean</span> hasCallback = lastArgClass != <span class="keyword">null</span> && </span><br><span class="line"> Callback.class.isAssignableFrom(lastArgClass); <span class="comment">//如果有CallBack, CallBack只能是最后一个参数。</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Check for invalid configurations.</span></span><br><span class="line"> <span class="keyword">if</span> (hasReturnType && hasCallback) { </span><br><span class="line"> <span class="comment">//返回值是非void类型和方法有CallBack参数有且只能有一个满足</span></span><br><span class="line"> <span class="keyword">throw</span> methodError(</span><br><span class="line"> <span class="string">"Must have return type or Callback as last argument, not both."</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (!hasReturnType && !hasCallback) {</span><br><span class="line"> <span class="keyword">throw</span> methodError(</span><br><span class="line"> <span class="string">"Must have either a return type or Callback as last argument."</span>);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (hasReturnType) {</span><br><span class="line"> <span class="keyword">if</span> (Platform.HAS_RX_JAVA) {</span><br><span class="line"> Class rawReturnType = Types.getRawType(returnType);</span><br><span class="line"> <span class="keyword">if</span> (RxSupport.isObservable(rawReturnType)) {</span><br><span class="line"> returnType = RxSupport.getObservableType(returnType, rawReturnType);</span><br><span class="line"> responseObjectType = getParameterUpperBound((ParameterizedType) returnType);</span><br><span class="line"> <span class="keyword">return</span> ResponseType.OBSERVABLE;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> responseObjectType = returnType;</span><br><span class="line"> <span class="keyword">return</span> ResponseType.OBJECT;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> lastArgType = Types.getSupertype(lastArgType,</span><br><span class="line"> Types.getRawType(lastArgType), Callback.class);</span><br><span class="line"> <span class="keyword">if</span> (lastArgType <span class="keyword">instanceof</span> ParameterizedType) {</span><br><span class="line"> responseObjectType = getParameterUpperBound((ParameterizedType) lastArgType);</span><br><span class="line"> <span class="keyword">return</span> ResponseType.VOID;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">throw</span> methodError(</span><br><span class="line"> <span class="string">"Last parameter must be of type Callback<X> or Callback<? super X>."</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parsePath</span><span class="params">(String path)</span> </span>{</span><br><span class="line"> <span class="comment">//解析路径 如GET(string),注意这里会对string进行判断,必须以"/"开头。所以不能是空字符串,如""</span></span><br><span class="line"> ...........</span><br><span class="line"> }</span><br><span class="line"> List<retrofit.client.Header> parseHeaders(String[] headers) { <span class="comment">//解析Headers注解。</span></span><br><span class="line"> ...........</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseParameters</span><span class="params">()</span> </span>{ <span class="comment">//解析方法参数,如方法参数的@Header,@Query等。</span></span><br><span class="line"> ...........</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseMethodAnnotations</span><span class="params">()</span> </span>{ <span class="comment">//解析http方式。如GET(),POST()</span></span><br><span class="line"> ...........</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
</entry>
<entry>
<title><![CDATA[Android必备小代码段]]></title>
<url>https://sogary.github.io/2016/01/28/Android%E5%BF%85%E5%A4%87%E5%B0%8F%E4%BB%A3%E7%A0%81%E6%AE%B5/</url>
<content type="html"><![CDATA[<h4 id="拨打电话">拨打电话</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">call</span><span class="params">(Context context, String phoneNumber)</span> </span>{</span><br><span class="line"> context.startActivity(<span class="keyword">new</span> Intent(Intent.ACTION_CALL,</span><br><span class="line"> Uri.parse(<span class="string">"tel:"</span> + phoneNumber)));</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="跳转至拨号界面">跳转至拨号界面</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">callDial</span><span class="params">(Context context, String phoneNumber)</span> </span>{</span><br><span class="line"> context.startActivity(<span class="keyword">new</span> Intent(Intent.ACTION_DIAL,</span><br><span class="line"> Uri.parse(<span class="string">"tel:"</span> + phoneNumber)));</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<a id="more"></a>
<h4 id="发送短信">发送短信</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">sendSms</span><span class="params">(Context context, String phoneNumber, String content)</span> </span>{</span><br><span class="line"> Uri uri = Uri.parse(<span class="string">"smsto:"</span> + </span><br><span class="line"> (TextUtils.isEmpty(phoneNumber) ? <span class="string">""</span> : phoneNumber));</span><br><span class="line"> Intent intent = <span class="keyword">new</span> Intent(Intent.ACTION_SENDTO, uri);</span><br><span class="line"> intent.putExtra(<span class="string">"sms_body"</span>, </span><br><span class="line"> TextUtils.isEmpty(content) ? <span class="string">""</span> : content);</span><br><span class="line"> context.startActivity(intent);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="唤醒屏幕并解锁">唤醒屏幕并解锁</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">wakeUpAndUnlock</span><span class="params">(Context context)</span></span>{ </span><br><span class="line"> KeyguardManager km= (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); KeyguardManager.KeyguardLock kl = km.newKeyguardLock(<span class="string">"unLock"</span>); </span><br><span class="line"> <span class="comment">//解锁 </span></span><br><span class="line"> kl.disableKeyguard(); </span><br><span class="line"> <span class="comment">//获取电源管理器对象 </span></span><br><span class="line"> PowerManager pm=(PowerManager) context.getSystemService(Context.POWER_SERVICE); </span><br><span class="line"> <span class="comment">//获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag </span></span><br><span class="line"> PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | </span><br><span class="line"> PowerManager.SCREEN_DIM_WAKE_LOCK,<span class="string">"bright"</span>); </span><br><span class="line"> <span class="comment">//点亮屏幕 </span></span><br><span class="line"> wl.acquire(); </span><br><span class="line"> <span class="comment">//释放 </span></span><br><span class="line"> wl.release(); </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="需要添加权限">需要添加权限</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="title">uses-permission</span> <span class="attribute">android:name</span>=<span class="value">"android.permission.WAKE_LOCK"</span> /></span></span><br><span class="line"><span class="tag"><<span class="title">uses-permission</span> <span class="attribute">android:name</span>=<span class="value">"android.permission.DISABLE_KEYGUARD"</span> /></span></span><br></pre></td></tr></table></figure>
<h4 id="判断当前App处于前台还是后台状态">判断当前App处于前台还是后台状态</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isApplicationBackground</span><span class="params">(<span class="keyword">final</span> Context context)</span> </span>{</span><br><span class="line"> ActivityManager am = (ActivityManager) context</span><br><span class="line"> .getSystemService(Context.ACTIVITY_SERVICE);</span><br><span class="line"> <span class="annotation">@SuppressWarnings</span>(<span class="string">"deprecation"</span>)</span><br><span class="line"> List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(<span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (!tasks.isEmpty()) {</span><br><span class="line"> ComponentName topActivity = tasks.get(<span class="number">0</span>).topActivity;</span><br><span class="line"> <span class="keyword">if</span> (!topActivity.getPackageName().equals(context.getPackageName())) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="判断当前手机是否处于锁屏(睡眠)状态">判断当前手机是否处于锁屏(睡眠)状态</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isSleeping</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> KeyguardManager kgMgr = (KeyguardManager) context</span><br><span class="line"> .getSystemService(Context.KEYGUARD_SERVICE);</span><br><span class="line"> <span class="keyword">boolean</span> isSleeping = kgMgr.inKeyguardRestrictedInputMode();</span><br><span class="line"> <span class="keyword">return</span> isSleeping;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="判断当前是否有网络连接">判断当前是否有网络连接</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isOnline</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> ConnectivityManager manager = (ConnectivityManager) context</span><br><span class="line"> .getSystemService(Activity.CONNECTIVITY_SERVICE);</span><br><span class="line"> NetworkInfo info = manager.getActiveNetworkInfo();</span><br><span class="line"> <span class="keyword">if</span> (info != <span class="keyword">null</span> && info.isConnected()) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="判断当前是否是WIFI连接状态">判断当前是否是WIFI连接状态</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isWifiConnected</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> ConnectivityManager connectivityManager = (ConnectivityManager) context</span><br><span class="line"> .getSystemService(Context.CONNECTIVITY_SERVICE);</span><br><span class="line"> NetworkInfo wifiNetworkInfo = connectivityManager</span><br><span class="line"> .getNetworkInfo(ConnectivityManager.TYPE_WIFI);</span><br><span class="line"> <span class="keyword">if</span> (wifiNetworkInfo.isConnected()) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="安装APK">安装APK</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">installApk</span><span class="params">(Context context, File file)</span> </span>{</span><br><span class="line"> Intent intent = <span class="keyword">new</span> Intent();</span><br><span class="line"> intent.setAction(<span class="string">"android.intent.action.VIEW"</span>);</span><br><span class="line"> intent.addCategory(<span class="string">"android.intent.category.DEFAULT"</span>);</span><br><span class="line"> intent.setType(<span class="string">"application/vnd.android.package-archive"</span>);</span><br><span class="line"> intent.setDataAndType(Uri.fromFile(file),</span><br><span class="line"> <span class="string">"application/vnd.android.package-archive"</span>);</span><br><span class="line"> intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);</span><br><span class="line"> context.startActivity(intent);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="判断当前设备是否为手机">判断当前设备是否为手机</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isPhone</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> TelephonyManager telephony = (TelephonyManager) context</span><br><span class="line"> .getSystemService(Context.TELEPHONY_SERVICE);</span><br><span class="line"> <span class="keyword">if</span> (telephony.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="获取当前设备宽高,单位px">获取当前设备宽高,单位px</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@SuppressWarnings</span>(<span class="string">"deprecation"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getDeviceWidth</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> WindowManager manager = (WindowManager) context</span><br><span class="line"> .getSystemService(Context.WINDOW_SERVICE);</span><br><span class="line"> <span class="keyword">return</span> manager.getDefaultDisplay().getWidth();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="annotation">@SuppressWarnings</span>(<span class="string">"deprecation"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getDeviceHeight</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> WindowManager manager = (WindowManager) context</span><br><span class="line"> .getSystemService(Context.WINDOW_SERVICE);</span><br><span class="line"> <span class="keyword">return</span> manager.getDefaultDisplay().getHeight();</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="获取当前设备的IMEI,需要与上面的isPhone()一起使用">获取当前设备的IMEI,需要与上面的isPhone()一起使用</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@TargetApi</span>(Build.VERSION_CODES.CUPCAKE)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getDeviceIMEI</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> String deviceId;</span><br><span class="line"> <span class="keyword">if</span> (isPhone(context)) {</span><br><span class="line"> TelephonyManager telephony = (TelephonyManager) context</span><br><span class="line"> .getSystemService(Context.TELEPHONY_SERVICE);</span><br><span class="line"> deviceId = telephony.getDeviceId();</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> deviceId = Settings.Secure.getString(context.getContentResolver(),</span><br><span class="line"> Settings.Secure.ANDROID_ID);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> deviceId;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="获取当前设备的MAC地址">获取当前设备的MAC地址</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getMacAddress</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> String macAddress;</span><br><span class="line"> WifiManager wifi = (WifiManager) context</span><br><span class="line"> .getSystemService(Context.WIFI_SERVICE);</span><br><span class="line"> WifiInfo info = wifi.getConnectionInfo();</span><br><span class="line"> macAddress = info.getMacAddress();</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == macAddress) {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">""</span>;</span><br><span class="line"> }</span><br><span class="line"> macAddress = macAddress.replace(<span class="string">":"</span>, <span class="string">""</span>);</span><br><span class="line"> <span class="keyword">return</span> macAddress;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="获取当前程序的版本号">获取当前程序的版本号</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getAppVersion</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> String version = <span class="string">"0"</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> version = context.getPackageManager().getPackageInfo(</span><br><span class="line"> context.getPackageName(), <span class="number">0</span>).versionName;</span><br><span class="line"> } <span class="keyword">catch</span> (PackageManager.NameNotFoundException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> version;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="收集设备信息,用于信息统计分析">收集设备信息,用于信息统计分析</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Properties <span class="title">collectDeviceInfo</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> Properties mDeviceCrashInfo = <span class="keyword">new</span> Properties();</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> PackageManager pm = context.getPackageManager();</span><br><span class="line"> PackageInfo pi = pm.getPackageInfo(context.getPackageName(),</span><br><span class="line"> PackageManager.GET_ACTIVITIES);</span><br><span class="line"> <span class="keyword">if</span> (pi != <span class="keyword">null</span>) {</span><br><span class="line"> mDeviceCrashInfo.put(VERSION_NAME,</span><br><span class="line"> pi.versionName == <span class="keyword">null</span> ? <span class="string">"not set"</span> : pi.versionName);</span><br><span class="line"> mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (PackageManager.NameNotFoundException e) {</span><br><span class="line"> Log.e(TAG, <span class="string">"Error while collect package info"</span>, e);</span><br><span class="line"> }</span><br><span class="line"> Field[] fields = Build.class.getDeclaredFields();</span><br><span class="line"> <span class="keyword">for</span> (Field field : fields) {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> field.setAccessible(<span class="keyword">true</span>);</span><br><span class="line"> mDeviceCrashInfo.put(field.getName(), field.get(<span class="keyword">null</span>));</span><br><span class="line"> } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line"> Log.e(TAG, <span class="string">"Error while collect crash info"</span>, e);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> mDeviceCrashInfo;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">collectDeviceInfoStr</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> Properties prop = collectDeviceInfo(context);</span><br><span class="line"> Set deviceInfos = prop.keySet();</span><br><span class="line"> StringBuilder deviceInfoStr = <span class="keyword">new</span> StringBuilder(<span class="string">"{\n"</span>);</span><br><span class="line"> <span class="keyword">for</span> (Iterator iter = deviceInfos.iterator(); iter.hasNext();) {</span><br><span class="line"> Object item = iter.next();</span><br><span class="line"> deviceInfoStr.append(<span class="string">"\t\t\t"</span> + item + <span class="string">":"</span> + prop.get(item)</span><br><span class="line"> + <span class="string">", \n"</span>);</span><br><span class="line"> }</span><br><span class="line"> deviceInfoStr.append(<span class="string">"}"</span>);</span><br><span class="line"> <span class="keyword">return</span> deviceInfoStr.toString();</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="是否有SD卡">是否有SD卡</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">haveSDCard</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> android.os.Environment.getExternalStorageState().equals(</span><br><span class="line"> android.os.Environment.MEDIA_MOUNTED);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="动态隐藏软键盘">动态隐藏软键盘</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@TargetApi</span>(Build.VERSION_CODES.CUPCAKE)</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">hideSoftInput</span><span class="params">(Activity activity)</span> </span>{</span><br><span class="line"> View view = activity.getWindow().peekDecorView();</span><br><span class="line"> <span class="keyword">if</span> (view != <span class="keyword">null</span>) {</span><br><span class="line"> InputMethodManager inputmanger = (InputMethodManager) activity</span><br><span class="line"> .getSystemService(Context.INPUT_METHOD_SERVICE);</span><br><span class="line"> inputmanger.hideSoftInputFromWindow(view.getWindowToken(), <span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="annotation">@TargetApi</span>(Build.VERSION_CODES.CUPCAKE)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">hideSoftInput</span><span class="params">(Context context, EditText edit)</span> </span>{</span><br><span class="line"> edit.clearFocus();</span><br><span class="line"> InputMethodManager inputmanger = (InputMethodManager) context</span><br><span class="line"> .getSystemService(Context.INPUT_METHOD_SERVICE);</span><br><span class="line"> inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), <span class="number">0</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="动态显示软键盘">动态显示软键盘</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@TargetApi</span>(Build.VERSION_CODES.CUPCAKE)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">showSoftInput</span><span class="params">(Context context, EditText edit)</span> </span>{</span><br><span class="line"> edit.setFocusable(<span class="keyword">true</span>);</span><br><span class="line"> edit.setFocusableInTouchMode(<span class="keyword">true</span>);</span><br><span class="line"> edit.requestFocus();</span><br><span class="line"> InputMethodManager inputManager = (InputMethodManager) context</span><br><span class="line"> .getSystemService(Context.INPUT_METHOD_SERVICE);</span><br><span class="line"> inputManager.showSoftInput(edit, <span class="number">0</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="动态显示或者是隐藏软键盘">动态显示或者是隐藏软键盘</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@TargetApi</span>(Build.VERSION_CODES.CUPCAKE)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">toggleSoftInput</span><span class="params">(Context context, EditText edit)</span> </span>{</span><br><span class="line"> edit.setFocusable(<span class="keyword">true</span>);</span><br><span class="line"> edit.setFocusableInTouchMode(<span class="keyword">true</span>);</span><br><span class="line"> edit.requestFocus();</span><br><span class="line"> InputMethodManager inputManager = (InputMethodManager) context</span><br><span class="line"> .getSystemService(Context.INPUT_METHOD_SERVICE);</span><br><span class="line"> inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, <span class="number">0</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="主动回到Home,后台运行">主动回到Home,后台运行</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">goHome</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> Intent mHomeIntent = <span class="keyword">new</span> Intent(Intent.ACTION_MAIN);</span><br><span class="line"> mHomeIntent.addCategory(Intent.CATEGORY_HOME);</span><br><span class="line"> mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK</span><br><span class="line"> | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);</span><br><span class="line"> context.startActivity(mHomeIntent);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="获取状态栏高度">获取状态栏高度</h4><p>注意,要在onWindowFocusChanged中调用,在onCreate中获取高度为0<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@TargetApi</span>(Build.VERSION_CODES.CUPCAKE)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getStatusBarHeight</span><span class="params">(Activity activity)</span> </span>{</span><br><span class="line"> Rect frame = <span class="keyword">new</span> Rect();</span><br><span class="line"> activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);</span><br><span class="line"> <span class="keyword">return</span> frame.top;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<h4 id="获取状态栏高度+标题栏(ActionBar)高度">获取状态栏高度+标题栏(ActionBar)高度</h4><p>(注意,如果没有ActionBar,那么获取的高度将和上面的是一样的,只有状态栏的高度)<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getTopBarHeight</span><span class="params">(Activity activity)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT)</span><br><span class="line"> .getTop();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<h4 id="获取MCC+MNC代码_(SIM卡运营商国家代码和运营商网络代码)">获取MCC+MNC代码 (SIM卡运营商国家代码和运营商网络代码)</h4><p>仅当用户已在网络注册时有效, CDMA 可能会无效(中国移动:46000 46002, 中国联通:46001,中国电信:46003)<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getNetworkOperator</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> TelephonyManager telephonyManager = (TelephonyManager) context</span><br><span class="line"> .getSystemService(Context.TELEPHONY_SERVICE);</span><br><span class="line"> <span class="keyword">return</span> telephonyManager.getNetworkOperator();</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p>
<h4 id="返回移动网络运营商的名字">返回移动网络运营商的名字</h4><p>(例:中国联通、中国移动、中国电信) 仅当用户已在网络注册时有效, CDMA 可能会无效)<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getNetworkOperatorName</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> TelephonyManager telephonyManager = (TelephonyManager) context</span><br><span class="line"> .getSystemService(Context.TELEPHONY_SERVICE);</span><br><span class="line"> <span class="keyword">return</span> telephonyManager.getNetworkOperatorName();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<h4 id="返回移动终端类型">返回移动终端类型</h4><ul>
<li>PHONE_TYPE_NONE :0 手机制式未知</li>
<li>PHONE_TYPE_GSM :1 手机制式为GSM,移动和联通</li>
<li>PHONE_TYPE_CDMA :2 手机制式为CDMA,电信</li>
<li>PHONE_TYPE_SIP:3</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getPhoneType</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> TelephonyManager telephonyManager = (TelephonyManager) context</span><br><span class="line"> .getSystemService(Context.TELEPHONY_SERVICE);</span><br><span class="line"> <span class="keyword">return</span> telephonyManager.getPhoneType();</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="判断手机连接的网络类型(2G,3G,4G)">判断手机连接的网络类型(2G,3G,4G)</h4><p>联通的3G为UMTS或HSDPA,移动和联通的2G为GPRS或EGDE,电信的2G为CDMA,电信的3G为EVDO<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Constants</span> </span>{</span><br><span class="line"> <span class="comment">/**</span><br><span class="line"> * Unknown network class</span><br><span class="line"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> NETWORK_CLASS_UNKNOWN = <span class="number">0</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span><br><span class="line"> * wifi net work</span><br><span class="line"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> NETWORK_WIFI = <span class="number">1</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span><br><span class="line"> * "2G" networks</span><br><span class="line"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> NETWORK_CLASS_2_G = <span class="number">2</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span><br><span class="line"> * "3G" networks</span><br><span class="line"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> NETWORK_CLASS_3_G = <span class="number">3</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span><br><span class="line"> * "4G" networks</span><br><span class="line"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> NETWORK_CLASS_4_G = <span class="number">4</span>;</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getNetWorkClass</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> TelephonyManager telephonyManager = (TelephonyManager) context</span><br><span class="line"> .getSystemService(Context.TELEPHONY_SERVICE);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">switch</span> (telephonyManager.getNetworkType()) {</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_GPRS:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_EDGE:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_CDMA:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_1xRTT:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_IDEN:</span><br><span class="line"> <span class="keyword">return</span> Constants.NETWORK_CLASS_2_G;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_UMTS:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_EVDO_0:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_EVDO_A:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_HSDPA:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_HSUPA:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_HSPA:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_EVDO_B:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_EHRPD:</span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_HSPAP:</span><br><span class="line"> <span class="keyword">return</span> Constants.NETWORK_CLASS_3_G;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">case</span> TelephonyManager.NETWORK_TYPE_LTE:</span><br><span class="line"> <span class="keyword">return</span> Constants.NETWORK_CLASS_4_G;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">return</span> Constants.NETWORK_CLASS_UNKNOWN;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<h4 id="判断当前手机的网络类型(WIFI还是2,3,4G)">判断当前手机的网络类型(WIFI还是2,3,4G)</h4><p>需要用到上面的方法<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getNetWorkStatus</span><span class="params">(Context context)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> netWorkType = Constants.NETWORK_CLASS_UNKNOWN;</span><br><span class="line"> </span><br><span class="line"> ConnectivityManager connectivityManager = (ConnectivityManager) context</span><br><span class="line"> .getSystemService(Context.CONNECTIVITY_SERVICE);</span><br><span class="line"> NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (networkInfo != <span class="keyword">null</span> && networkInfo.isConnected()) {</span><br><span class="line"> <span class="keyword">int</span> type = networkInfo.getType();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (type == ConnectivityManager.TYPE_WIFI) {</span><br><span class="line"> netWorkType = Constants.NETWORK_WIFI;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (type == ConnectivityManager.TYPE_MOBILE) {</span><br><span class="line"> netWorkType = getNetWorkClass(context);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> netWorkType;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<blockquote>
<p>来源:赵凯强(@裸奔的凯子哥)<br>链接:<a href="http://blog.csdn.net/zhaokaiqiang1992/article/details/44724057" target="_blank" rel="external">http://blog.csdn.net/zhaokaiqiang1992/article/details/44724057</a></p>
</blockquote>
]]></content>
</entry>
<entry>
<title><![CDATA[传统硬件厂商的体验]]></title>
<url>https://sogary.github.io/2015/12/13/%E4%BC%A0%E7%BB%9F%E7%A1%AC%E4%BB%B6%E5%8E%82%E5%95%86%E7%9A%84%E4%BD%93%E9%AA%8C/</url>
<content type="html"><![CDATA[<p>适应一个新环境并不容易,虽然工作内容变化不会变化太大,但是跨行业必须要对所在行业领域进行深入了解才能做好看似一样的工作。就像同样是法务,在协助上市公司IPO法律资讯和普通公司的标签知识产权维护两种方向上,大致工作内容应该是差不多,也就是辅助和保证公司合法完成各项事项,但是对于行业的理解所偏重的细节就会差别很大。</p>
<a id="more"></a>
<h3 id="国家垄断通信运营商">国家垄断通信运营商</h3><p>国家垄断通信运营商其实也是在苦苦挣扎,整个体制决定了这种企业没有活力,但是也不会灭亡。互联网行业不断对运营商进行冲击,其实运营商有两条路可以走:一是大规模扩展和创新业务与互联网进行竞争,二是裁减缩窄业务更加专注于通信网络,扎实做好自己的价值。</p>
<p>显而易见,骄傲的运营只会选择第一条路。他们新建了很多互联网公司,做App、电商和支付,直接与现有的互联网产品竞争。有钱就是任性,看他们什么时候能烧死自己。运营商为什么注定失败呢?其中有三点:</p>
<ul>
<li>运营商没有市场的触觉。运营商所有产品基本都是按照“上头”指示去做。这对领导者的要求非常高,而运营商的领导者并不是企业家,他们没有企业家的触觉,甚至对自身业务都不了解,他们只是政治家。</li>
<li>运营商没有技术核心。运营商在技术上根本一点竞争力都没有,所有系统都是外包技术,甚至运营商的命根子通信技术也是外包。运营商根本不可能在技术上进行创新,去优化社会资源或者社会资源配置。</li>
<li>运营商没有互联网运营经验。运营商的姿态一直是客户跟着运营商走,运营商说啥是啥,这种垄断经济使运营商根本不了解市场和客户。但是,互联网行业对用户体验和感知非常敏感,运营商无法做好。</li>
</ul>
<p>其实第二条路更适合运营商,通信一直是刚需而且是国家垄断的,扎扎实实做深入才是硬道理。但是,这条路会远离大众用户,淡出公众视野。</p>
<h3 id="互联网企业">互联网企业</h3><p>互联网创业潮正在兴起,也正在衰落。千千万万的企业崛起,千千万万的企业倒闭。投身创业使我成长非常快。肩负一个公司的所有技术和公司的部分其他职能,在大环境中艰难生存,真是毕生难忘的经历。很可惜这家公司没有给我带来原始积累,但是增加了我自身的个人价值。</p>
<p>互联网企业无疑是最有创新的企业。公司的年轻,员工的年轻和行业的年轻决定了这些企业非常有活力,能够带动社会前沿科技的革新。中国互联网公司和美国不一样,中国互联网公司很少在一个点上做到深度优化,大公司都会涉足各行各业以谋求稳步发展和减少试错风险。美国互联网企业很多都是集中精力把一个东西做到极致,例如苹果和特斯拉,这些企业所引领的变革才会引起社会的巨大进步。一个真正谋求创新的地方和一个追求利益的地方还是有所不同的。</p>
<p>互联网创业公司非常浮躁,他们总是口号大但是没有做很多实事,或者说想做实事却不懂怎么去做。我们都太年轻太多东西要学,总有一天我们都会实现自己的梦想。大家都有要坚持的东西,也会有要放弃的东西,一个意志坚定的人从不会因为环境而妥协。一直被社会高估的互联网公司,泡沫终究会调整得与社会相匹配。我们回过头看会觉得自己真的可笑。</p>
<h3 id="传统制造企业">传统制造企业</h3><p>传统制造业企业能够活到现在,一定会有原因。他们为社会提供价值,提供制造业的创新。传统制造业的生产效率非常高,因为他们拥有自身的一整套生产流程,基本不需要借助外接进行生产协助,只要外接物流和销售就可以使产品快速退出市场。我本以为大部分企业的行业和社会触觉都很敏锐,只是局限于庞大的管理生产系统而没办法快速适应市场。但是,我进入这个行业之后发觉并不是这样的。我觉得他们的管理导致某方面的触觉非常不敏感,他们能够在制造业本身范围内进行高效率运作,但是缺少对外界的敏感,而且做起创新来畏首畏尾,所以革新产品迟迟不会推出市场。</p>
<p>传统企业喜欢埋头苦干的员工,喜欢一颗颗螺丝钉组装称为一个高效的团队,再加上传统企业低调而注重质量的不光鲜外表。当他们想涉足互联网领域的时候,很难吸引顶级人才。传统企业的团队气质很难进行创新,低调而沉稳的性格可以在本领域不断创新,但是一旦涉及到领域外就有点束手无策了。</p>
<h3 id="总结">总结</h3><p>我本身热爱互联网,希望能在传统企业学习到更多的东西,帮助他们进入互联网领域,也帮助我自己实现自己的梦想。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[Retrofit的实现原理(一)]]></title>
<url>https://sogary.github.io/2015/11/17/Retrofit%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86-%E4%B8%80/</url>
<content type="html"><![CDATA[<p>Retrofit框架实现的这么巧妙,虽然我们不需要再造一个轮子,但研究下轮子的实现还是很有帮助的。</p>
<p>Retrofit有几个关键的地方:</p>
<ul>
<li>用户自定义的接口和接口方法.(由动态代理创建对象.)</li>
<li>Converter转换器.(把response转换为一个具体的对象)</li>
<li>注解的使用.</li>
</ul>
<p>先从API来看。</p>
<a id="more"></a>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RestAdapter restAdapter = <span class="keyword">new</span> RestAdapter.Builder().setEndpoint(API_URL).build();</span><br></pre></td></tr></table></figure>
<p>build()其内部实现是这样的:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> RestAdapter <span class="title">build</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (endpoint == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"Endpoint may not be null."</span>);</span><br><span class="line"> }</span><br><span class="line"> ensureSaneDefaults();</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> RestAdapter(endpoint, clientProvider, httpExecutor, </span><br><span class="line"> callbackExecutor, requestInterceptor, converter, profiler, </span><br><span class="line"> errorHandler, log, logLevel);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>当用户没有设置自定义的converter,client, httpExecutor(http访问执行的线程只对异步的retrofit有效), callBackExecutor(异步的callBack执行的线程),errorHandler,log, RequestInterceptor的时候,就会使用retrofit默认的配置。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">ensureSaneDefaults</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (converter == <span class="keyword">null</span>) {</span><br><span class="line"> converter = Platform.get().defaultConverter();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (clientProvider == <span class="keyword">null</span>) {</span><br><span class="line"> clientProvider = Platform.get().defaultClient();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (httpExecutor == <span class="keyword">null</span>) {</span><br><span class="line"> httpExecutor = Platform.get().defaultHttpExecutor();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (callbackExecutor == <span class="keyword">null</span>) {</span><br><span class="line"> callbackExecutor = Platform.get().defaultCallbackExecutor();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (errorHandler == <span class="keyword">null</span>) {</span><br><span class="line"> errorHandler = ErrorHandler.DEFAULT;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (log == <span class="keyword">null</span>) {</span><br><span class="line"> log = Platform.get().defaultLog();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (requestInterceptor == <span class="keyword">null</span>) {</span><br><span class="line"> requestInterceptor = RequestInterceptor.NONE;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Platform.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Platform PLATFORM = findPlatform();</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">static</span> Platform <span class="title">get</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> PLATFORM;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> Platform <span class="title">findPlatform</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Class.forName(<span class="string">"android.os.Build"</span>);<span class="comment">//只要android.os.Build的class可以正常找到,证明是在android平台</span></span><br><span class="line"> <span class="keyword">if</span> (Build.VERSION.SDK_INT != <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Android();</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (ClassNotFoundException ignored) {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (System.getProperty(<span class="string">"com.google.appengine.runtime.version"</span>) != <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> AppEngine(); <span class="comment">//google的app Engine平台</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Base();</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Retrofit的Android类继承了Platform,根据android的特性对配置项做了处理。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Android</span> <span class="keyword">extends</span> <span class="title">Platform</span> </span>{</span><br><span class="line"> <span class="annotation">@Override</span> <span class="function">Converter <span class="title">defaultConverter</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> GsonConverter(<span class="keyword">new</span> Gson()); <span class="comment">//默认的转换器是Gson</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Override</span> Client.<span class="function">Provider <span class="title">defaultClient</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">final</span> Client client;</span><br><span class="line"> <span class="keyword">if</span> (hasOkHttpOnClasspath()) { <span class="comment">//有okhttp的路径就使用 Okhttp</span></span><br><span class="line"> client = OkClientInstantiator.instantiate();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {</span><br><span class="line"> client = <span class="keyword">new</span> AndroidApacheClient(); <span class="comment">//没有okhttp,且版本小于2.3 使用HttpClient</span></span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> client = <span class="keyword">new</span> UrlConnectionClient(); <span class="comment">//没有okhttp,且版本大于等于2.3 使用urlConnection.</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Client.Provider() {</span><br><span class="line"> <span class="annotation">@Override</span> <span class="function"><span class="keyword">public</span> Client <span class="title">get</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> client;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Override</span> <span class="function">Executor <span class="title">defaultHttpExecutor</span><span class="params">()</span> </span>{ <span class="comment">//网络访问执行的线程.</span></span><br><span class="line"> <span class="keyword">return</span> Executors.newCachedThreadPool(<span class="keyword">new</span> ThreadFactory() { <span class="comment">//一个cached的线程池.可以复用老线程且线程长时间不用会自动回收. 线程池中线程不够会生成新线程.</span></span><br><span class="line"> <span class="annotation">@Override</span> <span class="function"><span class="keyword">public</span> Thread <span class="title">newThread</span><span class="params">(<span class="keyword">final</span> Runnable r)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() {</span><br><span class="line"> <span class="annotation">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>{</span><br><span class="line"> Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); <span class="comment">//设置线程的优先级 为最低</span></span><br><span class="line"> r.run();</span><br><span class="line"> }</span><br><span class="line"> }, RestAdapter.IDLE_THREAD_NAME);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Override</span> <span class="function">Executor <span class="title">defaultCallbackExecutor</span><span class="params">()</span> </span>{ <span class="comment">//异步执行的线程.</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> MainThreadExecutor();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Override</span> RestAdapter.<span class="function">Log <span class="title">defaultLog</span><span class="params">()</span> </span>{ <span class="comment">//通过Log.d("Retrofit",String)打印log</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> AndroidLog(<span class="string">"Retrofit"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">hasOkHttpOnClasspath</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Class.forName(<span class="string">"com.squareup.okhttp.OkHttpClient"</span>); <span class="comment">//是否可以找到OkHttpClient类.</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> } <span class="keyword">catch</span> (ClassNotFoundException ignored) {</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>可以发现上面默认的Http的Executor是一个线程池。<br>而CallBack的Executor是在主线程执行的。由绑定MainLooper的Handler提交到主线程执行。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">MainThreadExecutor</span> <span class="keyword">implements</span> <span class="title">Executor</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Handler handler = <span class="keyword">new</span> Handler(Looper.getMainLooper()); <span class="comment">//关联主线程的Handler</span></span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">execute</span><span class="params">(Runnable r)</span> </span>{</span><br><span class="line"> handler.post(r); <span class="comment">//提交到主线程执行</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">post</span><span class="params">(Runnable r)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> sendMessageDelayed(getPostMessage(r), <span class="number">0</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> Message <span class="title">getPostMessage</span><span class="params">(Runnable r)</span> </span>{ <span class="comment">//把runnable封装到Message中.</span></span><br><span class="line"> Message m = Message.obtain();</span><br><span class="line"> m.callback = r;</span><br><span class="line"> <span class="keyword">return</span> m;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
]]></content>
</entry>
<entry>
<title><![CDATA[简单服务器架构改造]]></title>
<url>https://sogary.github.io/2015/11/11/%E7%AE%80%E5%8D%95%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%9E%B6%E6%9E%84%E6%94%B9%E9%80%A0/</url>
<content type="html"><![CDATA[<p>最近朋友需要做一个线上流量峰值很大的活动,第一天由于某段时间太多人并发访问,服务器性能到峰值就崩溃了。他用的是Discuz里面一个简单插件,之前是付钱让外面的人帮忙搭起来的。我那天晚上看了一下情况,然后我也达到疯值崩溃了。</p>
<p>他们在阿里云买了单台服务器,所有东西丢进去,把CPU,内存和网络资源调整得比较高。一台云服务器甚至比我做的一套框架还贵😂。为了避免高并发带来的系统崩溃,我开始帮他在现有的系统下改服务器架构。</p>
<a id="more"></a>
<h2 id="单服务器">单服务器</h2><p>他们原来的部署逻辑是把所有的东西丢在同一台服务,然后把这台服务器的性能调高。显然这种小学生的做法只可以满足一些低并发的需求,几个人玩玩泥沙这样做是没问题的。但是,我朋友的活动有几十万人参与,而且有比较集中的峰值,这种架构显然不能撑起所有访问。</p>
<p><img src="http://7xo6cz.com1.z0.glb.clouddn.com/20151111/singleserver.png" alt="singleserver"></p>
<h2 id="负载均衡">负载均衡</h2><p>首先我把数据库进行了分离,业务处理与数据处理的分离有效减少服务器的计算和IO压力。云数据库本身的HA和定期备份比较有保证。这样数据本身可以安全的被隔离,而读写访问的压力也分离了。</p>
<p>之后我用四台性能比前面提及到的单机低的云服务器,分别搭建了该系统。由于系统程序本身的局限性,我把业务逻辑和文件处理放在了一起,加上一个负载均衡做访问分发。由于Session同步问题,我使用了源IP访问的形式进行访问的分发。</p>
<p><img src="http://7xo6cz.com1.z0.glb.clouddn.com/20151111/loadbalance.png" alt="laodbalance"></p>
<h2 id="文件服务器">文件服务器</h2><p>经过数据库分离和负载均衡,在峰值的时候我们发现速度有所改进,页面打开的时候很快有反应,但是图片加载非常慢,导致整体页面打开速度非常慢。通过服务器的参数对比,发现网络流量占用特别大,原因是图片没有集中存储进行独立分发,需要在四台服务器进行分发。当大量并发访问的时候,所有的流量都用于分发图片,没办法支撑起新的请求。</p>
<p>我们立刻做了一个应急处理,我把所有服务器的带宽都动态调整到较大的最高值。而且,我发现大量图片占用的空间偏大,分发的时候严重占用带宽,就算缩小10倍也不会影响用户使用。所以,我让朋友把所有图片都缩小。最后利用这种方法听过去,活动顺利结束。</p>
<p>由于这类活动会频繁举行,我想在空档期间把系统进行改造。把图片服务器分离出来,使用第三方对象存储进行图片访问和分发,例如现在很火的<a href="http://www.qiniu.com/" target="_blank" rel="external">七牛</a>。由于这种改造需求修改源码,所以日后开始开发的时候就需要考虑到这种情况。</p>
<p><img src="http://7xo6cz.com1.z0.glb.clouddn.com/20151111/withfileserver.png" alt="withfileserver"></p>
<h2 id="内存存储">内存存储</h2><p>到再下一步,网站比较多动态态数据更新频率不高,可以用内存存储进行纪录。而且对与网站访问,把Session统一存放也是比较好管理的。所以,增加内存存储能够帮助系统提升性能和可用性。有了内存存储能够提升部分访问速度,而且可以把负载均衡的分发改成轮询,使应用服务器的压力分配比较平均。</p>
<p><img src="http://7xo6cz.com1.z0.glb.clouddn.com/20151111/withmemory.png" alt="withmemory"></p>
<h2 id="总结">总结</h2><p>当我们做服务器架构的时候需要考虑大一点,不是把所有东西放在一台服务器上,然后把单台服务器性能提升就可以解决问题的。术业有专攻,不同的服务器完成不同的功能,通力合作,这样顺利才能完成大量任务。当然,要处理更大的业务量,这种架构肯定好快出现瓶颈,还有很多更加细节的优化需要注意。</p>
<p>这里只是纪录我平时的一些工作或者一些想法,也会写一写自己对一些技术的理解,当然还会分享一些比较厉害的文章。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[Hello World]]></title>
<url>https://sogary.github.io/2015/11/09/hello-world/</url>
<content type="html"><![CDATA[<p>Welcome to <a href="http://hexo.io/" target="_blank" rel="external">Hexo</a>! This is your very first post. Check <a href="http://hexo.io/docs/" target="_blank" rel="external">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="http://hexo.io/docs/troubleshooting.html" target="_blank" rel="external">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="external">GitHub</a>.</p>
<h2 id="Quick_Start">Quick Start</h2><h3 id="Create_a_new_post">Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/writing.html" target="_blank" rel="external">Writing</a></p>
<a id="more"></a>
<h3 id="Run_server">Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/server.html" target="_blank" rel="external">Server</a></p>
<h3 id="Generate_static_files">Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/generating.html" target="_blank" rel="external">Generating</a></p>
<h3 id="Deploy_to_remote_sites">Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/deployment.html" target="_blank" rel="external">Deployment</a></p>
]]></content>
</entry>
</search>