-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
432 lines (364 loc) · 81 KB
/
atom.xml
File metadata and controls
432 lines (364 loc) · 81 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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[KOST]]></title>
<subtitle><![CDATA[Do not ship shits.]]></subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://jinyudong.com/"/>
<updated>2015-03-10T04:57:42.215Z</updated>
<id>http://jinyudong.com/</id>
<author>
<name><![CDATA[Jin Yudong]]></name>
<email><![CDATA[kost@outlook.com]]></email>
</author>
<generator uri="http://zespia.tw/hexo/">Hexo</generator>
<entry>
<title><![CDATA[Android作品集]]></title>
<link href="http://jinyudong.com/2015/03/09/works/"/>
<id>http://jinyudong.com/2015/03/09/works/</id>
<published>2015-03-09T04:03:28.000Z</published>
<updated>2015-03-10T04:55:45.000Z</updated>
<content type="html"><![CDATA[<hr>
<p>从2012年开始学习开发Android应用,到现在已经上线了七八款应用。对于应用的开发流程、优化等也有一定的了解,大部分都是独立设计界面与开发编码的,下面选一些比较有代表性的作品进行简单的展示介绍。</p>
<h1 id="弹窗信息">弹窗信息</h1>
<p>这个一个跟同学两个人合作做的作品,其中我承担了大部分手机端功能的开发,同时也独自负责了服务器端的开发(使用简单的PHP语言与MySQL数据库)。这是一款让你在Android设备上拥有ios通知功能的软件,除此之外还有很多个性化设置,在功能和体验上更加完善。在各大市场均可下载。</p>
<p>下载量:<strong>500万次(免费付费各大市场总和)</strong></p>
<p>累计用户:<strong>70万人(按独立设备统计)</strong></p>
<p>日弹窗量:<strong>200万次</strong></p>
<p>荣耀达成:<strong>魅族软件中心首页推荐、付费排行榜第一名</strong></p>
<p>技术创新:</p>
<ol>
<li>仿照系统源码重新开发设置界面(K-PreferencScreen),使其更加灵活多变;</li>
<li>主题切换功能(包括皮肤、自定义颜色等等);</li>
<li>可视化投票模块(使用RecyclerView等),让用户可以发布自己的投票表达意见。</li>
</ol>
<p>部分截图如下:</p>
<p><img src="http://sinacloud.net/kost-works/pics/popup.jpg" alt=""></p>
<h1 id="魅手机隐私锁">魅手机隐私锁</h1>
<p>是一款独立设计与开发的手机锁定软件,可以锁定App与文件等。七大锁定模式:九宫格锁定模式、手势锁定模式、密码锁定模式、程序假死锁定模式、提示锁定模式、不执行模式、程序跳转模式。每个模式的作用具体是什么还需要您自己来体会。文件隐藏:不仅仅可以隐藏android系统下面的文件,而且当手机作为u盘连接到windows电脑上面时,文件也会被隐藏的天衣无缝。</p>
<p>下载量:<strong>12万次(魅族市场收费版)</strong></p>
<p>荣耀达成:<strong>魅族软件中心首页推荐、付费排行榜第一名</strong></p>
<p>技术难点:</p>
<ol>
<li>防止用户破解,保证锁定的坚固有效;</li>
<li>密码等隐私信息的存储;</li>
</ol>
<p>截图如下:</p>
<p><img src="http://sinacloud.net/kost-works/pics/lock.jpg" alt=""></p>
<h1 id="计划派">计划派</h1>
<p>如果你正被每天琐碎的种种急得焦头烂额,如果你曾因为忘了准备礼物而让TA生气,如果你渴望把一切打理的井井有条,那么“计划派”正是你的不二选择!她将为你提供:最简单易用的计划管理列表;最轻松自如的交互操作;最简洁大方的用户界面。她让繁杂的事物变得亲切有序,让远大的目标变得真实可企及。</p>
<p>下载量:<strong>5万次</strong></p>
<p>荣耀达成:<strong>魅族软件中心首页推荐</strong></p>
<p>技术难点:</p>
<ol>
<li>列表的拖动与排序功能;</li>
<li>自定义时间Picker的效率优化与时间展示问题。</li>
</ol>
<p>截图如下:</p>
<p><img src="http://sinacloud.net/kost-works/pics/jihuapai.jpg" alt=""></p>
<h1 id="夜间模式">夜间模式</h1>
<p>你是否有晚上玩手机的习惯?是否觉得最小亮度还是刺眼?《夜间模式》可帮您将亮度降到更低!保护您的双眼!并具备手电筒功能哦~</p>
<p>下载量:<strong>16万次(魅族市场收费版)</strong></p>
<p>荣耀达成:<strong>魅族软件中心首页推荐</strong></p>
<p>技术实现:本软件实现较为简单,使用WindowManager创建覆盖整个屏幕的悬浮窗即可。仅使用了两天开发的时间,但是还取得了比较好的销量,着实比较意外。</p>
<p>截图如下:</p>
<p><img src="http://sinacloud.net/kost-works/pics/night.jpg" alt=""></p>
<h1 id="大象框">大象框</h1>
<p>大象框是赵云科技的一款新产品,简单来说是一个云电子相框,可以通过手机向异地的长辈传送照片,免去让他们操作复杂手机的烦恼。我在其中独自负责相框端软件的开发。</p>
<p>官方网站:<a href="http://www.zhaoyuntech.com" target="_blank" rel="external">大象框</a></p>
<p>技术难点:</p>
<ol>
<li>低端平板上大量高清图片的展示与存储(需要良好的内存管理避免OOM);</li>
<li>低端平板上交互的重构与流畅度优化。</li>
</ol>
]]></content>
<summary type="html">
<![CDATA[<hr>
<p>从2012年开始学习开发Android应用,到现在已经上线了七八款应用。对于应用的开发流程、优化等也有一定的了解,大部分都是独立设计界面与开发编码的,下面选一些比较有代表性的作品进行简单的展示介绍。</p>
<h1 id="弹窗信息">弹窗信息</h1>
<p>这]]>
</summary>
</entry>
<entry>
<title><![CDATA[庖丁解牛之Volley篇(一) - 简单介绍与使用方法]]></title>
<link href="http://jinyudong.com/2014/12/22/Volley-1/"/>
<id>http://jinyudong.com/2014/12/22/Volley-1/</id>
<published>2014-12-22T13:17:06.000Z</published>
<updated>2014-12-23T07:55:26.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p><em>笔者小菜,文中可能会有一些误解或者错误的地方,欢迎指出交流</em></p>
</blockquote>
<h2 id="什么是Volley">什么是Volley</h2>
<p>Volley是google在2013年IO大会上推出的一个轻量级HTTP库,可以让Android上面的网络操作的构建变得异常简单,而且响应更加迅速。据说google内部测试了很多种HTTP库,Volley在每一项测试中都取得了最好的成绩。真假不知道,但是这个开源库的内部实现肯定会引起程序猿的兴趣,它内部是如何实现的呢?我们能从这个开源库里面学到一些什么东西呢?这就是接下来一系列的博文给大家讲述的内容。</p>
<a id="more"></a>
<blockquote>
<p>本文中的内容基本来自于Google的<a href="http://developer.android.com/training/volley/index.html" target="_blank" rel="external">官方文档</a>,如果熟悉Volley的使用方法,可以跳过本文章。</p>
</blockquote>
<p>Volley的优势有以下几点:</p>
<ul>
<li>网络请求的队列化、自动化处理</li>
<li>多网络连接并发</li>
<li>使用文件和内存Cache机制实现HTTP的快速响应</li>
<li>支持网络请求的自定义优先级</li>
<li>网络请求的取消功能,可以对指定范围或指定种类的网络请求进行取消</li>
<li>傻瓜式自定义,如可以自定义重试策略</li>
<li>数据显示与网络请求的异步</li>
<li>强大的跟踪与调试工具</li>
</ul>
<p>优点说了这么多,到底是如何做到的呢?别着急,了解内部实现之前,先来了解一下Volley的简单用法。</p>
<h2 id="Volley的简单使用方法">Volley的简单使用方法</h2>
<h3 id="发送请求">发送请求</h3>
<p>使用Volley时,需要创建一个RequestQueue,并将Request传递给它。RequestQueue管理后台工作线程获取网络内容、读写Cache、解析Response。Request负责解析获取到的网络数据,Volley负责将解析后的结果在主线程进行分发。下面是一个简单的例子,从网络获取字符串:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">RequestQueue queue = Volley.newRequestQueue(<span class="keyword">this</span>);</div><div class="line">String url =<span class="string">"http://www.google.com"</span>;</div><div class="line"><span class="comment">// Request a string response from the provided URL.</span></div><div class="line">StringRequest stringRequest = <span class="keyword">new</span> StringRequest(Request.Method.GET, url,</div><div class="line"> <span class="keyword">new</span> Response.Listener() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(String response) {</div><div class="line"> <span class="comment">// Display the first 500 characters of the response string.</span></div><div class="line"> mTextView.setText(<span class="string">"Response is: "</span>+ response.substring(<span class="number">0</span>,<span class="number">500</span>));</div><div class="line"> }</div><div class="line">}, <span class="keyword">new</span> Response.ErrorListener() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) {</div><div class="line"> mTextView.setText(<span class="string">"That didn't work!"</span>);</div><div class="line"> }</div><div class="line">});</div><div class="line"><span class="comment">// Add the request to the RequestQueue.</span></div><div class="line">queue.add(stringRequest);</div></pre></td></tr></table></figure>
<p>首先使用<em>Volley.newRequestQueue(this)</em>来创建一个请求队列,然后创建一个Request,并将这个Request添加到请求队列当中。在这个例子中,StringRequest是Request的具体的一个实现,还有很多种其他类型的Request,并可以编写自己的Request。当添加到队列之后,Volley会自动开始处理队列中的Request(通过<em>PriorityBlockingQueue</em>进行实现),处理结果通过上面所示的<em>Response.Listener</em>与<em>Response.ErrorListener</em>来进行返回。值得注意的是,Volley都在主线程进行结果的返回,你可以直接在listener中进行UI的控制操作。</p>
<h3 id="取消请求">取消请求</h3>
<p>Volley的取消网络异常简单方便,一旦Request被取消掉,Volley就不会对listener进行调用。实际中利用到取消请求的情况非常多,在一个activity结束的时候,我们通常会在onStop方法中处理一些没有被反馈的网络请求,并且在listener中判断当前Activity是否存在: <em>getActivity() == null</em>或<em>onSaveInstanceState()</em>是否被调用。而在Volley中,并不需要这些繁琐的判断操作:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = <span class="string">"MyTag"</span>;</div><div class="line">StringRequest stringRequest;</div><div class="line">RequestQueue mRequestQueue;</div><div class="line">stringRequest.setTag(TAG);<span class="comment">//或将此Activity(Context)传入也可以</span></div><div class="line">mRequestQueue.add(stringRequest);</div></pre></td></tr></table></figure>
<p>在上面的代码中,我们对Request设置Tag,这个Tag可以是任何类型,可以是当前的Activity,可以是一个字符串,相同Tag的Request表示他们是同一个类型的Request,并可以进行批量的取消:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="annotation">@Override</span></div><div class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onStop</span> () {</div><div class="line"> <span class="keyword">super</span>.onStop();</div><div class="line"> <span class="keyword">if</span> (mRequestQueue != <span class="keyword">null</span>) {</div><div class="line"> mRequestQueue.cancelAll(TAG);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="配置RequestQueue请求队列">配置RequestQueue请求队列</h2>
<p>上面介绍了Volley的最基本的使用方法,本节将介绍如何自定义RequestQueue的配置,让它更适用于你自己的应用程序。</p>
<h3 id="配置RequestQueue">配置RequestQueue</h3>
<p>RequestQueue工作过程中,需要两件东西:</p>
<ul>
<li>网络请求实现(HttpURLConnection or AndroidHttpClient or ANYHING ELSE)</li>
<li>缓存空间来对网络请求进行缓存</li>
</ul>
<p>关于网络请求实现需要特别说一下,Volley对不同的Android版本提供了不同的网络请求实现,在低于API Level 9 (Gingerbread)的情况下,使用<a href="http://developer.android.com/reference/android/net/http/AndroidHttpClient.html" target="_blank" rel="external">AndroidHttpClient</a>。当高于API Level 9的时候,使用<a href="http://developer.android.com/reference/java/net/HttpURLConnection.html" target="_blank" rel="external">HttpURLConnection</a>。关于为何这么做,可以参考<a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html" target="_blank" rel="external">这里</a>,当然你也可以使用自己的网络请求实现。</p>
<p>如下的代码展示了如何对RequestQueue进行配置:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line">RequestQueue mRequestQueue;</div><div class="line"><span class="comment">//初始化Cache空间,可指定大小与地址</span></div><div class="line">Cache cache = <span class="keyword">new</span> DiskBasedCache(getCacheDir(), <span class="number">1024</span> * <span class="number">1024</span>); <span class="comment">// 1MB</span></div><div class="line"><span class="comment">//使用HttpURLConnection作为网络请求实现,若要用AndroidHttpClient,可以使用HttpClientStack</span></div><div class="line">Network network = <span class="keyword">new</span> BasicNetwork(<span class="keyword">new</span> HurlStack());</div><div class="line"><span class="comment">//使用Cache和Network对请求队列进行初始化</span></div><div class="line">mRequestQueue = <span class="keyword">new</span> RequestQueue(cache, network);</div><div class="line">mRequestQueue.start();</div><div class="line">String url =<span class="string">"http://www.myurl.com"</span>;</div><div class="line">StringRequest stringRequest = <span class="keyword">new</span> StringRequest(Request.Method.GET, url,</div><div class="line"> <span class="keyword">new</span> Response.Listener<String>() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(String response) {</div><div class="line"> <span class="comment">//处理结果</span></div><div class="line"> }</div><div class="line">},</div><div class="line"> <span class="keyword">new</span> Response.ErrorListener() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) {</div><div class="line"> <span class="comment">//处理错误</span></div><div class="line"> }</div><div class="line">});</div><div class="line"><span class="comment">//将请求添加到队列当中</span></div><div class="line">mRequestQueue.add(stringRequest);</div></pre></td></tr></table></figure>
<h3 id="使用单例模式">使用单例模式</h3>
<p>在RequestQueue的使用中,你可以随时调用<em>Volley.newRequestQueue()</em>来创建一个请求队列,如果不再想使用此队列了,直接调用stop函数即可。这样做无可厚非,但是一个更有趣的做法是保持一个单例,在整个程序运行的过程中维持这个RequestQueue单例。从易于管理与效率方面,这么做会更好一些。当然还是具体情况具体分析,看哪种使用发放更适合你的使用场景。如果你对单例模式不太了解,可以参见<a href="http://en.wikipedia.org/wiki/Singleton_pattern" target="_blank" rel="external">这里</a>。</p>
<p>我们在Application.onCreate()中创建这个单例,值得注意的是,传给RequesQueue的Context需要是Application的Context,而不是Activity的Context。放码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> MySingleton {</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> MySingleton mInstance;</div><div class="line"> <span class="keyword">private</span> RequestQueue mRequestQueue;</div><div class="line"> <span class="keyword">private</span> ImageLoader mImageLoader;</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Context mCtx;</div><div class="line"> <span class="keyword">private</span> <span class="title">MySingleton</span>(Context context) {</div><div class="line"> mCtx = context;</div><div class="line"> mRequestQueue = getRequestQueue();</div><div class="line"> mImageLoader = <span class="keyword">new</span> ImageLoader(mRequestQueue,</div><div class="line"> <span class="keyword">new</span> ImageLoader.ImageCache() {</div><div class="line"> <span class="keyword">private</span> <span class="keyword">final</span> LruCache<String, Bitmap></div><div class="line"> cache = <span class="keyword">new</span> LruCache<String, Bitmap>(<span class="number">20</span>);</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> Bitmap <span class="title">getBitmap</span>(String url) {</div><div class="line"> <span class="keyword">return</span> cache.get(url);</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">putBitmap</span>(String url, Bitmap bitmap) {</div><div class="line"> cache.put(url, bitmap);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> MySingleton <span class="title">getInstance</span>(Context context) {</div><div class="line"> <span class="keyword">if</span> (mInstance == <span class="keyword">null</span>) {</div><div class="line"> mInstance = <span class="keyword">new</span> MySingleton(context);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> mInstance;</div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> RequestQueue <span class="title">getRequestQueue</span>() {</div><div class="line"> <span class="keyword">if</span> (mRequestQueue == <span class="keyword">null</span>) {</div><div class="line"> <span class="comment">// getApplicationContext() is key, it keeps you from leaking the</span></div><div class="line"> <span class="comment">// Activity or BroadcastReceiver if someone passes one in.</span></div><div class="line"> mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> mRequestQueue;</div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> <T> <span class="keyword">void</span> <span class="title">addToRequestQueue</span>(Request<T> req) {</div><div class="line"> getRequestQueue().add(req);</div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> ImageLoader <span class="title">getImageLoader</span>() {</div><div class="line"> <span class="keyword">return</span> mImageLoader;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>写好这个单例模式之后,使用方法就变得异常简单,你可以在不同的Activity中使用如下代码,它们使用的都会是同一个RequestQueue:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//获取RequestQueue</span></div><div class="line">RequestQueue queue = MySingleton.getInstance(<span class="keyword">this</span>.getApplicationContext()).</div><div class="line"> getRequestQueue();</div><div class="line">...</div><div class="line"><span class="comment">//添加一个Request到RequestQueue中</span></div><div class="line">MySingleton.getInstance(<span class="keyword">this</span>).addToRequestQueue(stringRequest);</div></pre></td></tr></table></figure>
<p>需要注意的是,使用单例模式之后所有的网络请求都将插入到这个队列当中,因此我们在不同的界面中进行跳转的时候,需要注意对一些Request的优先级进行提高,或者是取消一些Request,让当前界面的Request更快速的进行响应。关于Request的取消在上面已经讲过了,这里不再赘述。</p>
<h2 id="图片的网络请求">图片的网络请求</h2>
<p>请求图片对于Android应用来说是一个很重要的功能,看上去简单,其实涉及到很多复杂的东西。比如图片的解析,内存的管理,不同设备下的优化等等。Volley对于网络图片支持方面虽然比不上Picasso或UniversalImageLoader等工具,但是在某些场景下,也足够使用了。在这里讲一下使用Volley对图片进行网络请求。</p>
<p>在Volley中关于图片请求功能部分,提供了三个类:</p>
<p><strong>ImageRequest</strong>:与StringRequest相同,它继承了Request类,实现了对指定URL的图片进行解码,并将解码后的图片按照规定的大小进行返回。它的牛逼之处是对图片解析和处理的操作都是在后台工作线程进行,不会影响主线程的操作,等到图片处理完毕,再交给主线程进行处理。</p>
<p><strong>ImageLoader</strong>:它提供了对远程网络图片的缓存功能,牛逼之处是在内存中开辟了一块缓存图片的空间,在进行网络加载时,可以对已加载过的图片从Cache中获取。</p>
<p><strong>NetworkImageView</strong>:这个更进一步,直接提供了一个加载图片的控件,它其实也是继承了ImageView,使用起来更加方便。牛逼的地方是,当这个View不再显示的时候或被销毁后它会对正在进行的图片Request进行取消,不浪费带宽和CPU资源,屌吗?</p>
<h3 id="使用ImageRequest">使用ImageRequest</h3>
<p>使用ImageRequest的方法与使用其他Request的方法大同小异,直接放码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">ImageView mImageView;</div><div class="line">String url = <span class="string">"http://i.imgur.com/7spzG.png"</span>;</div><div class="line">mImageView = (ImageView) findViewById(R.id.myImage);</div><div class="line">...</div><div class="line"><span class="comment">//根据URL获取Bitmap,并展示到界面上</span></div><div class="line">ImageRequest request = <span class="keyword">new</span> ImageRequest(url,</div><div class="line"> <span class="keyword">new</span> Response.Listener() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(Bitmap bitmap) {</div><div class="line"> mImageView.setImageBitmap(bitmap);</div><div class="line"> }</div><div class="line"> }, <span class="number">0</span>, <span class="number">0</span>, <span class="keyword">null</span>,</div><div class="line"> <span class="keyword">new</span> Response.ErrorListener() {</div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) {</div><div class="line"> mImageView.setImageResource(R.drawable.image_load_error);</div><div class="line"> }</div><div class="line"> });</div><div class="line"><span class="comment">//添加到单例队列</span></div><div class="line">MySingleton.getInstance(<span class="keyword">this</span>).addToRequestQueue(request);</div></pre></td></tr></table></figure>
<h3 id="使用ImageLoader和NetworkImageView">使用ImageLoader和NetworkImageView</h3>
<h4 id="ImageLoader的使用">ImageLoader的使用</h4>
<p>Imageloader的使用代码如下,我们从之前的那个单例中,可以获取一个ImageLoader实例,使用这个ImageLoader来进行图片的加载。同样,在使用单例的时候,也要注意图片请求的优先级、取消等等。执行了get函数之后,当图片从网络获取完毕,会自动加载:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">ImageLoader mImageLoader;</div><div class="line">ImageView mImageView;</div><div class="line"><span class="comment">//请求的图片地址</span></div><div class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String IMAGE_URL =</div><div class="line"> <span class="string">"http://developer.android.com/images/training/system-ui.png"</span>;</div><div class="line">...</div><div class="line">mImageView = (ImageView) findViewById(R.id.regularImageView);</div><div class="line"><span class="comment">//获取单例中的Imageloader</span></div><div class="line">mImageLoader = MySingleton.getInstance(<span class="keyword">this</span>).getImageLoader();</div><div class="line"><span class="comment">//指定URL、默认图片、加载失败图片</span></div><div class="line">mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,</div><div class="line"> R.drawable.def_image, R.drawable.err_image));</div></pre></td></tr></table></figure>
<h4 id="NetworkImageView的使用">NetworkImageView的使用</h4>
<p>由于NetworkImageView是继承自ImageView的,所以基本用法一致,就多了一些网络请求的包装。在XML布局文件中声明布局如下:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="title">com.android.volley.toolbox.NetworkImageView</span></span></div><div class="line"> <span class="attribute">android:id</span>=<span class="value">"@+id/networkImageView"</span></div><div class="line"> <span class="attribute">android:layout_width</span>=<span class="value">"150dp"</span></div><div class="line"> <span class="attribute">android:layout_height</span>=<span class="value">"170dp"</span></div><div class="line"> <span class="attribute">android:layout_centerHorizontal</span>=<span class="value">"true"</span> /></div></pre></td></tr></table></figure>
<p>使用NetworkImageView的时候,也需要指定一个ImageLoader实例。当图片从网络获取完毕,会自动加载到NetworkImageView上面:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">ImageLoader mImageLoader;</div><div class="line">NetworkImageView mNetworkImageView;</div><div class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String IMAGE_URL =</div><div class="line"> <span class="string">"http://developer.android.com/images/training/system-ui.png"</span>;</div><div class="line">mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);</div><div class="line"><span class="comment">//获取ImageLoader单例</span></div><div class="line">mImageLoader = MySingleton.getInstance(<span class="keyword">this</span>).getImageLoader();</div><div class="line"><span class="comment">//指定图片URL与用来执行网络请求的ImageLoader</span></div><div class="line">mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);</div></pre></td></tr></table></figure>
<p>值得注意的是这里的单例模式,使用单例模式的一个好处是,这个单例的存活时间将比ctivity的存活周期更长。如果在Activity内部创建ImageLoader,当Activity旋转的时候,所有实例、图片都要重新初始化加载一遍,造成界面的闪烁。显然浪费了网络和计算资源。而独立于Activity的Imageloader中的缓存机制,可以缓存图片到内存中,当下一次再次请求这个同样的URL的时候,如果Cache命中的话,就直接从Cache加载图片,而不再从网络中加载。</p>
<h4 id="LRU_Cache">LRU Cache</h4>
<p>在Volley的toolbox中,提供了基于磁盘的缓存类<em>DiskBasedCache</em>,这个类会将缓存直接存储到指定的文件夹中。但是对于ImageLoader来说,我们必须提供一个建立在内存缓存基础上面的LRU Cache。我们可以实现<em>ImageLoader.ImageCache</em>接口来自定义一个Cache。</p>
<p>下面的代码继承了<a href="http://developer.android.com/reference/android/support/v4/util/LruCache.html" target="_blank" rel="external"><em>LruCache</em></a>类,并实现了ImageLoader.ImageCache接口。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> android.graphics.Bitmap;</div><div class="line"><span class="keyword">import</span> android.support.v4.util.LruCache;</div><div class="line"><span class="keyword">import</span> android.util.DisplayMetrics;</div><div class="line"><span class="keyword">import</span> com.android.volley.toolbox.ImageLoader.ImageCache;</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LruBitmapCache</span> <span class="keyword">extends</span> <span class="title">LruCache</span><<span class="title">String</span>, <span class="title">Bitmap</span>></span></div><div class="line"> <span class="keyword">implements</span> <span class="title">ImageCache</span> {</div><div class="line"> <span class="comment">//可以指定缓冲区的大小</span></div><div class="line"> <span class="keyword">public</span> <span class="title">LruBitmapCache</span>(<span class="keyword">int</span> maxSize) {</div><div class="line"> <span class="keyword">super</span>(maxSize);</div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> <span class="title">LruBitmapCache</span>(Context ctx) {</div><div class="line"> <span class="keyword">this</span>(getCacheSize(ctx));</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">protected</span> <span class="keyword">int</span> <span class="title">sizeOf</span>(String key, Bitmap value) {</div><div class="line"> <span class="keyword">return</span> value.getRowBytes() * value.getHeight();</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> Bitmap <span class="title">getBitmap</span>(String url) {</div><div class="line"> <span class="keyword">return</span> get(url);</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">putBitmap</span>(String url, Bitmap bitmap) {</div><div class="line"> put(url, bitmap);</div><div class="line"> }</div><div class="line"> <span class="comment">//根据屏幕的大小来动态调节缓存区的大小,屌</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getCacheSize</span>(Context ctx) {</div><div class="line"> <span class="keyword">final</span> DisplayMetrics displayMetrics = ctx.getResources().</div><div class="line"> getDisplayMetrics();</div><div class="line"> <span class="keyword">final</span> <span class="keyword">int</span> screenWidth = displayMetrics.widthPixels;</div><div class="line"> <span class="keyword">final</span> <span class="keyword">int</span> screenHeight = displayMetrics.heightPixels;</div><div class="line"> <span class="comment">// 4 bytes per pixel</span></div><div class="line"> <span class="keyword">final</span> <span class="keyword">int</span> screenBytes = screenWidth * screenHeight * <span class="number">4</span>;</div><div class="line"> <span class="keyword">return</span> screenBytes * <span class="number">3</span>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>如果ImageLoader使用这个Cache的话:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">RequestQueue mRequestQueue;</div><div class="line">ImageLoader mImageLoader = <span class="keyword">new</span> ImageLoader(mRequestQueue, <span class="keyword">new</span> LruBitmapCache(</div><div class="line"> LruBitmapCache.getCacheSize()));</div></pre></td></tr></table></figure>
<p>这里面非常好玩的地方是一个静态函数<em>getCacheSize</em>,它根据屏幕的分辨率大小动态调整缓冲区的大小。低端机的分辨率、内存都小一些,所以它的缓冲区也相应的小。这种做法确实很有意思。</p>
<h2 id="JSON的网络请求">JSON的网络请求</h2>
<p>这部分其实没啥好说的,基本上所有的Request用法都是一致的。Volley中对Json提供了两种类:</p>
<ul>
<li><strong>JsonArrayRequest</strong>:用来获取<a href="http://developer.android.com/reference/org/json/JSONArray.html" target="_blank" rel="external">JSONArray</a></li>
<li><strong>JsonObjectRequest</strong>:用来获取<a href="http://developer.android.com/reference/org/json/JSONObject.html" target="_blank" rel="external">JSONObject</a></li>
</ul>
<p>这两个类都是基于JsonRequest类来实现的,下面贴一个简单的代码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">TextView mTxtDisplay;</div><div class="line">ImageView mImageView;</div><div class="line">mTxtDisplay = (TextView) findViewById(R.id.txtDisplay);</div><div class="line">String url = <span class="string">"http://my-json-feed"</span>;</div><div class="line">JsonObjectRequest jsObjRequest = <span class="keyword">new</span> JsonObjectRequest</div><div class="line"> (Request.Method.GET, url, <span class="keyword">null</span>, <span class="keyword">new</span> Response.Listener() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(JSONObject response) {</div><div class="line"> mTxtDisplay.setText(<span class="string">"Response: "</span> + response.toString());</div><div class="line"> }</div><div class="line">}, <span class="keyword">new</span> Response.ErrorListener() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) {</div><div class="line"> <span class="comment">// TODO Auto-generated method stub</span></div><div class="line"> }</div><div class="line">});</div><div class="line">MySingleton.getInstance(<span class="keyword">this</span>).addToRequestQueue(jsObjRequest);</div></pre></td></tr></table></figure>
<h2 id="自定义Request请求">自定义Request请求</h2>
<p>Volley的灵活性在于你可以自定义非常多的东西,而且非常简单。Volley中提供了StringRequest、ImageRequest、JsonObjectRequest等等Request类,当然我们也可以自己实现一个Request类,来适应项目的需求。创建一个自定义的Request只需要两步:</p>
<ul>
<li>继承Request<t>类,其中<t>代表了你从网络获取的相应中需要解析出来的结果。比如获取一个String字符串,你就需要继承Request<string>。</string></t></t></li>
<li>实现抽象方法<em>parseNetworkResponse()</em>和<em>deliverResponse()</em>这两个函数。</li>
</ul>
<h3 id="parseNetworkResponse">parseNetworkResponse</h3>
<p>一个Response中包含了被解析过的对象,如Json、String、Bitmap等等。下面是一个简单的parseNetworkResponse实现:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="annotation">@Override</span></div><div class="line"><span class="keyword">protected</span> Response<T> <span class="title">parseNetworkResponse</span>(</div><div class="line"> NetworkResponse response) {</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> String json = <span class="keyword">new</span> String(response.data,</div><div class="line"> HttpHeaderParser.parseCharset(response.headers));</div><div class="line"> <span class="keyword">return</span> Response.success(gson.fromJson(json, clazz),</div><div class="line"> HttpHeaderParser.parseCacheHeaders(response));</div><div class="line"> }</div><div class="line"> <span class="comment">// handle errors</span></div><div class="line">...</div><div class="line">}</div></pre></td></tr></table></figure>
<p>在这里需要注意两点:</p>
<ul>
<li><em>parseNetworkResponse</em>的传入参数是<em>NetworkResponse</em>,它包含了HTTP响应报文的负载(byte[]形式)、HTTP的Status Code还有一些响应Headers。</li>
<li>你必须返回一个Response<t>。它包含了你解析后的实例类型(<t>),还有cache的元数据或错误信息。</t></t></li>
</ul>
<p>一般情况下都可以用如下代码来返回:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">return</span> Response.success(myDecodedObject,</div><div class="line"> HttpHeaderParser.parseCacheHeaders(response));</div></pre></td></tr></table></figure>
<p>其中Response.success()和Response.error()的内部实现如下所示:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="javadoc">/** Returns a successful response containing the parsed result. */</span></div><div class="line"><span class="keyword">public</span> <span class="keyword">static</span> <T> Response<T> <span class="title">success</span>(T result, Cache.Entry cacheEntry) {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Response<T>(result, cacheEntry);</div><div class="line">}</div><div class="line"><span class="javadoc">/**</span></div><div class="line">* Returns a failed response containing the given error code and an optional</div><div class="line">* localized message displayed to the user.</div><div class="line">*/</div><div class="line"><span class="keyword">public</span> <span class="keyword">static</span> <T> Response<T> <span class="title">error</span>(VolleyError error) {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Response<T>(error);</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="deliverResponse">deliverResponse</h3>
<p>Volley将处理结果在主线程进行返回,返回的实例就是你在<em>parseNetworkResponse()</em>中返回的东西。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">deliverResponse</span>(T response) {</div><div class="line"> listener.onResponse(response);</div></pre></td></tr></table></figure>
<h3 id="实例:实现GsonRequest">实例:实现GsonRequest</h3>
<p>Gson是一个可以将java对象和JSON相互转换的工具,它利用了java的反射机制。关于Gson的使用方法,参见<a href="http://code.google.com/p/google-gson/" target="_blank" rel="external">这里</a>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">GsonRequest</span><<span class="title">T</span>> <span class="keyword">extends</span> <span class="title">Request</span><<span class="title">T</span>> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Gson gson = <span class="keyword">new</span> Gson();</div><div class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Class<T> clazz;</div><div class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Map<String, String> headers;</div><div class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Listener<T> listener;</div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * Make a GET request and return a parsed object from JSON.</div><div class="line"> *</div><div class="line"> *<span class="javadoctag"> @param</span> url URL of the request to make</div><div class="line"> *<span class="javadoctag"> @param</span> clazz Relevant class object, for Gson's reflection</div><div class="line"> *<span class="javadoctag"> @param</span> headers Map of request headers</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <span class="title">GsonRequest</span>(String url, Class<T> clazz, Map<String, String> headers,</div><div class="line"> Listener<T> listener, ErrorListener errorListener) {</div><div class="line"> <span class="keyword">super</span>(Method.GET, url, errorListener);</div><div class="line"> <span class="keyword">this</span>.clazz = clazz;</div><div class="line"> <span class="keyword">this</span>.headers = headers;</div><div class="line"> <span class="keyword">this</span>.listener = listener;</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> Map<String, String> <span class="title">getHeaders</span>() <span class="keyword">throws</span> AuthFailureError {</div><div class="line"> <span class="keyword">return</span> headers != <span class="keyword">null</span> ? headers : <span class="keyword">super</span>.getHeaders();</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">deliverResponse</span>(T response) {</div><div class="line"> listener.onResponse(response);</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">protected</span> Response<T> <span class="title">parseNetworkResponse</span>(NetworkResponse response) {</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> String json = <span class="keyword">new</span> String(</div><div class="line"> response.data,</div><div class="line"> HttpHeaderParser.parseCharset(response.headers));</div><div class="line"> <span class="keyword">return</span> Response.success(</div><div class="line"> gson.fromJson(json, clazz),</div><div class="line"> HttpHeaderParser.parseCacheHeaders(response));</div><div class="line"> } <span class="keyword">catch</span> (UnsupportedEncodingException e) {</div><div class="line"> <span class="keyword">return</span> Response.error(<span class="keyword">new</span> ParseError(e));</div><div class="line"> } <span class="keyword">catch</span> (JsonSyntaxException e) {</div><div class="line"> <span class="keyword">return</span> Response.error(<span class="keyword">new</span> ParseError(e));</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>在这里没有将<t>具体化实现,而是可以传递一个Class进来,并使用网络获取的响应和Gson来进行Class的实例化。</t></p>
<blockquote>
<p>关于Volley使用的介绍就写到这里,可能会存在一些错误,欢迎指正交流。接下来几篇关于Volley的文章将讲一些Volley内部实现里比较有意思的地方。<br>最后奉上一个官方的介绍视频:<a href="https://developers.google.com/events/io/sessions/325304728" target="_blank" rel="external">点我!</a></p>
</blockquote>
]]></content>
<summary type="html">
<![CDATA[<blockquote>
<p><em>笔者小菜,文中可能会有一些误解或者错误的地方,欢迎指出交流</em></p>
</blockquote>
<h2 id="什么是Volley">什么是Volley</h2>
<p>Volley是google在2013年IO大会上推出的一个轻量级HTTP库,可以让Android上面的网络操作的构建变得异常简单,而且响应更加迅速。据说google内部测试了很多种HTTP库,Volley在每一项测试中都取得了最好的成绩。真假不知道,但是这个开源库的内部实现肯定会引起程序猿的兴趣,它内部是如何实现的呢?我们能从这个开源库里面学到一些什么东西呢?这就是接下来一系列的博文给大家讲述的内容。</p>
]]>
</summary>
<category term="android,volley" scheme="http://jinyudong.com/tags/android-volley/"/>
</entry>
<entry>
<title><![CDATA[Introducing RecyclerView(二)]]></title>
<link href="http://jinyudong.com/2014/11/14/add-listener-on-recyclerview/"/>
<id>http://jinyudong.com/2014/11/14/add-listener-on-recyclerview/</id>
<published>2014-11-14T12:29:10.000Z</published>
<updated>2014-11-14T13:04:27.000Z</updated>
<content type="html"><![CDATA[<p>当使用了一段时间的RecyclerView,发现为其每一项添加点击事件并没有ListView那么轻松,像ListView直接加个OnItemClickListener就行了。<strong>实际上我们不要把RecyclerView当做ListView的一个升级版</strong>,希望大家把他看做一个容器,同时里面包含了很多不同的Item,它们可以以不同方式排列组合,非常灵活,点击方式你可以按照你自己的意愿进行实现。</p>
<p>本节主要讲解如何为RecyclerView添加点击事件, 并简单介绍如何进行Item增加删除。</p>
<a id="more"></a>
<h2 id="添加点击事件">添加点击事件</h2>
<p><a href="http://jinyudong.com/2014/11/13/Introduce-RecyclerView-%E4%B8%80/" target="_blank" rel="external">上一节</a>中我们讲了如何使用RecyclerView的Adpater,其实我们会发现,Adapter是添加点击事件一个很好的地方,里面是构造布局等View的主要场所,也是数据和布局进行绑定的地方。首先我们在Adapter中创建一个实现点击接口,其中view是点击的Item,data是我们的数据,因为我们想知道我点击的区域部分的数据是什么,以便我下一步进行操作:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">interface</span> <span class="title">OnRecyclerViewItemClickListener</span> </span>{</div><div class="line"> <span class="keyword">void</span> onClick(View view , DataModel data);</div><div class="line">}</div></pre></td></tr></table></figure>
<p>定义完接口,添加接口和设置Adapter接口的方法:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">private</span> OnRecyclerViewItemClickListener mOnItemClickListener = <span class="keyword">null</span>;</div><div class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setOnItemClickListener</span>(OnRecyclerViewItemClickListener listener) {</div><div class="line"> <span class="keyword">this</span>.mOnItemClickListener = listener;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>那么这个接口用在什么地方呢?如下代码所示,我们为Adapter实现OnClickListener方法:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyAdapter</span> <span class="keyword">extends</span> <span class="title">RecyclerView</span>.<span class="title">Adapter</span><<span class="title">MyAdapter</span>.<span class="title">ViewHolder</span>> <span class="keyword">implements</span> <span class="title">View</span>.<span class="title">OnClickListener</span></span>{</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> ViewHolder <span class="title">onCreateViewHolder</span>(ViewGroup viewGroup, <span class="keyword">final</span> <span class="keyword">int</span> i) {</div><div class="line"> View view = LayoutInflater.from(viewGroup.getContext())</div><div class="line"> .inflate(R.layout.item, viewGroup, <span class="keyword">false</span>);</div><div class="line"> ViewHolder vh = <span class="keyword">new</span> ViewHolder(view);</div><div class="line"> <span class="comment">//将创建的View注册点击事件</span></div><div class="line"> view.setOnClickListener(<span class="keyword">this</span>);</div><div class="line"> <span class="keyword">return</span> vh;</div><div class="line"> }</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onBindViewHolder</span>(ViewHolder viewHolder, <span class="keyword">final</span> <span class="keyword">int</span> i) {</div><div class="line"> viewHolder.mTextView.setText(datas.get(i).title);</div><div class="line"> <span class="comment">//将数据保存在itemView的Tag中,以便点击时进行获取</span></div><div class="line"> viewHolder.itemView.setTag(datas.get(i));</div><div class="line"> }</div><div class="line"> ...</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span>(View v) {</div><div class="line"> <span class="keyword">if</span> (mOnItemClickListener != <span class="keyword">null</span>) {</div><div class="line"> <span class="comment">//注意这里使用getTag方法获取数据</span></div><div class="line"> mOnItemClickListener.onClick(v,(DataModel)v.getTag());</div><div class="line"> }</div><div class="line"> }</div><div class="line"> ...</div><div class="line">}</div></pre></td></tr></table></figure>
<p>做完这些事情,我们就可以在Activity或其他地方为RecyclerView添加项目点击事件了,如在MainActivity中:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">mAdapter = <span class="keyword">new</span> MyAdapter(getDummyDatas());</div><div class="line">mRecyclerView.setAdapter(mAdapter);</div><div class="line">mAdapter.setOnItemClickListener(<span class="keyword">new</span> MyAdapter.OnRecyclerViewItemClickListener() {</div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span>(View view, DataModel data) {</div><div class="line"> <span class="comment">//DO your fucking bussiness here!</span></div><div class="line"> }</div><div class="line">});</div></pre></td></tr></table></figure>
<p>完成了以上代码就可以为RecyclerView添加项目点击事件了,下面我们来看看RecyclerView如何添加和删除数据并在界面上显示。</p>
<h2 id="添加删除数据">添加删除数据</h2>
<p>以前在ListView当中,我们只要修改后数据用Adapter的notifyDatasetChange一下就可以更新界面。然而在RecyclerView中还有一些更高级的用法:</p>
<p>添加数据:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addItem</span>(DataModel content, <span class="keyword">int</span> position) {</div><div class="line"> datas.add(position, content);</div><div class="line"> notifyItemInserted(position); <span class="comment">//Attention!</span></div><div class="line">}</div></pre></td></tr></table></figure>
<p>删除数据:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">removeItem</span>(DataModel model) {</div><div class="line"> <span class="keyword">int</span> position = datas.indexOf(model);</div><div class="line"> datas.remove(position);</div><div class="line"> notifyItemRemoved(position);<span class="comment">//Attention!</span></div><div class="line">}</div></pre></td></tr></table></figure>
<p>值得注意的是RecyclerView的添加删除都是有默认的动画效果的,如果没有效果可以添加如下代码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mRecyclerView.setItemAnimator(<span class="keyword">new</span> DefaultItemAnimator());</div></pre></td></tr></table></figure>
<p>当然啦你也可以自己定义你自己的Animator,等我研究明白了也来讲一讲如何自定义这些效果~</p>
<p>感谢阅读,如果有什么建议或是错误的地方可以在底下留言~</p>
]]></content>
<summary type="html">
<![CDATA[<p>当使用了一段时间的RecyclerView,发现为其每一项添加点击事件并没有ListView那么轻松,像ListView直接加个OnItemClickListener就行了。<strong>实际上我们不要把RecyclerView当做ListView的一个升级版</strong>,希望大家把他看做一个容器,同时里面包含了很多不同的Item,它们可以以不同方式排列组合,非常灵活,点击方式你可以按照你自己的意愿进行实现。</p>
<p>本节主要讲解如何为RecyclerView添加点击事件, 并简单介绍如何进行Item增加删除。</p>
]]>
</summary>
<category term="android" scheme="http://jinyudong.com/tags/android/"/>
<category term="recycler view" scheme="http://jinyudong.com/tags/recycler-view/"/>
<category term="sdk" scheme="http://jinyudong.com/tags/sdk/"/>
</entry>
<entry>
<title><![CDATA[Introducing RecyclerView(一)]]></title>
<link href="http://jinyudong.com/2014/11/13/Introduce-RecyclerView-%E4%B8%80/"/>
<id>http://jinyudong.com/2014/11/13/Introduce-RecyclerView-一/</id>
<published>2014-11-12T16:06:42.000Z</published>
<updated>2014-11-13T16:12:43.000Z</updated>
<content type="html"><![CDATA[<p>RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好。接下来通过一系列的文章讲解如何使用RecyclerView,彻底抛弃ListView.</p>
<h2 id="介绍">介绍</h2>
<p>RecyclerView与ListView原理是类似的:都是仅仅维护少量的View并且可以展示大量的数据集。RecyclerView用以下两种方式简化了数据的展示和处理:</p>
<ul>
<li>使用LayoutManager来确定每一个item的排列方式。</li>
<li>为增加和删除项目提供默认的动画效果。 </li>
</ul>
<a id="more"></a>
<p>你也可以定义你自己的LayoutManager和添加删除动画,RecyclerView项目结构如下:</p>
<p><img src="https://developer.android.com/training/material/images/RecyclerView.png" alt=""></p>
<ul>
<li><p>Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。</p>
</li>
<li><p>LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)。</p>
</li>
</ul>
<p>目前SDK中提供了三种自带的LayoutManager:</p>
<ul>
<li><a href="https://developer.android.com/reference/android/support/v7/widget/LinearLayoutManager.html" target="_blank" rel="external">LinearLayoutManager</a></li>
<li><a href="https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.html" target="_blank" rel="external">GridLayoutManager</a></li>
<li><a href="https://developer.android.com/reference/android/support/v7/widget/StaggeredGridLayoutManager.html" target="_blank" rel="external">StaggeredGridLayoutManager</a></li>
</ul>
<h2 id="示例">示例</h2>
<p>本节所示示例是一个最简单的使用方法,在接下来几节中将会介绍更多RecyclerView的别的一些屌爆的用法。作者用的环境是Android Studio 0.8.6。</p>
<h3 id="1、添加依赖">1、添加依赖</h3>
<p>在AS的<code>build.gradle</code>中添加依赖,然后同步一下就可以引入依赖包:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">dependencies {</div><div class="line"> <span class="keyword">...</span></div><div class="line"> compile <span class="string">'com.android.support:recyclerview-v7:21.0.+'</span></div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="2、编写代码">2、编写代码</h3>
<p>添加完依赖之后,就开始写代码了,与ListView用法类似,也是先在xml布局文件中创建一个RecyclerView的布局:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="title">RelativeLayout</span> <span class="attribute">xmlns:android</span>=<span class="value">"http://schemas.android.com/apk/res/android"</span></span></div><div class="line"> <span class="attribute">xmlns:tools</span>=<span class="value">"http://schemas.android.com/tools"</span></div><div class="line"> <span class="attribute">android:layout_width</span>=<span class="value">"match_parent"</span></div><div class="line"> <span class="attribute">android:layout_height</span>=<span class="value">"match_parent"</span></div><div class="line"> <span class="attribute">tools:context</span>=<span class="value">".MainActivity"</span>></div><div class="line"> <span class="tag"><<span class="title">android.support.v7.widget.RecyclerView</span></span></div><div class="line"> <span class="attribute">android:id</span>=<span class="value">"@+id/my_recycler_view"</span></div><div class="line"> <span class="attribute">android:layout_width</span>=<span class="value">"match_parent"</span></div><div class="line"> <span class="attribute">android:layout_height</span>=<span class="value">"match_parent"</span></div><div class="line"> <span class="attribute">android:scrollbars</span>=<span class="value">"vertical"</span> /></div><div class="line"><span class="tag"></<span class="title">RelativeLayout</span>></span></div></pre></td></tr></table></figure>
<p>创建完布局之后在MainActivity中获取这个RecyclerView,并声明<code>LayoutManager</code>与<code>Adapter</code>,代码如下:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);</div><div class="line"><span class="comment">//创建默认的线性LayoutManager</span></div><div class="line">mLayoutManager = <span class="keyword">new</span> LinearLayoutManager(<span class="keyword">this</span>);</div><div class="line">mRecyclerView.setLayoutManager(mLayoutManager);</div><div class="line"><span class="comment">//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能</span></div><div class="line">mRecyclerView.setHasFixedSize(<span class="keyword">true</span>);</div><div class="line"><span class="comment">//创建并设置Adapter</span></div><div class="line">mAdapter = <span class="keyword">new</span> MyAdapter(getDummyDatas());</div><div class="line">mRecyclerView.setAdapter(mAdapter);</div></pre></td></tr></table></figure>
<p>接下来的问题就是Adapter的创建:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyAdapter</span> <span class="keyword">extends</span> <span class="title">RecyclerView</span>.<span class="title">Adapter</span><<span class="title">MyAdapter</span>.<span class="title">ViewHolder</span>> </span>{</div><div class="line"> <span class="keyword">public</span> String[] datas = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">public</span> <span class="title">MyAdapter</span>(String[] datas) {</div><div class="line"> <span class="keyword">this</span>.datas = datas;</div><div class="line"> }</div><div class="line"> <span class="comment">//创建新View,被LayoutManager所调用</span></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> ViewHolder <span class="title">onCreateViewHolder</span>(ViewGroup viewGroup, <span class="keyword">int</span> i) {</div><div class="line"> View view = LayoutInflater.from(viewGroup.getContext())</div><div class="line"> .inflate(R.layout.item,viewGroup,<span class="keyword">false</span>);</div><div class="line"> ViewHolder vh = <span class="keyword">new</span> ViewHolder(view);</div><div class="line"> <span class="keyword">return</span> vh;</div><div class="line"> }</div><div class="line"> <span class="comment">//将数据与界面进行绑定的操作</span></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onBindViewHolder</span>(ViewHolder viewHolder, <span class="keyword">int</span> i) {</div><div class="line"> viewHolder.mTextView.setText(datas[i]);</div><div class="line"> }</div><div class="line"> <span class="comment">//获取数据的数量</span></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getItemCount</span>() {</div><div class="line"> <span class="keyword">return</span> datas.length;</div><div class="line"> }</div><div class="line"> <span class="comment">//自定义的ViewHolder,持有每个Item的的所有界面元素</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ViewHolder</span> <span class="keyword">extends</span> <span class="title">RecyclerView</span>.<span class="title">ViewHolder</span> </span>{</div><div class="line"> <span class="keyword">public</span> TextView mTextView;</div><div class="line"> <span class="keyword">public</span> <span class="title">ViewHolder</span>(View view){</div><div class="line"> <span class="keyword">super</span>(view);</div><div class="line"> mTextView = (TextView) view.findViewById(R.id.text);</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="3、运行">3、运行</h3>
<p>写完这些代码这个例子既可以跑起来了。从例子也可以看出来,RecyclerView的用法并不比ListView复杂,反而更灵活好用,它将数据、排列方式、数据的展示方式都分割开来,因此可定制型,自定义的形式也非常多,非常灵活。</p>
<h4 id="横向布局">横向布局</h4>
<p>如果想要一个横向的List只要设置LinearLayoutManager如下就行,注意要声明mLayoutManager的类型是LinearLayoutManager而不是父类LayoutManager:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);</div></pre></td></tr></table></figure>
<h4 id="Grid布局">Grid布局</h4>
<p>如果想要一个Grid布局的列表,只要声明LayoutManager为GridLayoutManager即可:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">mLayoutManager = <span class="keyword">new</span> GridLayoutManager(context,columNum);</div><div class="line">mRecyclerView.setLayoutManager(mLayoutManager);</div></pre></td></tr></table></figure>
<p>注意,在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局。</p>
<h4 id="瀑布流布局">瀑布流布局</h4>
<p>瀑布流就使用StaggeredGridLayoutManager吧,具体方法与上面类似,就不做介绍啦。</p>
<h2 id="总结">总结</h2>
<p>本节介绍的是一个最最简单的RecyclerView的使用方法,后面将介绍一些更高级的用法。</p>
]]></content>
<summary type="html">
<![CDATA[<p>RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好。接下来通过一系列的文章讲解如何使用RecyclerView,彻底抛弃ListView.</p>
<h2 id="介绍">介绍</h2>
<p>RecyclerView与ListView原理是类似的:都是仅仅维护少量的View并且可以展示大量的数据集。RecyclerView用以下两种方式简化了数据的展示和处理:</p>
<ul>
<li>使用LayoutManager来确定每一个item的排列方式。</li>
<li>为增加和删除项目提供默认的动画效果。 </li>
</ul>
]]>
</summary>
<category term="android" scheme="http://jinyudong.com/tags/android/"/>
<category term="recycler view" scheme="http://jinyudong.com/tags/recycler-view/"/>
<category term="sdk" scheme="http://jinyudong.com/tags/sdk/"/>
</entry>
<entry>
<title><![CDATA[Android Studio SDK 更新方法]]></title>
<link href="http://jinyudong.com/2014/11/12/Android-Studio-SDK-Update/"/>
<id>http://jinyudong.com/2014/11/12/Android-Studio-SDK-Update/</id>
<published>2014-11-12T14:25:38.000Z</published>
<updated>2014-11-13T05:30:16.000Z</updated>
<content type="html"><![CDATA[<p>通常情况下,下载Android SDK需要连接谷歌的服务器进行下载,由于国内水深火热的网络,速度基本为0.好在国内也有一个更新的镜像地址。本文章介绍如何在不翻墙的情况下,使用国内镜像地址,更新android sdk.</p>
<a id="more"></a>
<h2 id="设置host">设置host</h2>
<p>首先在etc/hosts中设置hosts,需要管理员权限。使用vim对hosts进行编辑:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">sudo</span> vim hosts</div></pre></td></tr></table></figure>
<p>输入密码后进行编辑,添加如下几行:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#Google主页 </span></div><div class="line"><span class="number">203.208</span>.<span class="number">46.146</span> www.google.com </div><div class="line"><span class="comment">##这行是为了方便打开Android开发官网 现在好像不翻也可以打开 </span></div><div class="line"><span class="number">74.125</span>.<span class="number">113.121</span> developer.android.com </div><div class="line"><span class="comment">##更新的内容从以下地址下载 </span></div><div class="line"><span class="number">203.208</span>.<span class="number">46.146</span> dl.google.com </div><div class="line"><span class="number">203.208</span>.<span class="number">46.146</span> dl-ssl.google.com</div></pre></td></tr></table></figure>
<h2 id="更改Android_SDK_Manager设置">更改Android SDK Manager设置</h2>
<p><img src="http://dl2.iteye.com/upload/attachment/0097/7095/7e128ac5-bd43-38f4-8f8d-eaf388138c90.png" alt=""></p>
<p>在Preference中进行设置,修改配置如下:</p>
<blockquote>
<p>HTTP Proxy Server: mirrors.neusoft.edu.cn</p>
<p>HTTP Proxy Port: 80</p>
</blockquote>
<p>然后勾选强制使用http:</p>
<p><img src="http://dl2.iteye.com/upload/attachment/0097/7097/c75ffa94-21b5-3d90-8a22-a55d1c78b5d6.png" alt=""></p>
<p>然后就大功告成,可以愉快飞速的下载Android SDK而不用担心翻墙网速等问题啦。</p>
<p>参考:<a href="http://qianjigui.iteye.com/blog/2074695" target="_blank" rel="external">Android Studio SDK Manager无法正常下载如何设置</a></p>
]]></content>
<summary type="html">
<![CDATA[<p>通常情况下,下载Android SDK需要连接谷歌的服务器进行下载,由于国内水深火热的网络,速度基本为0.好在国内也有一个更新的镜像地址。本文章介绍如何在不翻墙的情况下,使用国内镜像地址,更新android sdk.</p>
]]>
</summary>
<category term="android" scheme="http://jinyudong.com/tags/android/"/>
<category term="android studio" scheme="http://jinyudong.com/tags/android-studio/"/>
<category term="sdk" scheme="http://jinyudong.com/tags/sdk/"/>
</entry>
<entry>
<title><![CDATA[How to create a ripple effect]]></title>
<link href="http://jinyudong.com/2014/11/11/How-to-create-ripple-effect/"/>
<id>http://jinyudong.com/2014/11/11/How-to-create-ripple-effect/</id>
<published>2014-11-11T15:07:25.000Z</published>
<updated>2014-11-11T15:15:46.000Z</updated>
<content type="html"><![CDATA[<p>挖个坑,分析一下Material design 中的ripple effect是如何实现的。</p>
]]></content>
<summary type="html">
<![CDATA[<p>挖个坑,分析一下Material design 中的ripple effect是如何实现的。</p>
]]>
</summary>
<category term="android" scheme="http://jinyudong.com/tags/android/"/>
<category term="material design" scheme="http://jinyudong.com/tags/material-design/"/>
</entry>
</feed>