-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
989 lines (806 loc) · 342 KB
/
atom.xml
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
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Alvin-一座小楼</title>
<subtitle>Test</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://czhzero.com/"/>
<updated>2017-07-03T16:00:23.000Z</updated>
<id>http://czhzero.com/</id>
<author>
<name>Alvin-一座小楼</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Activity的setContentView方法报空指针错误</title>
<link href="http://czhzero.com/2017/06/02/LayoutInflater-createViewFromTag-error/"/>
<id>http://czhzero.com/2017/06/02/LayoutInflater-createViewFromTag-error/</id>
<published>2017-06-02T09:25:40.000Z</published>
<updated>2017-07-03T16:00:23.000Z</updated>
<content type="html"><p>Android写xml的时候,有时候写错某些标签,编译不会报错,例如码字的时候,可能会不小心把一些基本单词的大小写混淆。</p>
<a id="more"></a>
<figure class="highlight plain"><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">&lt;view</span><br><span class="line"> android:layout_width=&quot;match_parent&quot;</span><br><span class="line"> android:layout_height=&quot;0.5dp&quot;</span><br><span class="line"> android:layout_marginBottom=&quot;@dimen/margin_normal&quot;</span><br><span class="line"> android:layout_marginTop=&quot;@dimen/margin_normal&quot;</span><br><span class="line"> android:background=&quot;@color/grey_E0E3E1&quot; /&gt;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>这里的<code>view</code>必须首字母大写,否则Activity的setContentView方法会报错。</p>
</blockquote>
<p>错误日志如下,</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">FATAL EXCEPTION: main</span><br><span class="line">Process: com.gezbox.winder.parttime, PID: 12924</span><br><span class="line">java.lang.RuntimeException: Unable to start activity ComponentInfo&#123;com.gezbox.winder.parttime/com.gezbox.task.activity.OrderIncomeReportActivity&#125;: java.lang.NullPointerException: Attempt to invoke virtual method &apos;boolean java.lang.String.equals(java.lang.Object)&apos; on a null object reference</span><br><span class="line">at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2660)</span><br><span class="line">at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2730)</span><br><span class="line">at android.app.ActivityThread.access$800(ActivityThread.java:185)</span><br><span class="line">at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567)</span><br><span class="line">at android.os.Handler.dispatchMessage(Handler.java:111)</span><br><span class="line">at android.os.Looper.loop(Looper.java:194)</span><br><span class="line">at android.app.ActivityThread.main(ActivityThread.java:5847)</span><br><span class="line">at java.lang.reflect.Method.invoke(Native Method)</span><br><span class="line">at java.lang.reflect.Method.invoke(Method.java:372)</span><br><span class="line">at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1010)</span><br><span class="line">at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)</span><br><span class="line">Caused by: java.lang.NullPointerException: Attempt to invoke virtual method &apos;boolean java.lang.String.equals(java.lang.Object)&apos; on a null object reference</span><br><span class="line"></span><br><span class="line">//createViewFromTag方法报错</span><br><span class="line">at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:721)</span><br><span class="line"></span><br><span class="line">at android.view.LayoutInflater.rInflate(LayoutInflater.java:812)</span><br><span class="line">at android.view.LayoutInflater.rInflate(LayoutInflater.java:815)</span><br><span class="line">at android.view.LayoutInflater.inflate(LayoutInflater.java:510)</span><br><span class="line">at android.view.LayoutInflater.inflate(LayoutInflater.java:420)</span><br><span class="line">at android.view.LayoutInflater.inflate(LayoutInflater.java:371)</span><br><span class="line">at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:437)</span><br><span class="line"></span><br><span class="line">//SetContentView方法报错</span><br><span class="line"></span><br><span class="line">at android.app.Activity.setContentView(Activity.java:2205)</span><br><span class="line">at com.gezbox.task.activity.OrderIncomeReportActivity.onCreate(OrderIncomeReportActivity.java:24)</span><br><span class="line">at android.app.Activity.performCreate(Activity.java:6117)</span><br><span class="line">at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)</span><br><span class="line">at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2613)</span><br><span class="line">at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2730) </span><br><span class="line">at android.app.ActivityThread.access$800(ActivityThread.java:185) </span><br><span class="line">at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567) </span><br><span class="line">at android.os.Handler.dispatchMessage(Handler.java:111) </span><br><span class="line">at android.os.Looper.loop(Looper.java:194) </span><br><span class="line">at android.app.ActivityThread.main(ActivityThread.java:5847) </span><br><span class="line">at java.lang.reflect.Method.invoke(Native Method) </span><br><span class="line">at java.lang.reflect.Method.invoke(Method.java:372) </span><br><span class="line">at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1010) </span><br><span class="line">at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)</span><br></pre></td></tr></table></figure>
<p>遇到这种错误大小写错误,一个不注意,还真有可能浪费很多时间。</p>
</content>
<summary type="html">
<p>Android写xml的时候,有时候写错某些标签,编译不会报错,例如码字的时候,可能会不小心把一些基本单词的大小写混淆。</p>
</summary>
<category term="Bug分析" scheme="http://czhzero.com/categories/Bug%E5%88%86%E6%9E%90/"/>
<category term="setContentView createViewFromTag" scheme="http://czhzero.com/tags/setContentView-createViewFromTag/"/>
</entry>
<entry>
<title>Android Studio Error:failed to find Build Tools revision 25.0.2</title>
<link href="http://czhzero.com/2017/05/11/build-tools-error/"/>
<id>http://czhzero.com/2017/05/11/build-tools-error/</id>
<published>2017-05-11T06:50:40.000Z</published>
<updated>2017-07-03T16:00:23.000Z</updated>
<content type="html"><p>Android Studio 升级时,会有各种插件版本需要进行更新。<a href="http://czhzero.com/2016/07/21/android-version-configure/">Android Studio 需要配置的版本号整理</a> 这里有详细介绍。</p>
<p>本文主要介绍<code>failed to find Build Tools revision</code>这个问题。</p>
<a id="more"></a>
<p>目前来说Android Studio的下载源已经可以不用翻墙,直接下载build tools了,所以下载一般是会成功的。</p>
<p><img src="http://o7y1sf21i.bkt.clouddn.com/blog/024/2017051101.png" alt=""></p>
<p>但是有时候会遇到,明明下载成功了,Android Stuido却还是提示build fail问题。</p>
<p>打开Android Studio 的Sdk Manager, 发现状态也还是<code>[not installed]</code>状态。</p>
<p><img src="http://o7y1sf21i.bkt.clouddn.com/blog/024/2017051102.png" alt=""></p>
<p>尝试过用Android Studio的tools工具命令,<code>android list sdk -a</code>查看版本,版本信息全部正常。</p>
<p>猜想一定是哪个配置文件一直没更新或者错误,从而导致Android Studio一直找不到Build Tools。</p>
<p><img src="http://o7y1sf21i.bkt.clouddn.com/blog/024/2017051103.png" alt=""></p>
<p>一个个排查,发现这个<code>source.properties</code>文件坑了Android Studio,让他一直找不到Build Tools Version。</p>
<figure class="highlight plain"><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">### Android Tool: Source of this archive.</span><br><span class="line">#Tue May 19 11:31:42 CST 2015</span><br><span class="line">Archive.HostOs=macosx</span><br><span class="line">Pkg.License=To get .....\n\nJune 2014.\n </span><br><span class="line">Pkg.LicenseRef=android-sdk-license</span><br><span class="line">Pkg.Obsolete=</span><br><span class="line">Pkg.Revision=21.1.1</span><br><span class="line">Pkg.SourceUrl=https\://dl-ssl.google.com/android/repository/repository-10.xml</span><br></pre></td></tr></table></figure>
<p>删掉这个文件重新,Build成功。貌似没有这个文件sdk照样可以使用。</p>
</content>
<summary type="html">
<p>Android Studio 升级时,会有各种插件版本需要进行更新。<a href="http://czhzero.com/2016/07/21/android-version-configure/">Android Studio 需要配置的版本号整理</a> 这里有详细介绍。</p>
<p>本文主要介绍<code>failed to find Build Tools revision</code>这个问题。</p>
</summary>
<category term="Android" scheme="http://czhzero.com/categories/Android/"/>
<category term="build-tools" scheme="http://czhzero.com/tags/build-tools/"/>
</entry>
<entry>
<title>EditText的针对输入法的强行显示与隐藏</title>
<link href="http://czhzero.com/2017/04/25/edittext-forbid-input/"/>
<id>http://czhzero.com/2017/04/25/edittext-forbid-input/</id>
<published>2017-04-25T08:23:24.000Z</published>
<updated>2017-04-30T02:12:46.000Z</updated>
<content type="html"><p>EditText是Android中最常用的控件之一,很多时候我们需要对这个控件输入与否进行控制。</p>
<a id="more"></a>
<h2 id="自动弹出输入法"><a href="#自动弹出输入法" class="headerlink" title="自动弹出输入法"></a>自动弹出输入法</h2><h3 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h3><figure class="highlight plain"><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">&lt;activity android:name=&quot;.ui.login&quot;</span><br><span class="line"> android:configChanges=&quot;orientation|keyboardHidden|locale&quot;</span><br><span class="line"> android:screenOrientation=&quot;portrait&quot;</span><br><span class="line"> android:windowSoftInputMode=&quot;stateVisible|adjustPan&quot; &gt; </span><br><span class="line">&lt;/activit</span><br></pre></td></tr></table></figure>
<p>设置stateVisible属性。不过这个方法有时候并不管用。</p>
<h3 id="方法二-推荐"><a href="#方法二-推荐" class="headerlink" title="方法二(推荐)"></a>方法二(推荐)</h3><figure class="highlight plain"><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><br><span class="line"> * 强行弹出输入法</span><br><span class="line"> *</span><br><span class="line"> * @param activity</span><br><span class="line"> * @param editText</span><br><span class="line"> */</span><br><span class="line">public static void showSoftInputFromWindow(Activity activity, EditText editText) &#123;</span><br><span class="line"> editText.setFocusable(true);</span><br><span class="line"> editText.setFocusableInTouchMode(true);</span><br><span class="line"> editText.requestFocus();</span><br><span class="line"> activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="首次进入禁止弹出输入法"><a href="#首次进入禁止弹出输入法" class="headerlink" title="首次进入禁止弹出输入法"></a>首次进入禁止弹出输入法</h2><h3 id="方法一-1"><a href="#方法一-1" class="headerlink" title="方法一"></a>方法一</h3><figure class="highlight plain"><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">&lt;activity android:name=&quot;.Main&quot;</span><br><span class="line">android:label=&quot;@string/app_name&quot;</span><br><span class="line">android:windowSoftInputMode=&quot;adjustUnspecified|stateHidden&quot;</span><br><span class="line">android:configChanges=&quot;orientation|keyboardHidden&quot;&gt;</span><br><span class="line"></span><br><span class="line">&lt;/activity&gt;</span><br></pre></td></tr></table></figure>
<p>设置android:windowSoftInputMode为stateHidden。</p>
<h3 id="方法二-推荐-1"><a href="#方法二-推荐-1" class="headerlink" title="方法二(推荐)"></a>方法二(推荐)</h3><p>在对应的xml文件里面,添加一个看不见的view,设置焦点。</p>
<figure class="highlight plain"><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">&lt;View</span><br><span class="line"> android:layout_width=&quot;wrap_content&quot;</span><br><span class="line"> android:layout_height=&quot;wrap_content&quot;</span><br><span class="line"> android:focusable=&quot;true&quot;</span><br><span class="line"> android:focusableInTouchMode=&quot;true&quot;&gt;&lt;/View&gt;</span><br></pre></td></tr></table></figure>
<h2 id="永久禁止弹出输入法"><a href="#永久禁止弹出输入法" class="headerlink" title="永久禁止弹出输入法"></a>永久禁止弹出输入法</h2><h3 id="方法一-推荐"><a href="#方法一-推荐" class="headerlink" title="方法一 (推荐)"></a>方法一 (推荐)</h3><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 永久隐藏softinput</span><br><span class="line"> *</span><br><span class="line"> * @param editText</span><br><span class="line"> */</span><br><span class="line">public static void hiddenSoftInputFromWindow(Activity activity, EditText editText) &#123;</span><br><span class="line"> if (android.os.Build.VERSION.SDK_INT &lt;= 10) &#123;//4.0以下</span><br><span class="line"> editText.setInputType(InputType.TYPE_NULL);</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> activity.getWindow().setSoftInputMode(</span><br><span class="line"> WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);</span><br><span class="line"> try &#123;</span><br><span class="line"> Class&lt;EditText&gt; cls = EditText.class;</span><br><span class="line"> Method setShowSoftInputOnFocus;</span><br><span class="line"> setShowSoftInputOnFocus = cls.getMethod(&quot;setShowSoftInputOnFocus&quot;,</span><br><span class="line"> boolean.class);</span><br><span class="line"> setShowSoftInputOnFocus.setAccessible(true);</span><br><span class="line"> setShowSoftInputOnFocus.invoke(editText, false);</span><br><span class="line"> &#125; catch (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h3><figure class="highlight plain"><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">&lt;EditText</span><br><span class="line"> android:layout_width=&quot;wrap_content&quot;</span><br><span class="line"> android:layout_height=&quot;wrap_content&quot;</span><br><span class="line"> android:inputType=&quot;none&quot;/&gt;</span><br></pre></td></tr></table></figure>
<p>这种方法,无法显示光标。</p>
<h2 id="无输入法的插入与删除"><a href="#无输入法的插入与删除" class="headerlink" title="无输入法的插入与删除"></a>无输入法的插入与删除</h2><h3 id="EditText最大长度"><a href="#EditText最大长度" class="headerlink" title="EditText最大长度"></a>EditText最大长度</h3><p>输入法被禁止后,光标跳转需要通过requestFocus进行手动跳转。</p>
<p>通常当输入内容达到输入框最长长度时,进行自动跳转</p>
<p>获取EditText最长输入长度方法如下。</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 获取edittext的最大长度</span><br><span class="line"> * @param et</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line">public static int getEditTextMaxLength(EditText et) &#123;</span><br><span class="line"> int length = 0;</span><br><span class="line"> try &#123;</span><br><span class="line"> InputFilter[] inputFilters = et.getFilters();</span><br><span class="line"> for (InputFilter filter : inputFilters) &#123;</span><br><span class="line"> Class&lt;?&gt; c = filter.getClass();</span><br><span class="line"> if (c.getName().equals(&quot;android.text.InputFilter$LengthFilter&quot;)) &#123;</span><br><span class="line"> Field[] f = c.getDeclaredFields();</span><br><span class="line"> for (Field field : f) &#123;</span><br><span class="line"> if (field.getName().equals(&quot;mMax&quot;)) &#123;</span><br><span class="line"> field.setAccessible(true);</span><br><span class="line"> length = (Integer) field.get(filter);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; catch (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> return length;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="插入字符"><a href="#插入字符" class="headerlink" title="插入字符"></a>插入字符</h3><figure class="highlight plain"><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><br><span class="line"> * 插入字符</span><br><span class="line"> * @param et</span><br><span class="line"> * @param str</span><br><span class="line"> */</span><br><span class="line">public static boolean insertEditText(EditText et, String str) &#123;</span><br><span class="line"> int position = et.getSelectionStart();</span><br><span class="line"></span><br><span class="line"> if(position &gt;= getEditTextMaxLength(et)) &#123;</span><br><span class="line"> return false; //插入失败</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> Editable editable = et.getText();</span><br><span class="line"> editable.insert(position, str);</span><br><span class="line"> return true;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="删除字符"><a href="#删除字符" class="headerlink" title="删除字符"></a>删除字符</h3><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 删除字符</span><br><span class="line"> *</span><br><span class="line"> * @param et</span><br><span class="line"> */</span><br><span class="line">public static boolean deleteEditText(EditText et) &#123;</span><br><span class="line"> int position = et.getSelectionStart();</span><br><span class="line"> Editable editable = et.getText();</span><br><span class="line"> if (position &gt; 0) &#123;</span><br><span class="line"> editable.delete(position - 1, position);</span><br><span class="line"> return true;</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> return false; //删除失败</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></content>
<summary type="html">
<p>EditText是Android中最常用的控件之一,很多时候我们需要对这个控件输入与否进行控制。</p>
</summary>
<category term="Android" scheme="http://czhzero.com/categories/Android/"/>
<category term="EditText" scheme="http://czhzero.com/tags/EditText/"/>
</entry>
<entry>
<title>ScrollView内部嵌套ListView的高度计算问题</title>
<link href="http://czhzero.com/2017/04/25/listview-in-scrollview/"/>
<id>http://czhzero.com/2017/04/25/listview-in-scrollview/</id>
<published>2017-04-25T07:55:25.000Z</published>
<updated>2017-04-30T02:12:46.000Z</updated>
<content type="html"><p>ScrollView嵌套ListView只显示一行的解决办法相信很多人都遇到过,原因是是因为ScrollView包着之后,ListView的onMeasure方法得到的父布局的mode为View.MeasureSpec.UNSPECIFIED,导致ListView计算的高度错误引起。</p>
<a id="more"></a>
<p>解决方案:</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Created by chenzhaohua on 17/4/25.</span><br><span class="line"> */</span><br><span class="line"></span><br><span class="line">public class CustomListView extends ListView &#123;</span><br><span class="line"></span><br><span class="line"> public CustomListView(Context context, AttributeSet attrs) &#123;</span><br><span class="line"> super(context, attrs);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public CustomListView(Context context) &#123;</span><br><span class="line"> super(context);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public CustomListView(Context context, AttributeSet attrs, int defStyle) &#123;</span><br><span class="line"> super(context, attrs, defStyle);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) &#123;</span><br><span class="line"></span><br><span class="line"> int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE &gt;&gt; 2,</span><br><span class="line"> MeasureSpec.AT_MOST); //将模式改为AT_MOST,并且将size设置为很大的数值。</span><br><span class="line"> super.onMeasure(widthMeasureSpec, expandSpec);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></content>
<summary type="html">
<p>ScrollView嵌套ListView只显示一行的解决办法相信很多人都遇到过,原因是是因为ScrollView包着之后,ListView的onMeasure方法得到的父布局的mode为View.MeasureSpec.UNSPECIFIED,导致ListView计算的高度错误引起。</p>
</summary>
<category term="Bug分析" scheme="http://czhzero.com/categories/Bug%E5%88%86%E6%9E%90/"/>
<category term="ListView嵌套" scheme="http://czhzero.com/tags/ListView%E5%B5%8C%E5%A5%97/"/>
</entry>
<entry>
<title>Java多态的概念</title>
<link href="http://czhzero.com/2017/04/19/java-polymorphism/"/>
<id>http://czhzero.com/2017/04/19/java-polymorphism/</id>
<published>2017-04-19T14:39:24.000Z</published>
<updated>2017-04-19T14:49:17.000Z</updated>
<content type="html"><p>“polymorphism(多态)”一词来自希腊语,意为“多种形式”。多数Java程序员把多态看作对象的一种能力,使其能调用正确的方法版本。尽管如此,这种面向实现的观点导致了多态的神奇功能,胜于仅仅把多态看成纯粹的概念。</p>
<p>Java中的多态总是子类型的多态。几乎是机械式产生了一些多态的行为,使我们不去考虑其中涉及的类型问题。本文研究了一种面向类型的对象观点,分 析了如何将对象能够 表现的行为和对象即将表现的行为分离开来。抛开Java中的多态都是来自继承的概念,我们仍然可以感到,Java中的接口是一组没有公共代码的对象共享实现。</p>
<a id="more"></a>
<h2 id="多态的好处"><a href="#多态的好处" class="headerlink" title="多态的好处"></a>多态的好处</h2><p>消除类型之间的耦合关系。</p>
<ul>
<li><p>可替换性(substitutability)。</p>
<p> 多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。</p>
</li>
<li><p>可扩充性(extensibility)。</p>
<p> 多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。</p>
</li>
<li><p>接口性(interface-ability)。</p>
<p> 多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。</p>
</li>
<li><p>灵活性(flexibility)。</p>
<p> 它在应用中体现了灵活多样的操作,提高了使用效率。</p>
</li>
<li><p>简化性(simplicity)。</p>
<p> 多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。</p>
</li>
</ul>
<h2 id="多态的分类"><a href="#多态的分类" class="headerlink" title="多态的分类"></a>多态的分类</h2><ul>
<li>广义多态分类<ul>
<li>强制的 </li>
<li>重载的</li>
<li>参数的</li>
<li>包含的</li>
</ul>
</li>
<li>狭义多态分类<ul>
<li>动态绑定</li>
</ul>
</li>
</ul>
<h3 id="强制的多态"><a href="#强制的多态" class="headerlink" title="强制的多态"></a>强制的多态</h3><p>强制多态隐式的将参数按某种方法,转换成编译器认为正确的类型以避免错误。在以下的表达式中,编译器必须决定二元运算符‘+’所应做的工作:</p>
<figure class="highlight plain"><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><br><span class="line">2.0 + 2.0</span><br><span class="line"></span><br><span class="line">2.0 + 2</span><br><span class="line"></span><br><span class="line">2.0 + &quot;2&quot;</span><br></pre></td></tr></table></figure>
<p>第一个表达式将两个double的 操作数相加;Java中特别声明了这种用法。</p>
<p>第二个表达式将double型和int相加。Java中没有明确定义这种运算。不过,编 译器隐式的将第二个操作数转换为double型,并作double型的加法。做对程序员来说十分方便,否则将会抛出一个编译错误,或者强制程序员显式的将 int转换为double。</p>
<p>第三个表达式将double与一个String相加。Java中同样没有定义这样的操作。所以,编译器将 double转换成String类型,并将他们做串联。</p>
<p>强制多态也会发生在方法调用中。</p>
<p>假设类A继承了类Base,类B有一个方法,原型为m(Base),在下面的代码中,编译器隐式的将A类的对象a转化为Base类的对象。这种隐式的转换使 m(Base)方法使用所有能转换成Base类的所有参数。</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">public class Base &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class A extends Base &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class B &#123;</span><br><span class="line"> public void m(Base base) &#123;</span><br><span class="line"> //dosomething</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class Client &#123;</span><br><span class="line"> B b = new B(); </span><br><span class="line"> A a = new A(); </span><br><span class="line"> b.m(a); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>并且,隐式的强制转换,可以避免类型转换的麻烦,减少编译错误。当然,编译器仍然会优先验证符合定义的对象类型。</p>
<h3 id="重载的多态"><a href="#重载的多态" class="headerlink" title="重载的多态"></a>重载的多态</h3><p>重载 允许用相同的运算符或方法,去表示截然不同的意义。‘+’在上面的程序中有两个意思:两个double型的数相加;两个串相连。另外还有整型相加,长整 型,等等。这些运算符的重载,依赖于编译器根据上下文做出的选择。以往的编译器会把操作数隐式转换为完全符合操作符的类型。虽然Java明确支持重载,但 不支持用户定义的操作符重载。</p>
<p>Java支持用户定义的函数重载。一个类中可以有相同名字的方法,这些方法可以有不同的意义。这些重载 的方法中,必须满足参数数目不同,相同位置上的参数类型不同。这些不同可以帮助编译器区分不同版本的方法。</p>
<p>编译器以这种唯一表示的特 征来表示不同的方法,比用名字表示更为有效。据此,所有的多态行为都能编译通过。</p>
<p>强制和重载的多态都被分类为特定的多态,因为这些多 态都是在特定的意义上的。这些被划入多态的特性给程序员带来了很大的方便。强制多态排除了麻烦的类型和编译错误。重载多态像一块糖,允许程序员用相同的名 字表示不同的方法,很方便。</p>
<h3 id="参数的多态"><a href="#参数的多态" class="headerlink" title="参数的多态"></a>参数的多态</h3><p>参数多态允许把许多类型抽象成单一的表示。例如,List抽象类中,描述了一组具有同样特征的对象,提供了一个通用的模板。你可以通过指定一种类型以重用这个抽象类。这些参数可以是任何用户定义的类型,大量的用 户可以使用这个抽象类,因此参数多态毫无疑问的成为最强大的多态。</p>
<p>乍一看,上面抽象类好像是java.util.List的功能。然 而,Java实际上并不支持真正的安全类型风格的参数多态,这也是java.util.List和java.util的其他集合类是用原始的 java.lang.Object写的原因。Java的单根继承方式解决了部分问题,但没有发挥出参数多态的全部功能。</p>
<h3 id="包含的多态"><a href="#包含的多态" class="headerlink" title="包含的多态"></a>包含的多态</h3><p>包含多态通过值的类型和集合的包含关系实现了多态的行为.在包括Java在内的众多面向对象语言中,包含关系是子类型的。所以,Java的包含多态是子类型的多态。</p>
<p>在早期,Java开发者们所提及的多态就特指子类型的多态。通过一种面向类型的观点,我们可以看到子类型多态的强大功能。</p>
<p>更多关于广义分类多态的解释,请参看<a href="http://blog.csdn.net/xiaoyu714543065/article/details/8130027" target="_blank" rel="external">java中实现多态的机制是什么?</a></p>
<h2 id="动态绑定"><a href="#动态绑定" class="headerlink" title="动态绑定"></a>动态绑定</h2><p>动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。</p>
<p>JAVA虚拟机调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当虚拟机调用一个实例方法时,它会基于对象实际 的类型(只能在运行时得知)来选择所调用的方法,这就是动态绑定,是多态的一种。动态绑定为解决实际的业务问题提供了很大的灵活性,是一种非常优美的机制。</p>
<p> JAVA虚拟机规范并没有规定JAVA对象在堆里是如何表示的。对象的内部表示也影响着整个堆以及垃圾收集器的设计,它由虚拟机的实现者决定。</p>
<ul>
<li><p>JAVA对象模型</p>
<p>JAVA对象中包含的基本数据由它所属的类及其所有超类声明的实例变量组成。只要有一个对象引用,虚拟机就必须能够快速地定位对象实例的数据。另外,它也 必须能通过该对象引用访问相应的类数据(存储于方法区的类型信息),因此在对象中通常会有一个指向方法区的指针。当程序在运行时需要转换某个对象引用为另 外一种类型时,虚拟机必须要检查这种转换是否被允许,被转换的对象是否的确是被引用的对象或者它的超类型。当程序在执行instanceof操作时,虚拟 机也进行了同样的检查。所以虚拟机都需要查看被引用的对象的类数据。</p>
<p>不管虚拟机的实现使用什么样的对象表示法,很可能每个对象都有一个方法表因为方法表加快了调用实例方法时的效率。但是JAVA虚拟机规范并未要求必须使用方法表,所以并不是所有实现中都会使用它。</p>
<p>下面是一种JAVA对象的内存表示:</p>
<p><img src="http://o7y1sf21i.bkt.clouddn.com/blog/009/binding1.png" alt=""></p>
<p>方法数据存放在类的方法区中,包含一个方法的具体实现的字节码二进制。方法指针直接指向这个方法在内存中的起始位置,通过方法指针就可以找到这个方法。</p>
</li>
<li><p>动态绑定内部机制</p>
</li>
</ul>
<p>方法表是一个指向方法区中的方法指针的数组。方法表中不包含static、private等静态绑定的方法,仅仅包含那些需要动态绑定的实例方法。</p>
<p> 在方法表中,来自超类的方法出现在来自子类的方法之前,并且排列方法指针的顺序和方法在class文件中出现的顺序相同,这种排列顺序的例外情况是,被子类的方法覆盖的方法出现在超类中该方法第一次出现的地方。</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public class Base </span><br><span class="line">&#123; </span><br><span class="line"> public Base() </span><br><span class="line"> &#123; </span><br><span class="line"> &#125; </span><br><span class="line"> </span><br><span class="line"> public void test() </span><br><span class="line"> &#123; </span><br><span class="line"> System.out.println( &quot;int Base&quot; ); </span><br><span class="line"> &#125; </span><br><span class="line"> </span><br><span class="line"> public void print() </span><br><span class="line"> &#123; </span><br><span class="line"> &#125; </span><br><span class="line">&#125; </span><br><span class="line"> </span><br><span class="line">public class Derive extends Base </span><br><span class="line">&#123; </span><br><span class="line"> public Derive() </span><br><span class="line"> &#123; </span><br><span class="line"> &#125; </span><br><span class="line"> </span><br><span class="line"> public void test() </span><br><span class="line"> &#123; </span><br><span class="line"> System.out.println( &quot;int Derive&quot; ); </span><br><span class="line"> &#125; </span><br><span class="line"> </span><br><span class="line"> public void sayHello() </span><br><span class="line"> &#123; </span><br><span class="line"> &#125; </span><br><span class="line"> </span><br><span class="line"> public static void main( String[] args ) </span><br><span class="line"> &#123; </span><br><span class="line"> Base base = new Derive(); </span><br><span class="line"> base.test(); </span><br><span class="line"> &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p> 上例中的Base和Derive的方法表如下:</p>
<p> <img src="http://o7y1sf21i.bkt.clouddn.com/blog/009/binding2.png" alt=""></p>
<p> 在这个例子里,test()方法在Base和Derive的方法表中都是同一个位置-位置1。在Base方法表中,test()指针是Base的test()方法内存地址;而在Derive方法表中,方法表的位置1放置的是Derive的test()方法内存地址。</p>
<p> 当JAVA虚拟机执行base.test()时,通过base引用可以找到base所指向的实际对象的内存位置,现在虚拟机不知道base引用的实际对象 是Base还是Derive。但是根据上面的对象内存模型,虚拟机从对象内存中的第一个指针“特殊结构指针”开始,可以找到实际对象的类型数据和 Class实例,这样虚拟机就可以知道base引用的实际对象是Derive对。为了执行test(),虚拟机需要找到test()的字节码,方法的字节 码存放在方法区中。虚拟机从对象内存中的第一个指针“特殊结构指针”开始,搜寻方法表的位置1,位置1指向的test()方法是Derive类的 test()方法,这就是JAVA虚拟机将要执行的test()的字节码。现在,虚拟机知道了调用的实际对象是Derive对象,调用的实际test() 方法是Derive类的test()方法,所以JAVA虚拟机能够正确执行-调用base引用的实际对象的方法而不是base引用本身的方法。</p>
<p> 这是动态绑定的一种实现方式,根据不同的JAVA虚拟机平台和不同的实际约束,动态绑定可以有不同的内部实现机制。</p>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ul>
<li><a href="http://www.cnblogs.com/TalkWithWorld/p/5641169.html" target="_blank" rel="external">java中实现多态的机制是什么?</a></li>
</ul>
</content>
<summary type="html">
<p>“polymorphism(多态)”一词来自希腊语,意为“多种形式”。多数Java程序员把多态看作对象的一种能力,使其能调用正确的方法版本。尽管如此,这种面向实现的观点导致了多态的神奇功能,胜于仅仅把多态看成纯粹的概念。</p>
<p>Java中的多态总是子类型的多态。几乎是机械式产生了一些多态的行为,使我们不去考虑其中涉及的类型问题。本文研究了一种面向类型的对象观点,分 析了如何将对象能够 表现的行为和对象即将表现的行为分离开来。抛开Java中的多态都是来自继承的概念,我们仍然可以感到,Java中的接口是一组没有公共代码的对象共享实现。</p>
</summary>
<category term="Java" scheme="http://czhzero.com/categories/Java/"/>
<category term="多态" scheme="http://czhzero.com/tags/%E5%A4%9A%E6%80%81/"/>
</entry>
<entry>
<title>设计模式学习笔记-观察者模式</title>
<link href="http://czhzero.com/2017/04/06/design-pattern-observer/"/>
<id>http://czhzero.com/2017/04/06/design-pattern-observer/</id>
<published>2017-04-06T15:22:24.000Z</published>
<updated>2017-04-06T15:36:25.000Z</updated>
<content type="html"><p>观察者模式是一个非常高的模式,简单来讲就是一种订阅发布系统,用来将观察者与被观察者解偶。</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><p>定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并被自动更新。</p>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><ul>
<li>观察者和被观察者之间是抽象耦合,应对业务变化</li>
<li>增强系统灵活性、可扩展性</li>
</ul>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><p>开发观察者模式需要考虑开放效率和运行效率问题。</p>
<ul>
<li>代码开发调试比较复杂</li>
<li>顺序执行的观察者模式,有时不如异步任务。</li>
</ul>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><ul>
<li>关联行为场景,需要注意的是,关联行为说可拆分待,而不是组合关系</li>
<li>事件多极触发场景</li>
<li>跨系统消息交换场景,如消息队列、事件总线的处理机制</li>
</ul>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><ul>
<li>ListView的notifyDataSetChanged()方法</li>
</ul>
<hr>
<ul>
<li>定义观察者所具有的共同的接口</li>
</ul>
<figure class="highlight plain"><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">interface Observer &#123;</span><br><span class="line"> public void update();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>定义两个观察者</li>
</ul>
<figure class="highlight plain"><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">class ObserverA implements Observer &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void update() &#123;</span><br><span class="line"> System.out.println(&quot;ObserverA has received!&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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">class ObserverB implements Observer &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void update() &#123;</span><br><span class="line"> System.out.println(&quot;ObserverB has received!&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>定义被观察者所具有的抽象父类</li>
</ul>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">abstract class Observable &#123;</span><br><span class="line"></span><br><span class="line"> private Vector&lt;Observer&gt; vector = new Vector&lt;Observer&gt;();</span><br><span class="line"></span><br><span class="line"> public void add(Observer observer) &#123;</span><br><span class="line"> vector.add(observer);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void del(Observer observer) &#123;</span><br><span class="line"> vector.remove(observer);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void notifyObservers() &#123;</span><br><span class="line"> Enumeration&lt;Observer&gt; enumo = vector.elements();</span><br><span class="line"> while (enumo.hasMoreElements()) &#123;</span><br><span class="line"> enumo.nextElement().update();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void operation() &#123;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>定义具体的被观察者</li>
</ul>
<figure class="highlight plain"><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">class ConcretObservable extends Observable&#123;</span><br><span class="line"> </span><br><span class="line"> @Override </span><br><span class="line"> public void operation() &#123; </span><br><span class="line"> System.out.println(&quot;update self!&quot;); </span><br><span class="line"> notifyObservers(); </span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>场景类</li>
</ul>
<figure class="highlight plain"><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">public class ObserverTest &#123; </span><br><span class="line"> </span><br><span class="line"> public static void main(String[] args) &#123; </span><br><span class="line"> Observable sub = new ConcretObservable(); </span><br><span class="line"> sub.add(new ObserverA()); </span><br><span class="line"> sub.add(new ObserverB()); </span><br><span class="line"> </span><br><span class="line"> sub.operation(); </span><br><span class="line"> &#125; </span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</content>
<summary type="html">
<p>观察者模式是一个非常高的模式,简单来讲就是一种订阅发布系统,用来将观察者与被观察者解偶。</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="观察者模式" scheme="http://czhzero.com/tags/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>设计模式学习笔记-策略模式</title>
<link href="http://czhzero.com/2017/04/06/design-pattern-stragety/"/>
<id>http://czhzero.com/2017/04/06/design-pattern-stragety/</id>
<published>2017-04-06T14:02:54.000Z</published>
<updated>2017-04-06T15:42:59.000Z</updated>
<content type="html"><p>在软件开发过程中,常常遇到这样的情况,实现某一个功能可以有多种算法,我们根据实际情况,选择不同的算法来完成这个功能。常规方法是通过if/else条件判断而选择算法。也可以通过策略模式来实现。</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><p>策略模式定义了一系列的算法,并每个算法封装起来,而且使他们还可以互相替换。策略模式让算法独立于使用它的客户而独立变化。</p>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><p>- 结构清晰明了、使用简单直观</p>
<ul>
<li>耦合度相对而言较低,扩展方便</li>
<li>操作封装也更为彻底,数据更为安全</li>
</ul>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><ul>
<li>策略增加后,子类也会增加</li>
</ul>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><ul>
<li>针对同一类型问题的多种处理方式,仅仅是具体行为有差别时</li>
<li>需要安全地封装多种同一类型的操作时</li>
<li>出现同一抽象类有多个子类,而又需要使用条件判断语句来选择具体子类时。</li>
</ul>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><ul>
<li>动画中的时间插值器</li>
</ul>
<hr>
<ul>
<li>对加、减、乘每个算各自封装成一个类,首先定义其共同的接口</li>
</ul>
<figure class="highlight plain"><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">interface ICalculator&#123;</span><br><span class="line"> </span><br><span class="line"> public int calculator(int a, int b);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>分别定义加、减、乘算法类</li>
</ul>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">class Plus implements ICalculator &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public int calculator(int a, int b) &#123;</span><br><span class="line"> return a + b;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class Minus implements ICalculator &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public int calculator(int a, int b) &#123;</span><br><span class="line"> return a - b;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class Multiply implements ICalculator &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public int calculator(int a, int b) &#123;</span><br><span class="line"> return a * b;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>定义上下文环境类,用于封装各个算法类操作</li>
</ul>
<figure class="highlight plain"><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">class Context&#123;</span><br><span class="line"> </span><br><span class="line"> private ICalculator iCalculator;</span><br><span class="line"> </span><br><span class="line"> public Context(ICalculator iCalculator)&#123;</span><br><span class="line"> this.iCalculator = iCalculator;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> public int calculator(int a, int b)&#123;</span><br><span class="line"> return iCalculator.calculator(a, b);</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>场景类</li>
</ul>
<figure class="highlight plain"><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">public class StrategyTest &#123;</span><br><span class="line"></span><br><span class="line"> public static void main(String[] args) &#123;</span><br><span class="line"> Context context = new Context(new Plus());</span><br><span class="line"> context.calculator(2, 3);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</content>
<summary type="html">
<p>在软件开发过程中,常常遇到这样的情况,实现某一个功能可以有多种算法,我们根据实际情况,选择不同的算法来完成这个功能。常规方法是通过if/else条件判断而选择算法。也可以通过策略模式来实现。</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="策略模式" scheme="http://czhzero.com/tags/%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>设计模式学习笔记-模版方法模式</title>
<link href="http://czhzero.com/2017/03/30/design-pattern-model/"/>
<id>http://czhzero.com/2017/03/30/design-pattern-model/</id>
<published>2017-03-30T15:37:26.000Z</published>
<updated>2017-04-06T14:00:23.000Z</updated>
<content type="html"><p>在面向对象开发过程中,通常会遇到这样一类问题。我们知道一个算法所需的关键步骤,并确定这些步骤的执行顺序,但是,某些步骤的具体实现是未知的,或者说某些步骤的具体实现是会随着环境的变化而改变。这时候就需要用到模版方法模式。</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><p>定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,即可重定义该算法的某些特定步骤。</p>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><ul>
<li>封装不变部分,扩展可变部分</li>
<li>提取公共部分代码,便于维护</li>
</ul>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><ul>
<li>模版方法会带来代码阅读的难度,会让用户觉得难以理解</li>
</ul>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><ul>
<li>多个子类有公有的方法,并且逻辑基本相同时。</li>
<li>重要、复杂的算法可以把核心算法设计为模版方法,周边细节功能则由子类实现</li>
<li>重构时,模版方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。</li>
</ul>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><ul>
<li>AsyncTask</li>
<li>Activity的生命周期函数onCreate()等方法均是模版方法的运用</li>
</ul>
<hr>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">public static abstract class CarModel &#123;</span><br><span class="line"> </span><br><span class="line"> //发动</span><br><span class="line"> protected abstract void start();</span><br><span class="line"> </span><br><span class="line"> //鸣笛</span><br><span class="line"> protected abstract void alarm();</span><br><span class="line"></span><br><span class="line"> //引擎轰鸣</span><br><span class="line"> protected abstract void engineBoom();</span><br><span class="line"> </span><br><span class="line"> //停止</span><br><span class="line"> protected abstract void stop();</span><br><span class="line"> </span><br><span class="line"> //模版方法,增加final关键字,不允许被复写</span><br><span class="line"> final public void run() &#123;</span><br><span class="line"> start();</span><br><span class="line"> engineBoom();</span><br><span class="line"> if(isAlarm()) &#123;</span><br><span class="line"> alarm();</span><br><span class="line"> &#125;</span><br><span class="line"> stop();</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> //钩子函数</span><br><span class="line"> protected boolean isAlarm() &#123;</span><br><span class="line"> return true;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">public static class AudiCar extends CarModel &#123;</span><br><span class="line"> </span><br><span class="line"> private boolean flag;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected void start() &#123;</span><br><span class="line"> System.out.println(&quot;奥迪启动&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected void alarm() &#123;</span><br><span class="line"> System.out.println(&quot;奥迪鸣笛&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected void engineBoom() &#123;</span><br><span class="line"> System.out.println(&quot;奥迪车引擎轰轰作响&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected void stop() &#123;</span><br><span class="line"> System.out.println(&quot;奥迪停车&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected boolean isAlarm() &#123;</span><br><span class="line"> return flag;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> public void setAlarmFlag(boolean flag) &#123;</span><br><span class="line"> this.flag = flag;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line">public static void main(String[] args) &#123;</span><br><span class="line"> AudiCar car = new AudiCar();</span><br><span class="line"> car.setAlarmFlag(false);</span><br><span class="line"> car.run();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</content>
<summary type="html">
<p>在面向对象开发过程中,通常会遇到这样一类问题。我们知道一个算法所需的关键步骤,并确定这些步骤的执行顺序,但是,某些步骤的具体实现是未知的,或者说某些步骤的具体实现是会随着环境的变化而改变。这时候就需要用到模版方法模式。</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="模版方法模式" scheme="http://czhzero.com/tags/%E6%A8%A1%E7%89%88%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>设计模式学习笔记-代理模式</title>
<link href="http://czhzero.com/2017/03/29/design-pattern-proxy/"/>
<id>http://czhzero.com/2017/03/29/design-pattern-proxy/</id>
<published>2017-03-29T14:43:34.000Z</published>
<updated>2017-03-30T15:18:57.000Z</updated>
<content type="html"><p>代理模式(Proxy Pattern)也称为委托模式,是一种结构型设计模式。</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><blockquote>
<p>为其他对象提供一种代理以控制对这个对象的访问。</p>
</blockquote>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><ul>
<li>职责清晰,真实的角色只要做自己份内的事情,后期通过代理完成一件事务。</li>
<li>高扩展性,代理类可以在不修改原来的真实类的情况下,改变逻辑。</li>
</ul>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><p>除了增加了一个类之外,没有什么缺点。</p>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><p>当无法或者不想直接访问某个对象或者访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象要实现相同的接口。</p>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><p>- ActivityManagerProxy代理类,其具体代理的是ActivityManagerNative的子类ActivityManagerService。</p>
<hr>
<figure class="highlight plain"><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><br><span class="line"> * 诉讼流程</span><br><span class="line"> */</span><br><span class="line">public interface ILawsuit &#123;</span><br><span class="line"> void submit();</span><br><span class="line"></span><br><span class="line"> void burden();</span><br><span class="line"></span><br><span class="line"> void defend();</span><br><span class="line"></span><br><span class="line"> void finish();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 诉讼人</span><br><span class="line"> */</span><br><span class="line">public static class XiaoMing implements ILawsuit &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void submit() &#123;</span><br><span class="line"> System.out.println(&quot;老板拖欠工资,申请仲裁&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void burden() &#123;</span><br><span class="line"> System.out.println(&quot;合同书和银行流水在此&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void defend() &#123;</span><br><span class="line"> System.out.println(&quot;铁证如山,不必多说&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void finish() &#123;</span><br><span class="line"> System.out.println(&quot;诉讼成功,回家等通知&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 律师</span><br><span class="line"> */</span><br><span class="line">public static class Lawyer implements ILawsuit &#123;</span><br><span class="line"></span><br><span class="line"> private ILawsuit mLawsuit;</span><br><span class="line"></span><br><span class="line"> public Lawyer(ILawsuit lawsuit) &#123;</span><br><span class="line"> mLawsuit = lawsuit;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void submit() &#123;</span><br><span class="line"> System.out.println(&quot;律师开始替 &quot; + mLawsuit.getClass().getSimpleName() + &quot;提交诉讼&quot;);</span><br><span class="line"> mLawsuit.submit();</span><br><span class="line"> System.out.println(&quot;律师提交诉讼完毕&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void burden() &#123;</span><br><span class="line"> System.out.println(&quot;律师开始替 &quot; + mLawsuit.getClass().getSimpleName() + &quot;举证&quot;);</span><br><span class="line"> mLawsuit.burden();</span><br><span class="line"> System.out.println(&quot;律师举证完成&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void defend() &#123;</span><br><span class="line"> System.out.println(&quot;律师开始替 &quot; + mLawsuit.getClass().getSimpleName() + &quot;辩护&quot;);</span><br><span class="line"> mLawsuit.defend();</span><br><span class="line"> System.out.println(&quot;律师辩护完成&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void finish() &#123;</span><br><span class="line"> System.out.println(&quot;律师申请&quot; + mLawsuit.getClass().getSimpleName() + &quot;回执&quot;);</span><br><span class="line"> mLawsuit.finish();</span><br><span class="line"> System.out.println(&quot;律师等待回执&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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">public static void main(String args[]) &#123;</span><br><span class="line"></span><br><span class="line"> XiaoMing user = new XiaoMing();</span><br><span class="line"> Lawyer lawyer = new Lawyer(user);</span><br><span class="line"> lawyer.submit();</span><br><span class="line"> lawyer.burden();</span><br><span class="line"> lawyer.defend();</span><br><span class="line"> lawyer.finish();</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="代理的分类"><a href="#代理的分类" class="headerlink" title="代理的分类"></a>代理的分类</h2><p>从代码到角度,可以分为静态代理和动态代理,静态代理就如上面例子所示,动态代理则是通过Java的InvocationHandler实现。代码如下</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public static class DynamicProxy implements InvocationHandler &#123;</span><br><span class="line"></span><br><span class="line"> private Object object;</span><br><span class="line"></span><br><span class="line"> public DynamicProxy(Object obj) &#123;</span><br><span class="line"> this.object = obj;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public Object invoke(Object proxy, Method method, Object[] args) throws Throwable &#123;</span><br><span class="line"> System.out.println(&quot;律师开始&quot; + method.getName());</span><br><span class="line"> Object result = method.invoke(object, args);</span><br><span class="line"> System.out.println(&quot;律师结束&quot; + method.getName());</span><br><span class="line"> return result;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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">public static void main(String args[]) &#123;</span><br><span class="line"></span><br><span class="line"> XiaoMing user = new XiaoMing();</span><br><span class="line"></span><br><span class="line"> DynamicProxy dynamicProxy = new DynamicProxy(user);</span><br><span class="line"> ClassLoader loader = user.getClass().getClassLoader();</span><br><span class="line"> ILawsuit dynamicLawyer = (ILawsuit) Proxy.newProxyInstance(loader, new Class[]&#123;ILawsuit.class&#125;, dynamicProxy);</span><br><span class="line"> dynamicLawyer.submit();</span><br><span class="line"> dynamicLawyer.burden();</span><br><span class="line"> dynamicLawyer.defend();</span><br><span class="line"> dynamicLawyer.finish();</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在适用范围上,又可以将代理分为以下几种,</p>
<h3 id="普通代理"><a href="#普通代理" class="headerlink" title="普通代理"></a>普通代理</h3><p>客户端只能访问代理角色,而不能访问真实角色。</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public static class Person &#123;</span><br><span class="line"></span><br><span class="line"> public String mUserName;</span><br><span class="line"></span><br><span class="line"> public Person(String userName) &#123;</span><br><span class="line"> mUserName = userName;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void submit() &#123;</span><br><span class="line"> System.out.println(&quot;dosomething&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">public static class Proxy &#123;</span><br><span class="line"></span><br><span class="line"> private Person mPerson;</span><br><span class="line"></span><br><span class="line"> public Proxy(String userName) &#123;</span><br><span class="line"> mPerson = new Person(userName);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void submit() &#123;</span><br><span class="line"> mPerson.submit();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line">public static void main(String args[]) &#123;</span><br><span class="line"></span><br><span class="line"> Proxy proxy = new Proxy(&quot;xiaoming&quot;);</span><br><span class="line"> proxy.submit();</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="强制代理"><a href="#强制代理" class="headerlink" title="强制代理"></a>强制代理</h3><p>强制代理的概念是指,要从真实角色找到代理角色,不允许直接访问真实角色,高层模块只要调用getProxy就可以访问真实角色的所有方法。代理管理由真实角色自己管理。</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public interface IGamePlayer &#123;</span><br><span class="line"> void login();</span><br><span class="line"></span><br><span class="line"> void upgrade();</span><br><span class="line"></span><br><span class="line"> IGamePlayer getProxy();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static class GamePlayerProxy implements IGamePlayer &#123;</span><br><span class="line"></span><br><span class="line"> public GamePlayer mPlayer;</span><br><span class="line"></span><br><span class="line"> public GamePlayerProxy(GamePlayer player) &#123;</span><br><span class="line"> mPlayer = player;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void login() &#123;</span><br><span class="line"> mPlayer.login();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void upgrade() &#123;</span><br><span class="line"> mPlayer.upgrade();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public IGamePlayer getProxy() &#123;</span><br><span class="line"> return this;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">public static class GamePlayer implements IGamePlayer &#123;</span><br><span class="line"></span><br><span class="line"> public GamePlayerProxy mProxy;</span><br><span class="line"> public String mName;</span><br><span class="line"></span><br><span class="line"> public GamePlayer(String name) &#123;</span><br><span class="line"> mName = name;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void login() &#123;</span><br><span class="line"> if (isMyProxy()) &#123;</span><br><span class="line"> System.out.println(&quot;登录游戏&quot;);</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> System.out.println(&quot;请使用官方指定代理&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void upgrade() &#123;</span><br><span class="line"> if (isMyProxy()) &#123;</span><br><span class="line"> System.out.println(&quot;打怪升级&quot;);</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> System.out.println(&quot;请使用官方指定代理&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public IGamePlayer getProxy() &#123;</span><br><span class="line"> mProxy = new GamePlayerProxy(this);</span><br><span class="line"> return mProxy;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> private boolean isMyProxy() &#123;</span><br><span class="line"> if (mProxy == null) &#123;</span><br><span class="line"> return false;</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> return true;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static void main(String args[]) &#123;</span><br><span class="line"> GamePlayer player = new GamePlayer(&quot;zhangsan&quot;);</span><br><span class="line"></span><br><span class="line"> player.login(); //被禁用</span><br><span class="line"> player.upgrade(); //被禁用</span><br><span class="line"></span><br><span class="line"> GamePlayerProxy proxy = new GamePlayerProxy(player);</span><br><span class="line"> proxy.login(); //被禁用</span><br><span class="line"> proxy.upgrade(); //被禁用</span><br><span class="line"></span><br><span class="line"> player.getProxy().login(); //指定代理</span><br><span class="line"> player.getProxy().upgrade(); //指定代理</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="虚拟代理"><a href="#虚拟代理" class="headerlink" title="虚拟代理"></a>虚拟代理</h3><p>使用一个代理对象表示一个十分耗资源掉对象,并在真正需要时才创建。</p>
<figure class="highlight plain"><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">public class Proxy implements Subject &#123;</span><br><span class="line"></span><br><span class="line"> private Subject subject;</span><br><span class="line"> </span><br><span class="line"> public void request() &#123;</span><br><span class="line"> if(subject == null) &#123;</span><br><span class="line"> subject = new RealSubject();</span><br><span class="line"> &#125;</span><br><span class="line"> subject.request();</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="个性代理"><a href="#个性代理" class="headerlink" title="个性代理"></a>个性代理</h3><p>一个代理可以实现多个接口,实现多个任务。代理的主要目的就是在目标对象方法的基础上增强,这种增强的本质就是对目标对象的方法进行拦截和过滤。</p>
<h3 id="远程代理"><a href="#远程代理" class="headerlink" title="远程代理"></a>远程代理</h3><p>为某个对象在不同的内存地址空间提供局部代理,使系统可以将Server部分的实现隐藏,以便Client可以不必考虑Server的存在。</p>
<h3 id="保护代理"><a href="#保护代理" class="headerlink" title="保护代理"></a>保护代理</h3><p>使用代理控制对原始对象的访问。该类型的代理常被用于原始对象有不同访问权限的情况。</p>
<h3 id="智能引用"><a href="#智能引用" class="headerlink" title="智能引用"></a>智能引用</h3><p>在访问原始对象时执行一些自己的附加操作并对指向原始对象的引用计数。</p>
</content>
<summary type="html">
<p>代理模式(Proxy Pattern)也称为委托模式,是一种结构型设计模式。</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="代理模式" scheme="http://czhzero.com/tags/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>一招破解Mac系统登录密码</title>
<link href="http://czhzero.com/2017/03/17/reset-mac-password/"/>
<id>http://czhzero.com/2017/03/17/reset-mac-password/</id>
<published>2017-03-17T02:07:57.000Z</published>
<updated>2017-03-18T08:43:24.000Z</updated>
<content type="html"><p>Mac系统忘记密码不用担心,几行命令帮你搞定密码,让你重新登录进入系统。</p>
<a id="more"></a>
<p>1: 开机,启动时候按command+s<br>2: 进入Single User Mode, root用户下的命令行界面</p>
<p>3: 在命令行界面,依次输入如下命令:</p>
<figure class="highlight plain"><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">fsck -y</span><br><span class="line"></span><br><span class="line">mount -uaw /</span><br><span class="line"></span><br><span class="line">rm /var/db/.AppleSetupDone</span><br><span class="line"></span><br><span class="line">reboot</span><br></pre></td></tr></table></figure>
<p>开机后是全新的欢迎界面,就是第一次使用时候设置的状态。不需要担心。重新进去管理员,里面会有原来的账号,切换到原来的账号,一切都还在。<br>如果是老用户,不需要输入原来密码就可以输入新的密码更改,前提是把小锁给点下,权限去除。</p>
</content>
<summary type="html">
<p>Mac系统忘记密码不用担心,几行命令帮你搞定密码,让你重新登录进入系统。</p>
</summary>
<category term="Mac" scheme="http://czhzero.com/categories/Mac/"/>
<category term="忘记密码" scheme="http://czhzero.com/tags/%E5%BF%98%E8%AE%B0%E5%AF%86%E7%A0%81/"/>
</entry>
<entry>
<title>设计模式学习笔记-抽象工厂模式</title>
<link href="http://czhzero.com/2017/03/12/design-pattern-abstract-factory/"/>
<id>http://czhzero.com/2017/03/12/design-pattern-abstract-factory/</id>
<published>2017-03-12T08:59:52.000Z</published>
<updated>2017-03-14T13:46:31.000Z</updated>
<content type="html"><p>抽象工厂模式也是创建型的设计模式。抽象工厂模式起源于以前对操作系统的图形化解决方案,如不同操作系统的按钮和文本控件,其实现不同。</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><blockquote>
<p>为创建一组相关或者是相互依赖的对象提供一个接口,而不需要指定他们的具体类。</p>
</blockquote>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><p>- 封装性,分离接口与实现,客户端只是面向接口编程,不需要具体实现是谁。</p>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><ul>
<li>类文件爆炸性增加</li>
<li>不太容易扩展新的产品类,因为增加一个产品类就要修改抽象工厂,娜美所有具体的工厂类均会被修改。</li>
</ul>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><p>一个对象族有相同约束时可以使用抽象工厂模式,如Android、iOS、WindowPhone下的短信软件和拨号软件。</p>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><ul>
<li>Activity和Service可以看作一个具体的工厂实习类</li>
<li>MediaPlayerFactory</li>
</ul>
<hr>
<p>产品类:</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public interface IEngine &#123;</span><br><span class="line"> void engine();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class ImportEngine implements IEngine &#123;</span><br><span class="line"> @Override</span><br><span class="line"> public void engine() &#123;</span><br><span class="line"> System.out.println(&quot;进口发动机&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class DomesticEngine implements IEngine &#123;</span><br><span class="line"> @Override</span><br><span class="line"> public void engine() &#123;</span><br><span class="line"> System.out.println(&quot;国产发动机&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public interface ITire &#123;</span><br><span class="line"></span><br><span class="line"> void tire();</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class NormalTire implements ITire&#123;</span><br><span class="line"> @Override</span><br><span class="line"> public void tire() &#123;</span><br><span class="line"> System.out.println(&quot;普通轮胎&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class SUVTire implements ITire&#123;</span><br><span class="line"> @Override</span><br><span class="line"> public void tire() &#123;</span><br><span class="line"> System.out.println(&quot;SUV轮胎&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>工厂类:</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public abstract class CarFactory &#123;</span><br><span class="line"></span><br><span class="line"> //生产轮胎</span><br><span class="line"> public abstract ITire createTire();</span><br><span class="line"></span><br><span class="line"> //生产发动机</span><br><span class="line"> public abstract IEngine createEngine();</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class BMWFactory extends CarFactory &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public ITire createTire() &#123;</span><br><span class="line"> return new SUVTire();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public IEngine createEngine() &#123;</span><br><span class="line"> return new ImportEngine();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class AudiFactory extends CarFactory &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public ITire createTire() &#123;</span><br><span class="line"> return new NormalTire();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public IEngine createEngine() &#123;</span><br><span class="line"> return new DomesticEngine();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>场景类:</p>
<figure class="highlight plain"><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><br><span class="line">public static void main() &#123;</span><br><span class="line"> CarFactory audiFactory = new AudiFactory();</span><br><span class="line"> audiFactory.createEngine().engine();</span><br><span class="line"> audiFactory.createTire().tire();</span><br><span class="line"></span><br><span class="line"> CarFactory bmwFactory = new BMWFactory();</span><br><span class="line"> bmwFactory.createEngine().engine();</span><br><span class="line"> bmwFactory.createTire().tire();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>工厂方法模式:</p>
<ul>
<li>一个抽象产品类,可以派生出多个具体产品类。 </li>
<li>一个抽象工厂类,可以派生出多个具体工厂类。 </li>
<li>每个具体工厂类只能创建一个具体产品类的实例。 </li>
</ul>
<p> <br>抽象工厂模式:</p>
<ul>
<li>多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 </li>
<li>一个抽象工厂类,可以派生出多个具体工厂类。 </li>
<li>每个具体工厂类可以创建多个具体产品类的实例。 </li>
</ul>
<p>区别:</p>
<ul>
<li>工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。</li>
<li>工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。</li>
</ul>
</content>
<summary type="html">
<p>抽象工厂模式也是创建型的设计模式。抽象工厂模式起源于以前对操作系统的图形化解决方案,如不同操作系统的按钮和文本控件,其实现不同。</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="设计模式" scheme="http://czhzero.com/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>设计模式学习笔记-工厂模式</title>
<link href="http://czhzero.com/2017/03/12/design-pattern-factory/"/>
<id>http://czhzero.com/2017/03/12/design-pattern-factory/</id>
<published>2017-03-12T08:07:32.000Z</published>
<updated>2017-03-12T09:38:29.000Z</updated>
<content type="html"><p>工厂方法模式,是创建型设计模式之一,是一种结构简单的模式。应用广泛,例如Activity的onCreate方法。</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><blockquote>
<p>定义一个用于创建对象的接口,让子类决定实例化哪个类。</p>
</blockquote>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><ul>
<li>良好的封装性,结构清晰</li>
<li>扩展性好,增加产品类十分方便</li>
<li>屏蔽产品类,高层只关心产品抽象类</li>
</ul>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><p>在任何需要生成复杂对象的地方,都可以使用工厂模式。复杂对象适合工厂模式,简单对象就不需要了。</p>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><ul>
<li>BitmapFactory</li>
<li>Activity的onCreate方法</li>
</ul>
<hr>
<p>通常工厂模式有三种实现方式。</p>
<h2 id="反射工厂模式"><a href="#反射工厂模式" class="headerlink" title="反射工厂模式"></a>反射工厂模式</h2><p>产品类</p>
<figure class="highlight plain"><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">public abstract class Product &#123;</span><br><span class="line"> public abstract void method();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class ConcreatProductA extends Product &#123;</span><br><span class="line"> @Override</span><br><span class="line"> public void method() &#123;</span><br><span class="line"> System.out.println(&quot;i am ProductA&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public class ConcreatProductB extends Product &#123;</span><br><span class="line"> @Override</span><br><span class="line"> public void method() &#123;</span><br><span class="line"> System.out.println(&quot;i am ProductB&quot;);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">public abstract class FactoryType1 &#123;</span><br><span class="line"> public abstract &lt;T extends Product&gt; T createProduct(Class&lt;T&gt; c);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">public class ConcreateFactoryType1 extends FactoryType1 &#123;</span><br><span class="line"> @Override</span><br><span class="line"> public &lt;T extends Product&gt; T createProduct(Class&lt;T&gt; c) &#123;</span><br><span class="line"></span><br><span class="line"> Product p = null;</span><br><span class="line"></span><br><span class="line"> try &#123;</span><br><span class="line"> p = (Product) Class.forName(c.getName()).newInstance();</span><br><span class="line"> &#125; catch (IllegalAccessException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125; catch (InstantiationException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125; catch (ClassNotFoundException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> return (T) p;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static void main(String args[]) &#123;</span><br><span class="line"></span><br><span class="line"> //反射方式实现工厂模式</span><br><span class="line"> FactoryType1 factory = new ConcreateFactoryType1();</span><br><span class="line"> Product A1 = factory.createProduct(ConcreatProductA.class);</span><br><span class="line"> Product B1 = factory.createProduct(ConcreatProductB.class);</span><br><span class="line"> A1.method();</span><br><span class="line"> B1.method();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="多工厂模式"><a href="#多工厂模式" class="headerlink" title="多工厂模式"></a>多工厂模式</h2><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public abstract class FactoryType2 &#123;</span><br><span class="line"> public abstract Product createProduct();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//工厂A</span><br><span class="line">public class ConcreateFactoryType2A extends FactoryType2 &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public Product createProduct() &#123;</span><br><span class="line"> return new ConcreatProductA();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//工厂B</span><br><span class="line">public class ConcreateFactoryType2B extends FactoryType2 &#123;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public Product createProduct() &#123;</span><br><span class="line"> return new ConcreatProductB();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static void main(String args[]) &#123;</span><br><span class="line"></span><br><span class="line"> //多工厂方法模式</span><br><span class="line"> FactoryType2 factoryType2A = new ConcreateFactoryType2A();</span><br><span class="line"> Product A2 = factoryType2A.createProduct();</span><br><span class="line"> FactoryType2 factoryType2B = new ConcreateFactoryType2B();</span><br><span class="line"> Product B2 = factoryType2B.createProduct();</span><br><span class="line"> A2.method();</span><br><span class="line"> B2.method();</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="简单工厂模式-静态工厂模式"><a href="#简单工厂模式-静态工厂模式" class="headerlink" title="简单工厂模式(静态工厂模式)"></a>简单工厂模式(静态工厂模式)</h2><figure class="highlight plain"><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">public class FactoryType3 &#123;</span><br><span class="line"> public static ConcreatProductA createProductA() &#123;</span><br><span class="line"> return new ConcreatProductA();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static void main(String args[]) &#123;</span><br><span class="line"></span><br><span class="line">//简单工厂模式或者静态工厂模式&#123;</span><br><span class="line">Product A3 = FactoryType3.createProductA();</span><br><span class="line">A3.method();</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</content>
<summary type="html">
<p>工厂方法模式,是创建型设计模式之一,是一种结构简单的模式。应用广泛,例如Activity的onCreate方法。</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="设计模式" scheme="http://czhzero.com/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>设计模式学习笔记-原型模式</title>
<link href="http://czhzero.com/2017/03/12/design-pattern-prototype/"/>
<id>http://czhzero.com/2017/03/12/design-pattern-prototype/</id>
<published>2017-03-12T07:03:47.000Z</published>
<updated>2017-03-12T08:02:21.000Z</updated>
<content type="html"><p>原型模式是一个创建型的模式。原型二字表明了该模式应该有一个样板实例,用户从这个样板对象中复制出一个内部属性一致的对象。这个过程也就是我们俗称的“克隆,本质就是对象拷贝。</p>
<p>原型模式中的拷贝分为”浅拷贝”和”深拷贝”:<br>浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.<br>深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><blockquote>
<p>用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。</p>
</blockquote>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><ul>
<li>原型模式是在内存中二进制流的拷贝,要比直接new一个对象的性能好很多,特别是要在一个循环体内产生大量对象时,原型模式可以更好地体现其优点。</li>
</ul>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><ul>
<li>直接在内存中的拷贝,构造函数不会知晓,在实际开发当中应该注意这个问题。</li>
</ul>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><ul>
<li>类的初始化需要消化非常多大资源,这些资源包括数据、硬件资源等,通过原型拷贝避免这些消耗。</li>
<li>通过new产生一个对象需要非常繁琐的数据准备或者访问权限,这时可以使用原型模式。</li>
<li>一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即是保护性拷贝。</li>
</ul>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><ul>
<li>ArrayList的clone方法</li>
<li>Intent的clone方法</li>
</ul>
<hr>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">import java.util.ArrayList;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Created by chenzhaohua on 17/3/12.</span><br><span class="line"> */</span><br><span class="line">public class ProtoTypeExample &#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> private static class ShallowWordDocument implements Cloneable &#123;</span><br><span class="line"></span><br><span class="line"> public String title;</span><br><span class="line"> public ArrayList&lt;String&gt; imageList;</span><br><span class="line"></span><br><span class="line"> public ShallowWordDocument() &#123;</span><br><span class="line"> System.out.println(&quot;ShallowWordDocument 执行构造函数 &quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected Object clone() &#123;</span><br><span class="line"> try &#123;</span><br><span class="line"> ShallowWordDocument document = (ShallowWordDocument) super.clone();</span><br><span class="line"> document.title = this.title;</span><br><span class="line"> document.imageList = this.imageList;</span><br><span class="line"> return document;</span><br><span class="line"> &#125; catch (Exception e) &#123;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> return null;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void printDocument() &#123;</span><br><span class="line"></span><br><span class="line"> System.out.println(&quot;------------- printDocument start -----------&quot;);</span><br><span class="line"> System.out.println(&quot;标题 :&quot; + title);</span><br><span class="line"></span><br><span class="line"> for (String str : imageList) &#123;</span><br><span class="line"> System.out.println(&quot;图片 :&quot; + str);</span><br><span class="line"> &#125;</span><br><span class="line"> System.out.println(&quot;------------- printDocument end -----------&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> private static class DeepWordDocument implements Cloneable &#123;</span><br><span class="line"></span><br><span class="line"> public String title;</span><br><span class="line"> public ArrayList&lt;String&gt; imageList;</span><br><span class="line"></span><br><span class="line"> public DeepWordDocument() &#123;</span><br><span class="line"> System.out.println(&quot;DeepWordDocument 执行构造函数 &quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected Object clone() &#123;</span><br><span class="line"> try &#123;</span><br><span class="line"> DeepWordDocument document = (DeepWordDocument) super.clone();</span><br><span class="line"> document.title = this.title;</span><br><span class="line"> document.imageList = (ArrayList&lt;String&gt;) this.imageList.clone();</span><br><span class="line"> return document;</span><br><span class="line"> &#125; catch (Exception e) &#123;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> return null;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void printDocument() &#123;</span><br><span class="line"></span><br><span class="line"> System.out.println(&quot;------------- printDocument start -----------&quot;);</span><br><span class="line"> System.out.println(&quot;标题 :&quot; + title);</span><br><span class="line"></span><br><span class="line"> for (String str : imageList) &#123;</span><br><span class="line"> System.out.println(&quot;图片 :&quot; + str);</span><br><span class="line"> &#125;</span><br><span class="line"> System.out.println(&quot;------------- printDocument end -----------&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> public static void main(String args[]) &#123;</span><br><span class="line"></span><br><span class="line"> ShallowWordDocument orginDoc = new ShallowWordDocument();</span><br><span class="line"> orginDoc.title = &quot;原始文档&quot;;</span><br><span class="line"> orginDoc.imageList = new ArrayList&lt;&gt;();</span><br><span class="line"> orginDoc.imageList.add(&quot;图片1&quot;);</span><br><span class="line"> orginDoc.imageList.add(&quot;图片2&quot;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> ShallowWordDocument copyDoc = (ShallowWordDocument) orginDoc.clone();;</span><br><span class="line"> copyDoc.title = &quot;拷贝文档&quot;;</span><br><span class="line"> copyDoc.imageList.add(&quot;图片3&quot;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> //浅拷贝, 只拷贝title和imageList的地址</span><br><span class="line"> orginDoc.printDocument();</span><br><span class="line"> copyDoc.printDocument();</span><br><span class="line"></span><br><span class="line"> DeepWordDocument orginDoc2 = new DeepWordDocument();</span><br><span class="line"> orginDoc2.title = &quot;原始文档&quot;;</span><br><span class="line"> orginDoc2.imageList = new ArrayList&lt;&gt;();</span><br><span class="line"> orginDoc2.imageList.add(&quot;图片1&quot;);</span><br><span class="line"> orginDoc2.imageList.add(&quot;图片2&quot;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> DeepWordDocument copyDoc2 = (DeepWordDocument) orginDoc2.clone();;</span><br><span class="line"> copyDoc2.title = &quot;拷贝文档&quot;;</span><br><span class="line"> copyDoc2.imageList.add(&quot;图片3&quot;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> //深拷贝, 拷贝title和imageList的完整内容</span><br><span class="line"> orginDoc2.printDocument();</span><br><span class="line"> copyDoc2.printDocument();</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">ShallowWordDocument 执行构造函数 </span><br><span class="line">------------- printDocument start -----------</span><br><span class="line">标题 :原始文档</span><br><span class="line">图片 :图片1</span><br><span class="line">图片 :图片2</span><br><span class="line">图片 :图片3</span><br><span class="line">------------- printDocument end -----------</span><br><span class="line">------------- printDocument start -----------</span><br><span class="line">标题 :拷贝文档</span><br><span class="line">图片 :图片1</span><br><span class="line">图片 :图片2</span><br><span class="line">图片 :图片3</span><br><span class="line">------------- printDocument end -----------</span><br><span class="line">DeepWordDocument 执行构造函数 </span><br><span class="line">------------- printDocument start -----------</span><br><span class="line">标题 :原始文档</span><br><span class="line">图片 :图片1</span><br><span class="line">图片 :图片2</span><br><span class="line">------------- printDocument end -----------</span><br><span class="line">------------- printDocument start -----------</span><br><span class="line">标题 :拷贝文档</span><br><span class="line">图片 :图片1</span><br><span class="line">图片 :图片2</span><br><span class="line">图片 :图片3</span><br><span class="line">------------- printDocument end -----------</span><br></pre></td></tr></table></figure>
</content>
<summary type="html">
<p>原型模式是一个创建型的模式。原型二字表明了该模式应该有一个样板实例,用户从这个样板对象中复制出一个内部属性一致的对象。这个过程也就是我们俗称的“克隆,本质就是对象拷贝。</p>
<p>原型模式中的拷贝分为”浅拷贝”和”深拷贝”:<br>浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.<br>深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="设计模式" scheme="http://czhzero.com/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>设计模式学习笔记-建造者模式</title>
<link href="http://czhzero.com/2017/03/12/design-pattern-builder/"/>
<id>http://czhzero.com/2017/03/12/design-pattern-builder/</id>
<published>2017-03-12T02:53:01.000Z</published>
<updated>2017-03-12T03:17:10.000Z</updated>
<content type="html"><p>Builder模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构造细节的情况下,可以更精细的控制对象的构造流程。</p>
<a id="more"></a>
<h2 id="定义"><a href="#定义" class="headerlink" title="定义:"></a>定义:</h2><blockquote>
<p>将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。</p>
</blockquote>
<h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><ul>
<li>良好的封装性,使用建造者模式可以使客户端不必知道产品内部组成的细节。</li>
<li>建造者独立,容易扩展。</li>
</ul>
<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2><ul>
<li>会产生多余的Builder对象以及Director对象,额外消耗内存。</li>
</ul>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><ul>
<li>相同的方法,不同的执行顺序,产生不同的事件结果时。</li>
<li>多个部件或者零件,都可以装配到一个对象中,但是产生的运行结果又不相同时。</li>
<li>产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用,这个时候使用建造者模式非常合适。</li>
<li>当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时。</li>
</ul>
<h2 id="常见实例"><a href="#常见实例" class="headerlink" title="常见实例:"></a>常见实例:</h2><ul>
<li>AlertDialog.Builder</li>
<li>ImageLoader的Builder</li>
</ul>
<hr>
<p>具体实现如下,</p>
<h2 id="方式一"><a href="#方式一" class="headerlink" title="方式一"></a>方式一</h2><ul>
<li>产品类</li>
</ul>
<figure class="highlight plain"><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">class Room &#123;</span><br><span class="line"></span><br><span class="line"> private Window window;</span><br><span class="line"> private Floor floor;</span><br><span class="line"></span><br><span class="line"> public Window getWindow() &#123;</span><br><span class="line"> return window;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void setWindow(Window window) &#123;</span><br><span class="line"> this.window = window;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public Floor getFloor() &#123;</span><br><span class="line"> return floor;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void setFloor(Floor floor) &#123;</span><br><span class="line"> this.floor = floor;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>定义Builder接口(非必需)</li>
</ul>
<figure class="highlight plain"><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">interface Builder &#123;</span><br><span class="line"></span><br><span class="line"> public void makeWindow();</span><br><span class="line"></span><br><span class="line"> public void makeFloor();</span><br><span class="line"></span><br><span class="line"> public Room getRoom();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>实现Builder</li>
</ul>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">class RoomBuilder implements Builder &#123;</span><br><span class="line"></span><br><span class="line"> private Room room = new Room();</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void makeWindow() &#123;</span><br><span class="line"> room.setWindow(new Window());</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void makeFloor() &#123;</span><br><span class="line"> room.setFloor(new Floor());</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public Room getRoom() &#123;</span><br><span class="line"> return room;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>定义Director</li>
</ul>
<figure class="highlight plain"><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">class Designer &#123;</span><br><span class="line"> </span><br><span class="line"> public void command(Builder builder)&#123;</span><br><span class="line"> // 先建造地板</span><br><span class="line"> builder.makeFloor();</span><br><span class="line"> // 再建造窗户</span><br><span class="line"> builder.makeWindow();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>场景类</li>
</ul>
<figure class="highlight plain"><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">public class Client &#123;</span><br><span class="line"></span><br><span class="line"> public static void main(String[] args) &#123;</span><br><span class="line"> // 先找来一个工人</span><br><span class="line"> Builder builder = new RoomBuilder();</span><br><span class="line"> // 再找来一个房屋设计师</span><br><span class="line"> Designer designer = new Designer();</span><br><span class="line"> // 工人按照设计师设计建造</span><br><span class="line"> designer.command(builder);</span><br><span class="line"> // 工人向雇主交房子</span><br><span class="line"> Room newRoom = builder.getRoom();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="方式二链式调用"><a href="#方式二链式调用" class="headerlink" title="方式二链式调用"></a>方式二链式调用</h2><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">public class Client &#123;</span><br><span class="line"></span><br><span class="line"> public static void main(String[] args) &#123;</span><br><span class="line"> User.Builder builder = new User.Builder();</span><br><span class="line"> User user = builder.setName(&quot;corn&quot;).setAge(100).setAddress(&quot;广州&quot;).build();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class User &#123;</span><br><span class="line"></span><br><span class="line"> private String name;</span><br><span class="line"> private int age;</span><br><span class="line"> private String address;</span><br><span class="line"></span><br><span class="line"> public String getName() &#123;</span><br><span class="line"> return name;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public int getAge() &#123;</span><br><span class="line"> return age;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public String getAddress() &#123;</span><br><span class="line"> return address;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public static class Builder &#123;</span><br><span class="line"> private User user = new User();</span><br><span class="line"></span><br><span class="line"> public Builder setName(String name) &#123;</span><br><span class="line"> user.name = name;</span><br><span class="line"> return this;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public Builder setAge(int age) &#123;</span><br><span class="line"> user.age = age;</span><br><span class="line"> return this;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public Builder setAddress(String address) &#123;</span><br><span class="line"> user.address = address;</span><br><span class="line"> return this;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public User build() &#123;</span><br><span class="line"> return user;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</content>
<summary type="html">
<p>Builder模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构造细节的情况下,可以更精细的控制对象的构造流程。</p>
</summary>
<category term="设计模式" scheme="http://czhzero.com/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="设计模式" scheme="http://czhzero.com/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>Android如何重新签名APK</title>
<link href="http://czhzero.com/2017/03/10/how-to-resign-apk/"/>
<id>http://czhzero.com/2017/03/10/how-to-resign-apk/</id>
<published>2017-03-10T03:17:06.000Z</published>
<updated>2017-03-10T13:27:29.000Z</updated>
<content type="html"><p>如何使用jarsigner进行apk的重新签名</p>
<a id="more"></a>
<h2 id="Step1-删除apk包中旧的签名文件"><a href="#Step1-删除apk包中旧的签名文件" class="headerlink" title="Step1.删除apk包中旧的签名文件"></a>Step1.删除apk包中旧的签名文件</h2><p>将apk重命名为zip文件,解压后,将其中META-INF文件夹删除,再改回.apk格式。</p>
<h2 id="Step2-进入到java安装目录,进入bin文件夹"><a href="#Step2-进入到java安装目录,进入bin文件夹" class="headerlink" title="Step2.进入到java安装目录,进入bin文件夹"></a>Step2.进入到java安装目录,进入bin文件夹</h2><h2 id="Step3-命令行生成keystore"><a href="#Step3-命令行生成keystore" class="headerlink" title="Step3.命令行生成keystore"></a>Step3.命令行生成keystore</h2><p>keytool -genkey -alias nt.android -keyalg RSA -validity 20000 -keystorent.keystore<br>(-validity 20000代表有效期天数),命令完成后,bin目录中会生成nt.keystore</p>
<h2 id="Step4-找到jarsigner文件-执行如下命令"><a href="#Step4-找到jarsigner文件-执行如下命令" class="headerlink" title="Step4.找到jarsigner文件,执行如下命令"></a>Step4.找到jarsigner文件,执行如下命令</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jarsigner -verbose -keystore /Users/chenzhaohua/Downloads/sign/nt.keystore -storepass ntandroid -signedjar /Users/chenzhaohua/Downloads/sign/windthunder_signed.apk -digestalg SHA1 -sigalg MD5withRSA /Users/chenzhaohua/Downloads/sign/windthunder_unsigned.apk nt.android</span><br></pre></td></tr></table></figure>
<p>其中,</p>
<ul>
<li><code>/Users/chenzhaohua/Downloads/sign/nt.keystore</code>为签名证书文件。</li>
<li><code>ntandroid</code>为证书密码</li>
<li><code>/Users/chenzhaohua/Downloads/sign/windthunder_signed.apk</code> 为签名后的apk文件名</li>
<li><code>/Users/chenzhaohua/Downloads/sign/windthunder_unsigned.apk</code> 为待签名的apk<br>nt.android 为Key的别名</li>
</ul>
</content>
<summary type="html">
<p>如何使用jarsigner进行apk的重新签名</p>
</summary>
</entry>
<entry>
<title>Android设备获取扫码枪扫描内容</title>
<link href="http://czhzero.com/2017/03/10/scangon-get/"/>
<id>http://czhzero.com/2017/03/10/scangon-get/</id>
<published>2017-03-10T03:15:03.000Z</published>
<updated>2017-03-10T13:27:29.000Z</updated>
<content type="html"><p>条形码扫码枪现在随处可见,可以很迅速地扫描出条形码内容,比什么手机相机扫码快了不是一点两点。<br>为了节约成本,扫码枪可以直接通过蓝牙连接android或其他设备。<br>那么android设备如何通过蓝牙获取扫描内容的呢?</p>
<a id="more"></a>
<h3 id="1-蓝牙配对,连接设备"><a href="#1-蓝牙配对,连接设备" class="headerlink" title="1. 蓝牙配对,连接设备"></a>1. 蓝牙配对,连接设备</h3><p>打开系统设置,找到蓝牙,打开扫码枪,配对扫码枪设备。输入一个固定的配对码,一般扫码枪说明书里都有写。配对完成后,显示设备已连接。就ok。</p>
<h3 id="2-AndroidManifest中配置权限"><a href="#2-AndroidManifest中配置权限" class="headerlink" title="2.AndroidManifest中配置权限"></a>2.AndroidManifest中配置权限</h3><p>android项目中的AndroidManifest.xml文件添加蓝牙权限。</p>
<figure class="highlight plain"><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">&lt;uses-permission android:name=&quot;android.permission.BLUETOOTH&quot; /&gt;</span><br><span class="line">&lt;uses-permission android:name=&quot;android.permission.BLUETOOTH_ADMIN&quot; /&gt;</span><br></pre></td></tr></table></figure>
<h3 id="3-检测扫码枪的连接状态"><a href="#3-检测扫码枪的连接状态" class="headerlink" title="3.检测扫码枪的连接状态"></a>3.检测扫码枪的连接状态</h3><p>通常来说,扫码枪设备也相当于普通外接输入设备类型,外接键盘。</p>
<p>我这款扫码枪设备返回的是如下蓝牙类型。</p>
<blockquote>
<p>BluetoothClass.Device.Major.PERIPHERAL</p>
</blockquote>
<p>一般而言,通过如下这种方式就可以获得到我们扫码枪设备的信息。</p>
<figure class="highlight plain"><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">Set&lt;BluetoothDevice&gt; blueDevices = mBluetoothAdapter.getBondedDevices();</span><br><span class="line"></span><br><span class="line">if (blueDevices == null || blueDevices.size() &lt;= 0) &#123;</span><br><span class="line"> return false;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">for (Iterator&lt;BluetoothDevice&gt; iterator = blueDevices.iterator(); iterator.hasNext(); ) &#123;</span><br><span class="line"> BluetoothDevice bluetoothDevice = iterator.next();</span><br><span class="line"></span><br><span class="line"> if (bluetoothDevice.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.PERIPHERAL) &#123;</span><br><span class="line"> //TODO 获取扫码枪设备信息</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>开发过程中,必然会需要实时判断设备是否正常连接。</p>
<blockquote>
<p>mBluetoothAdapter.getBondedDevices()</p>
</blockquote>
<p>这个方法仅仅只能够判断设备是否已配对绑定。但是绑定不代表连接,所以只能放弃。</p>
<blockquote>
<p>public List<bluetoothdevice> getConnectedDevices (int profile)<br>public int getConnectionState (BluetoothDevice device, int profile)</bluetoothdevice></p>
</blockquote>
<p>接着又尝试了这两个方法,方法是可用,但是必须要求设备sdk&gt;18,即android 4.3版本以上才可用。</p>
<p>后来转头一想,既然扫码枪也是输入设备,我们可以不同蓝牙设备状态检测入手,改为从输入设备检测入手。于是,</p>
<figure class="highlight plain"><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">private void hasScanGun() &#123;</span><br><span class="line"> Configuration cfg = getResources().getConfiguration();</span><br><span class="line"> return cfg.keyboard != Configuration.KEYBOARD_NOKEYS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>搞定。</p>
<h3 id="4-获取扫码枪扫描内容"><a href="#4-获取扫码枪扫描内容" class="headerlink" title="4.获取扫码枪扫描内容"></a>4.获取扫码枪扫描内容</h3><p>扫描枪,既然是一个外接输入设备,那么很自然的,我们就从KeyEvent入手。</p>
<p>事件解析类<br><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 扫码枪事件解析类</span><br><span class="line"> */</span><br><span class="line">public class ScanGunKeyEventHelper &#123;</span><br><span class="line"></span><br><span class="line"> //延迟500ms,判断扫码是否完成。</span><br><span class="line"> private final static long MESSAGE_DELAY = 500;</span><br><span class="line"> //扫码内容</span><br><span class="line"> private StringBuffer mStringBufferResult = new StringBuffer();</span><br><span class="line"> //大小写区分</span><br><span class="line"> private boolean mCaps;</span><br><span class="line"> private OnScanSuccessListener mOnScanSuccessListener;</span><br><span class="line"> private Handler mHandler = new Handler();</span><br><span class="line"></span><br><span class="line"> private final Runnable mScanningFishedRunnable = new Runnable() &#123;</span><br><span class="line"> @Override</span><br><span class="line"> public void run() &#123;</span><br><span class="line"> performScanSuccess();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;;</span><br><span class="line"></span><br><span class="line"> //返回扫描结果</span><br><span class="line"> private void performScanSuccess() &#123;</span><br><span class="line"> String barcode = mStringBufferResult.toString();</span><br><span class="line"> if (mOnScanSuccessListener != null)</span><br><span class="line"> mOnScanSuccessListener.onScanSuccess(barcode);</span><br><span class="line"> mStringBufferResult.setLength(0);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> //key事件处理</span><br><span class="line"> public void analysisKeyEvent(KeyEvent event) &#123;</span><br><span class="line"></span><br><span class="line"> int keyCode = event.getKeyCode();</span><br><span class="line"></span><br><span class="line"> //字母大小写判断</span><br><span class="line"> checkLetterStatus(event);</span><br><span class="line"></span><br><span class="line"> if (event.getAction() == KeyEvent.ACTION_DOWN) &#123;</span><br><span class="line"></span><br><span class="line"> char aChar = getInputCode(event);;</span><br><span class="line"></span><br><span class="line"> if (aChar != 0) &#123;</span><br><span class="line"> mStringBufferResult.append(aChar);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> if (keyCode == KeyEvent.KEYCODE_ENTER) &#123;</span><br><span class="line"> //若为回车键,直接返回</span><br><span class="line"> mHandler.removeCallbacks(mScanningFishedRunnable);</span><br><span class="line"> mHandler.post(mScanningFishedRunnable);</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> //延迟post,若500ms内,有其他事件</span><br><span class="line"> mHandler.removeCallbacks(mScanningFishedRunnable);</span><br><span class="line"> mHandler.postDelayed(mScanningFishedRunnable, MESSAGE_DELAY);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> //检查shift键</span><br><span class="line"> private void checkLetterStatus(KeyEvent event) &#123;</span><br><span class="line"> int keyCode = event.getKeyCode();</span><br><span class="line"> if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT || keyCode == KeyEvent.KEYCODE_SHIFT_LEFT) &#123;</span><br><span class="line"> if (event.getAction() == KeyEvent.ACTION_DOWN) &#123;</span><br><span class="line"> //按着shift键,表示大写</span><br><span class="line"> mCaps = true;</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> //松开shift键,表示小写</span><br><span class="line"> mCaps = false;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> //获取扫描内容</span><br><span class="line"> private char getInputCode(KeyEvent event) &#123;</span><br><span class="line"></span><br><span class="line"> int keyCode = event.getKeyCode();</span><br><span class="line"></span><br><span class="line"> char aChar;</span><br><span class="line"></span><br><span class="line"> if (keyCode &gt;= KeyEvent.KEYCODE_A &amp;&amp; keyCode &lt;= KeyEvent.KEYCODE_Z) &#123;</span><br><span class="line"> //字母</span><br><span class="line"> aChar = (char) ((mCaps ? &apos;A&apos; : &apos;a&apos;) + keyCode - KeyEvent.KEYCODE_A);</span><br><span class="line"> &#125; else if (keyCode &gt;= KeyEvent.KEYCODE_0 &amp;&amp; keyCode &lt;= KeyEvent.KEYCODE_9) &#123;</span><br><span class="line"> //数字</span><br><span class="line"> aChar = (char) (&apos;0&apos; + keyCode - KeyEvent.KEYCODE_0);</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> //其他符号</span><br><span class="line"> switch (keyCode) &#123;</span><br><span class="line"> case KeyEvent.KEYCODE_PERIOD:</span><br><span class="line"> aChar = &apos;.&apos;;</span><br><span class="line"> break;</span><br><span class="line"> case KeyEvent.KEYCODE_MINUS:</span><br><span class="line"> aChar = mCaps ? &apos;_&apos; : &apos;-&apos;;</span><br><span class="line"> break;</span><br><span class="line"> case KeyEvent.KEYCODE_SLASH:</span><br><span class="line"> aChar = &apos;/&apos;;</span><br><span class="line"> break;</span><br><span class="line"> case KeyEvent.KEYCODE_BACKSLASH:</span><br><span class="line"> aChar = mCaps ? &apos;|&apos; : &apos;\\&apos;;</span><br><span class="line"> break;</span><br><span class="line"> default:</span><br><span class="line"> aChar = 0;</span><br><span class="line"> break;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> return aChar;</span><br><span class="line"></span><br><span class="line"> &#125;</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"> public interface OnScanSuccessListener &#123;</span><br><span class="line"> public void onScanSuccess(String barcode);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void setOnBarCodeCatchListener(OnScanSuccessListener onScanSuccessListener) &#123;</span><br><span class="line"> mOnScanSuccessListener = onScanSuccessListener;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public void onDestroy() &#123;</span><br><span class="line"> mHandler.removeCallbacks(mScanningFishedRunnable);</span><br><span class="line"> mOnScanSuccessListener = null;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>Activity中重写dispatchKeyEvent方法,截取Key事件。</p>
<figure class="highlight plain"><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><br><span class="line"> * Activity截获按键事件.发给ScanGunKeyEventHelper</span><br><span class="line"> *</span><br><span class="line"> * @param event</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> @Override</span><br><span class="line"> public boolean dispatchKeyEvent(KeyEvent event) &#123;</span><br><span class="line"></span><br><span class="line"> if (isScanGunEvent(event)) &#123;</span><br><span class="line"> mScanGunKeyEventHelper.analysisKeyEvent(event);</span><br><span class="line"> return true;</span><br><span class="line"> &#125;</span><br><span class="line"> return super.dispatchKeyEvent(event);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 显示扫描内容</span><br><span class="line"> * @param barcode 条形码</span><br><span class="line"> */</span><br><span class="line"> @Override</span><br><span class="line"> public void onScanSuccess(String barcode) &#123;</span><br><span class="line"> //TODO 显示扫描内容</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<p>详细代码参看:<a href="https://github.com/czhzero/scangon" target="_blank" rel="external">https://github.com/czhzero/scangon</a></p>
<p>注意点:</p>
<p>1.部分机型无法判断外接键盘信息,如三星。</p>
<figure class="highlight plain"><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">private void hasScanGun() &#123;</span><br><span class="line"> Configuration cfg = getResources().getConfiguration();</span><br><span class="line"> return cfg.keyboard != Configuration.KEYBOARD_NOKEYS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>三星手机cfg.keyboard返回值等于Configuration.KEYBOARD_NOKEYS。</p>
<p>因此为了更好的兼容,可以采用如下方法,</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 判断是否已经连接扫码枪</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line">protected boolean hasScanGun() &#123;</span><br><span class="line"></span><br><span class="line"> Set&lt;BluetoothDevice&gt; blueDevices = mBluetoothAdapter.getBondedDevices();</span><br><span class="line"></span><br><span class="line"> if (blueDevices == null || blueDevices.size() &lt;= 0) &#123;</span><br><span class="line"> return false;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> for (Iterator&lt;BluetoothDevice&gt; iterator = blueDevices.iterator(); iterator.hasNext(); ) &#123;</span><br><span class="line"> BluetoothDevice bluetoothDevice = iterator.next();</span><br><span class="line"></span><br><span class="line"> if (bluetoothDevice.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.PERIPHERAL) &#123;</span><br><span class="line"> return isInputDeviceUsed(bluetoothDevice.getName());</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> return false;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">private boolean isInputDeviceUsed(String deviceName) &#123;</span><br><span class="line"></span><br><span class="line"> int[] deviceIds = InputDevice.getDeviceIds();</span><br><span class="line"></span><br><span class="line"> for (int id : deviceIds) &#123;</span><br><span class="line"> if (InputDevice.getDevice(id).getName().equals(deviceName)) &#123;</span><br><span class="line"> return true;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> return false;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</content>
<summary type="html">
<p>条形码扫码枪现在随处可见,可以很迅速地扫描出条形码内容,比什么手机相机扫码快了不是一点两点。<br>为了节约成本,扫码枪可以直接通过蓝牙连接android或其他设备。<br>那么android设备如何通过蓝牙获取扫描内容的呢?</p>
</summary>
<category term="Android" scheme="http://czhzero.com/categories/Android/"/>
<category term="扫码枪" scheme="http://czhzero.com/tags/%E6%89%AB%E7%A0%81%E6%9E%AA/"/>
</entry>
<entry>
<title>Android自定义Dialog的Match_parent无效问题解决</title>
<link href="http://czhzero.com/2017/03/10/dialog-matchparent-invalid/"/>
<id>http://czhzero.com/2017/03/10/dialog-matchparent-invalid/</id>
<published>2017-03-10T03:12:53.000Z</published>
<updated>2017-03-10T13:27:29.000Z</updated>
<content type="html"><p>Android 开发过程中,自定义dialog 用得很多,通常都是通过继承Dialog, 再加载自定义的xml来实现。</p>
<a id="more"></a>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">//自定义Dialog</span><br><span class="line">public class OrderFilterDialog extends Dialog &#123;</span><br><span class="line"></span><br><span class="line"> public OrderFilterDialog(Context context) &#123;</span><br><span class="line"> super(context);</span><br><span class="line"> initView(this);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> public OrderFilterDialog(Context context, int themeResId) &#123;</span><br><span class="line"> super(context, themeResId);</span><br><span class="line"> initView(this);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> public void initView(Dialog dialog) &#123;</span><br><span class="line"> dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);</span><br><span class="line"> dialog.setContentView(R.layout.dialog_search_order);</span><br><span class="line"> show();</span><br><span class="line"> dialog.setCancelable(false);</span><br><span class="line"> Window window = dialog.getWindow();</span><br><span class="line"> WindowManager.LayoutParams lp = window.getAttributes();</span><br><span class="line"> lp.width = WindowManager.LayoutParams.MATCH_PARENT;</span><br><span class="line"> lp.height = WindowManager.LayoutParams.WRAP_CONTENT;</span><br><span class="line"> lp.gravity = Gravity.TOP;</span><br><span class="line"> window.setAttributes(lp);</span><br><span class="line"> window.setWindowAnimations(R.style.DialogInOutTopAnimation);</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行后,发现效果如下,</p>
<p><img src="http://img.blog.csdn.net/20160114170927743" alt="这里写图片描述"></p>
<p>我们发现,match_parent属性根本没有生效。查看Dialog源码才发现,默认Dialog是有一个theme属性的,坑。</p>
<p>Dialog部分代码如下,</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line">140 * Creates a dialog window that uses the default dialog theme.</span><br><span class="line">141 * &lt;p&gt;</span><br><span class="line">142 * The supplied &#123;@code context&#125; is used to obtain the window manager and</span><br><span class="line">143 * base theme used to present the dialog.</span><br><span class="line">144 *</span><br><span class="line">145 * @param context the context in which the dialog should run</span><br><span class="line">146 * @see android.R.styleable#Theme_dialogTheme</span><br><span class="line">147 */</span><br><span class="line">148 public Dialog(@NonNull Context context) &#123;</span><br><span class="line">149 this(context, 0, true); //默认传入0</span><br><span class="line">150 &#125;</span><br><span class="line">151</span><br><span class="line">152 /**</span><br><span class="line">153 * Creates a dialog window that uses a custom dialog style.</span><br><span class="line">154 * &lt;p&gt;</span><br><span class="line">155 * The supplied &#123;@code context&#125; is used to obtain the window manager and</span><br><span class="line">156 * base theme used to present the dialog.</span><br><span class="line">157 * &lt;p&gt;</span><br><span class="line">158 * The supplied &#123;@code theme&#125; is applied on top of the context&apos;s theme. See</span><br><span class="line">159 * &lt;a href=&quot;&#123;@docRoot&#125;guide/topics/resources/available-resources.html#stylesandthemes&quot;&gt;</span><br><span class="line">160 * Style and Theme Resources&lt;/a&gt; for more information about defining and</span><br><span class="line">161 * using styles.</span><br><span class="line">162 *</span><br><span class="line">163 * @param context the context in which the dialog should run</span><br><span class="line">164 * @param themeResId a style resource describing the theme to use for the</span><br><span class="line">165 * window, or &#123;@code 0&#125; to use the default dialog theme</span><br><span class="line">166 */</span><br><span class="line">167 public Dialog(@NonNull Context context, @StyleRes int themeResId) &#123;</span><br><span class="line">168 this(context, themeResId, true);</span><br><span class="line">169 &#125;</span><br><span class="line">170</span><br><span class="line">171 Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) &#123;</span><br><span class="line">172 if (createContextThemeWrapper) &#123;</span><br><span class="line">173 if (themeResId == 0) &#123;</span><br><span class="line">174 final TypedValue outValue = new TypedValue();</span><br><span class="line">175 context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true); //若值为0,则默认设置dialogTheme样式</span><br><span class="line">176 themeResId = outValue.resourceId;</span><br><span class="line">177 &#125;</span><br><span class="line">178 mContext = new ContextThemeWrapper(context, themeResId);</span><br><span class="line">179 &#125; else &#123;</span><br><span class="line">180 mContext = context;</span><br><span class="line">181 &#125;</span><br><span class="line">182</span><br><span class="line">183 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);</span><br><span class="line">184</span><br><span class="line">185 final Window w = new PhoneWindow(mContext);</span><br><span class="line">186 mWindow = w;</span><br><span class="line">187 w.setCallback(this);</span><br><span class="line">188 w.setOnWindowDismissedCallback(this);</span><br><span class="line">189 w.setWindowManager(mWindowManager, null, null);</span><br><span class="line">190 w.setGravity(Gravity.CENTER);</span><br><span class="line">191</span><br><span class="line">192 mListenersHandler = new ListenersHandler(this);</span><br><span class="line">193 &#125;</span><br></pre></td></tr></table></figure>
<p>其中</p>
<blockquote>
<p>if (themeResId == 0) {<br> final TypedValue outValue = new TypedValue();<br> context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);<br> themeResId = outValue.resourceId;<br>}</p>
</blockquote>
<p>从上述代码可以看出,若Dialog没有设置默认样式,系统会自动给你适配为R.attr.dialogTheme样式。<br>而查看themes.xml后,发现 dialogTheme样式是自带有Padding值的,所以match_parent自然是无效的。</p>
<p>那么,如何实现match_parent呢</p>
<p>(1) 设置padding值为0。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dialog.getWindow().getDecorView().setPadding(0, 0, 0, 0);</span><br></pre></td></tr></table></figure>
<p>(2) 自定义一个Theme,覆盖原生Theme。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">OrderFilterDialog dialog = new OrderFilterDialog(context, R.style.test);</span><br></pre></td></tr></table></figure>
<p>运行效果如下,</p>
<p><img src="http://img.blog.csdn.net/20160114171122552" alt="这里写图片描述"></p>
</content>
<summary type="html">
<p>Android 开发过程中,自定义dialog 用得很多,通常都是通过继承Dialog, 再加载自定义的xml来实现。</p>
</summary>
<category term="Android" scheme="http://czhzero.com/categories/Android/"/>
<category term="Dialog" scheme="http://czhzero.com/tags/Dialog/"/>
</entry>
<entry>
<title>git submodule 使用命令简介</title>
<link href="http://czhzero.com/2017/03/10/git-submodule-introduce/"/>
<id>http://czhzero.com/2017/03/10/git-submodule-introduce/</id>
<published>2017-03-10T03:10:48.000Z</published>
<updated>2017-03-10T13:27:29.000Z</updated>
<content type="html"><p>抽取项目公共模块,多项目共用,必然会使用到git submodule命令。<br>项目中submodule的管理,无外乎添加,更新,删除等操作。</p>
<a id="more"></a>
<p>###1. submodule 添加</p>
<p>进入到git项目根目录下,输入命令:</p>
<blockquote>
<p>git submodule add [-b master ] [URL to Git repo] [local path]</p>
</blockquote>
<p>其中,[-b master] 为submodule的默认分支,[local path]为submodule的本地路径。</p>
<p>若出现如下提示,则表示submodule添加成功。</p>
<p><img src="http://img.blog.csdn.net/20160121154730707" alt="这里写图片描述"></p>
<p>命令执行完成,会在当前工程根路径下生成一个名为“.gitmodules”的文件,其中记录了子模块的信息,如下:</p>
<figure class="highlight plain"><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">[submodule &quot;libraries/pushserver&quot;]</span><br><span class="line"> path = libraries/pushserver //本地路径</span><br><span class="line"> url = git@*****/android-library-push.git //仓库地址</span><br><span class="line"> branch = master //默认分支</span><br></pre></td></tr></table></figure>
<h3 id="2-submodule-更新"><a href="#2-submodule-更新" class="headerlink" title="2. submodule 更新"></a>2. submodule 更新</h3><p> 若项目中包含.gitmodules, 进入到git项目根目录下,输入命令, .gitmodules中的所有项目都会进行更新:</p>
<blockquote>
<p>git clone 父项目.git<br>git submodule init<br>git submodule update (update时,submodule分支必须已在正确分支上)</p>
</blockquote>
<p>submodule远程分支发生变更后,直接使用git submodule update是不会进行更新操作的。必须依次进入到各个submodule的目录,进行git pull操作,如果submodule数目很多,每次发版本时必须进入所有目录进行git pull,这将是噩梦。不过有个更简单的方法,</p>
<blockquote>
<p>git submodule foreach git checkout master<br>git submodule foreach git pull</p>
</blockquote>
<h3 id="3-submodule-删除"><a href="#3-submodule-删除" class="headerlink" title="3. submodule 删除"></a>3. submodule 删除</h3><p>删除submodule会麻烦些,仅仅删除submodule模块内容,是无法彻底从git中删除掉。还需要到git相关配置文件中删除条目。</p>
<ol>
<li>删除 [项目根目录/.gitmodules] 中对应的条目</li>
<li>删除 [项目根目录/.git/config] 中对应的条目</li>
<li>删除 [项目根目录/.git/modules] 目录下的对应的submodule文件夹</li>
<li>执行 git rm –cached [modulename] 命令</li>
<li>删除 submodule 模块内容</li>
</ol>
</content>
<summary type="html">
<p>抽取项目公共模块,多项目共用,必然会使用到git submodule命令。<br>项目中submodule的管理,无外乎添加,更新,删除等操作。</p>
</summary>
<category term="开发工具" scheme="http://czhzero.com/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
<category term="submodule" scheme="http://czhzero.com/tags/submodule/"/>
</entry>
<entry>
<title>Fragment的setUserVisibleHint详解</title>
<link href="http://czhzero.com/2017/03/10/fragment-setuservisiblehit/"/>
<id>http://czhzero.com/2017/03/10/fragment-setuservisiblehit/</id>
<published>2017-03-10T03:06:12.000Z</published>
<updated>2017-03-10T13:27:29.000Z</updated>
<content type="html"><p>Android应用开发过程中,ViewPager同时加载多个fragment,以实现多tab页面快速切换, 但是fragment初始化时若加载的内容较多,就可能导致整个应用启动速度缓慢,影响用户体验。<br>为了提高用户体验,我们会使用一些懒加载方案,实现加载延迟。这时我们会用到getUserVisibleHint()与setUserVisibleHint()这两个方法。</p>
<a id="more"></a>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line">*</span><br><span class="line">* @param isVisibleToUser true if this fragment&apos;s UI is currently visible to the user (default),</span><br><span class="line">* false if it is not.</span><br><span class="line">*/</span><br><span class="line">public void setUserVisibleHint(boolean isVisibleToUser) &#123;</span><br><span class="line"> if (!mUserVisibleHint &amp;&amp; isVisibleToUser &amp;&amp; mState &lt; STARTED) &#123;</span><br><span class="line"> mFragmentManager.performPendingDeferredStart(this);</span><br><span class="line"> &#125;</span><br><span class="line"> mUserVisibleHint = isVisibleToUser;</span><br><span class="line"> mDeferStart = !isVisibleToUser;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @return The current value of the user-visible hint on this fragment.</span><br><span class="line"> * @see #setUserVisibleHint(boolean)</span><br><span class="line"> */</span><br><span class="line">public boolean getUserVisibleHint() &#123;</span><br><span class="line"> return mUserVisibleHint;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>从上述源码注释我们可以看出,当fragment被用户可见时,setUserVisibleHint()会调用且传入true值,当fragment不被用户可见时,setUserVisibleHint()则得到false值。而在传统的fragment生命周期里也看不到这个函数。</p>
<p><img src="http://img.blog.csdn.net/20160428203327414" alt="这里写图片描述"></p>
<p>那么,问题来了,</p>
<blockquote>
<ol>
<li>fragment是如何知道自己时候用户可见?</li>
<li>setUserVisibleHint() 在上图所示fragment的生命周期的什么位置?</li>
</ol>
</blockquote>
<p>先说结论,</p>
<blockquote>
<ol>
<li>viewpager监听切换tab事件,tab切换一次,执行一次setUserVisibleHint()方法</li>
<li>setUserVisibleHint() 在 上图所示fragment所有生命周期之前,无论viewpager是在activity哪个生命周期里初始化。</li>
<li>activity生命周期 和 fragment生命周期 时序并不是按序来的,也就是说fragment的oncreate方法时序并不一定在activity的oncreate方法之后。</li>
</ol>
</blockquote>
<p>具体原因,我们从应用场景开始一点一点的分析。</p>
<h3 id="Theme-1-我们的应用场景"><a href="#Theme-1-我们的应用场景" class="headerlink" title="Theme 1. 我们的应用场景"></a>Theme 1. 我们的应用场景</h3><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">public class MainActivity extends FragmentActivity &#123;</span><br><span class="line"></span><br><span class="line"> private ViewPager viewPager;</span><br><span class="line"> </span><br><span class="line"> @Override</span><br><span class="line"> protected void onCreate(Bundle savedInstanceState) &#123;</span><br><span class="line"> super.onCreate(savedInstanceState);</span><br><span class="line"></span><br><span class="line"> viewPager = (ViewPager) findViewById(R.id.viewpager);</span><br><span class="line"> vpOrder.setAdapter(new MainFragmentPagerAdapter(getSupportFragmentManager()));</span><br><span class="line"> vpOrder.setOffscreenPageLimit(5);</span><br><span class="line"> vpOrder.setCurrentItem(0);</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="Theme-2-ViewPager-FragmentPagerAdapter"><a href="#Theme-2-ViewPager-FragmentPagerAdapter" class="headerlink" title="Theme 2. ViewPager ,FragmentPagerAdapter"></a>Theme 2. ViewPager ,FragmentPagerAdapter</h3><ul>
<li><code>/frameworks/base/core/java/com/android/internal/widget/ViewPager.java</code></li>
</ul>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">//每次切换ViewPager的Tab时调用的方法</span><br><span class="line">void populate(int newCurrentItem) &#123;</span><br><span class="line"></span><br><span class="line"> mAdapter.startUpdate(this);</span><br><span class="line"></span><br><span class="line"> //......</span><br><span class="line"> addNewItem(mCurItem, curIndex);</span><br><span class="line"> // mCurItem 为当前可见Fragment</span><br><span class="line"> // 调用setUserVisibleHint(true)</span><br><span class="line"> mAdapter.setPrimaryItem(this, mCurItem, curItem != null ? curItem.object : null); </span><br><span class="line"></span><br><span class="line"> mAdapter.finishUpdate(this);</span><br><span class="line"></span><br><span class="line"> //.....</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">ItemInfo addNewItem(int position, int index) &#123;</span><br><span class="line"> ItemInfo ii = new ItemInfo();</span><br><span class="line"> ii.position = position;</span><br><span class="line"> //初始化fragment, 调用setUserVisibleHint(false)</span><br><span class="line"> ii.object = mAdapter.instantiateItem(this, position);</span><br><span class="line"> ii.widthFactor = mAdapter.getPageWidth(position);</span><br><span class="line"> if (index &lt; 0 || index &gt;= mItems.size()) &#123;</span><br><span class="line"> mItems.add(ii);</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> mItems.add(index, ii);</span><br><span class="line"> &#125;</span><br><span class="line"> return ii;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><code>/frameworks/support/v4/java/android/support/v4/app/FragmentPagerAdapter.java</code></li>
</ul>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"> @Override</span><br><span class="line">public Object instantiateItem(ViewGroup container, int position) &#123;</span><br><span class="line"> if (mCurTransaction == null) &#123;</span><br><span class="line"> mCurTransaction = mFragmentManager.beginTransaction();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> final long itemId = getItemId(position);</span><br><span class="line"></span><br><span class="line"> // Do we already have this fragment?</span><br><span class="line"> String name = makeFragmentName(container.getId(), itemId);</span><br><span class="line"> Fragment fragment = mFragmentManager.findFragmentByTag(name);</span><br><span class="line"> if (fragment != null) &#123;</span><br><span class="line"> if (DEBUG) Log.v(TAG, &quot;Attaching item #&quot; + itemId + &quot;: f=&quot; + fragment);</span><br><span class="line"> mCurTransaction.attach(fragment);</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> fragment = getItem(position);</span><br><span class="line"> if (DEBUG) Log.v(TAG, &quot;Adding item #&quot; + itemId + &quot;: f=&quot; + fragment);</span><br><span class="line"> //将fragment添加到FragmentManager里面</span><br><span class="line"> mCurTransaction.add(container.getId(), fragment,</span><br><span class="line"> makeFragmentName(container.getId(), itemId));</span><br><span class="line"> &#125;</span><br><span class="line"> if (fragment != mCurrentPrimaryItem) &#123;</span><br><span class="line"> fragment.setMenuVisibility(false);</span><br><span class="line"> //我们要找的方法在这里</span><br><span class="line"> fragment.setUserVisibleHint(false); </span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> return fragment;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@Override</span><br><span class="line">public void setPrimaryItem(ViewGroup container, int position, Object object) &#123;</span><br><span class="line"> Fragment fragment = (Fragment)object;</span><br><span class="line"> if (fragment != mCurrentPrimaryItem) &#123;</span><br><span class="line"> if (mCurrentPrimaryItem != null) &#123;</span><br><span class="line"> mCurrentPrimaryItem.setMenuVisibility(false);</span><br><span class="line"> mCurrentPrimaryItem.setUserVisibleHint(false);</span><br><span class="line"> &#125;</span><br><span class="line"> if (fragment != null) &#123;</span><br><span class="line"> //我们要找的方法在这里</span><br><span class="line"> fragment.setMenuVisibility(true);</span><br><span class="line"> fragment.setUserVisibleHint(true);</span><br><span class="line"> &#125;</span><br><span class="line"> mCurrentPrimaryItem = fragment;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="Theme-3-Activity-FragmentManager"><a href="#Theme-3-Activity-FragmentManager" class="headerlink" title="Theme 3. Activity , FragmentManager"></a>Theme 3. Activity , FragmentManager</h3><ul>
<li><code>/frameworks/base/core/java/android/app/Activity.java</code></li>
</ul>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">protected void onCreate(@Nullable Bundle savedInstanceState) &#123;</span><br><span class="line"> if (DEBUG_LIFECYCLE) Slog.v(TAG, &quot;onCreate &quot; + this + &quot;: &quot; + savedInstanceState);</span><br><span class="line"> if (mLastNonConfigurationInstances != null) &#123;</span><br><span class="line"> mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);</span><br><span class="line"> &#125;</span><br><span class="line"> if (mActivityInfo.parentActivityName != null) &#123;</span><br><span class="line"> if (mActionBar == null) &#123;</span><br><span class="line"> mEnableDefaultActionBarUp = true;</span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> mActionBar.setDefaultDisplayHomeAsUpEnabled(true);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> if (savedInstanceState != null) &#123;</span><br><span class="line"> Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);</span><br><span class="line"> mFragments.restoreAllState(p, mLastNonConfigurationInstances != null</span><br><span class="line"> ? mLastNonConfigurationInstances.fragments : null);</span><br><span class="line"> &#125;</span><br><span class="line"> //分发fragment的onCreate()事件</span><br><span class="line"> mFragments.dispatchCreate(); </span><br><span class="line"> getApplication().dispatchActivityCreated(this, savedInstanceState);</span><br><span class="line"> if (mVoiceInteractor != null) &#123;</span><br><span class="line"> mVoiceInteractor.attachActivity(this);</span><br><span class="line"> &#125;</span><br><span class="line"> mCalled = true;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><code>/frameworks/support/v4/java/android/support/v4/app/FragmentManager.java</code></li>
</ul>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">//分发onCreate事件函数</span><br><span class="line">public void dispatchCreate() &#123;</span><br><span class="line"> mStateSaved = false;</span><br><span class="line"> moveToState(Fragment.CREATED, false);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//moveToState 重载 1</span><br><span class="line">void moveToState(int newState, boolean always) &#123;</span><br><span class="line"> moveToState(newState, 0, 0, always);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//moveToState 重载 2</span><br><span class="line">void moveToState(int newState, int transit, int transitStyle, boolean always) &#123;</span><br><span class="line"> if (mHost == null &amp;&amp; newState != Fragment.INITIALIZING) &#123;</span><br><span class="line"> throw new IllegalStateException(&quot;No host&quot;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> if (!always &amp;&amp; mCurState == newState) &#123;</span><br><span class="line"> return;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> mCurState = newState;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> //若mActive为null,就算Activtiy里面调用了dispatchOnCreate()也不会执行Fragment</span><br><span class="line"> //的OnAttach和onCreate等方法。</span><br><span class="line"></span><br><span class="line"> //只有mActive非null,即addFragment()执行后,才会真正进入到生命周期。</span><br><span class="line"> //而根据FragmentPagerAdapter可知,只有当viewpager调用setAdapter方法,才会添加fragment到FramentManager。</span><br><span class="line"></span><br><span class="line"> //执行setAdapter的时候,会调用setUserVisibleHint()方法,并且,只有当setAdapter方法执行完之后,才会进入到Fragment到生命周期,因此setUserVisibleHint()方法在所有生命周期之前被调用。</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> if (mActive != null) &#123;</span><br><span class="line"> boolean loadersRunning = false;</span><br><span class="line"> for (int i=0; i&lt;mActive.size(); i++) &#123;</span><br><span class="line"> Fragment f = mActive.get(i);</span><br><span class="line"> if (f != null) &#123;</span><br><span class="line"> moveToState(f, newState, transit, transitStyle, false);</span><br><span class="line"> if (f.mLoaderManager != null) &#123;</span><br><span class="line"> loadersRunning |= f.mLoaderManager.hasRunningLoaders();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> if (!loadersRunning) &#123;</span><br><span class="line"> startPendingDeferredFragments();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> if (mNeedMenuInvalidate &amp;&amp; mHost != null &amp;&amp; mCurState == Fragment.RESUMED) &#123;</span><br><span class="line"> mHost.onSupportInvalidateOptionsMenu();</span><br><span class="line"> mNeedMenuInvalidate = false;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//moveToState 重载 3</span><br><span class="line">void moveToState(Fragment f, int newState, int transit, int transitionStyle,</span><br><span class="line"> </span><br><span class="line"> //...</span><br><span class="line"></span><br><span class="line"> f.onAttach();</span><br><span class="line"></span><br><span class="line"> //...</span><br><span class="line"></span><br><span class="line"> f.performOnCreate();</span><br><span class="line"> </span><br><span class="line"> //其他生命周期</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//添加fragment到FragmentManager</span><br><span class="line">public void addFragment(Fragment fragment, boolean moveToStateNow) &#123;</span><br><span class="line"> if (mAdded == null) &#123;</span><br><span class="line"> mAdded = new ArrayList&lt;Fragment&gt;();</span><br><span class="line"> &#125;</span><br><span class="line"> if (DEBUG) Log.v(TAG, &quot;add: &quot; + fragment);</span><br><span class="line"></span><br><span class="line"> //激活fragment</span><br><span class="line"> makeActive(fragment);</span><br><span class="line"></span><br><span class="line"> if (!fragment.mDetached) &#123;</span><br><span class="line"> if (mAdded.contains(fragment)) &#123;</span><br><span class="line"> throw new IllegalStateException(&quot;Fragment already added: &quot; + fragment);</span><br><span class="line"> &#125;</span><br><span class="line"> mAdded.add(fragment);</span><br><span class="line"> fragment.mAdded = true;</span><br><span class="line"> fragment.mRemoving = false;</span><br><span class="line"> if (fragment.mHasMenu &amp;&amp; fragment.mMenuVisible) &#123;</span><br><span class="line"> mNeedMenuInvalidate = true;</span><br><span class="line"> &#125;</span><br><span class="line"> if (moveToStateNow) &#123;</span><br><span class="line"> moveToState(fragment);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">void makeActive(Fragment f) &#123;</span><br><span class="line"> if (f.mIndex &gt;= 0) &#123;</span><br><span class="line"> return;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> if (mAvailIndices == null || mAvailIndices.size() &lt;= 0) &#123;</span><br><span class="line"> if (mActive == null) &#123;</span><br><span class="line"> //激活Fragment</span><br><span class="line"> mActive = new ArrayList&lt;Fragment&gt;(); </span><br><span class="line"> &#125;</span><br><span class="line"> f.setIndex(mActive.size(), mParent);</span><br><span class="line"> mActive.add(f);</span><br><span class="line"> </span><br><span class="line"> &#125; else &#123;</span><br><span class="line"> f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent);</span><br><span class="line"> mActive.set(f.mIndex, f);</span><br><span class="line"> &#125;</span><br><span class="line"> if (DEBUG) Log.v(TAG, &quot;Allocated fragment index &quot; + f);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></content>
<summary type="html">
<p>Android应用开发过程中,ViewPager同时加载多个fragment,以实现多tab页面快速切换, 但是fragment初始化时若加载的内容较多,就可能导致整个应用启动速度缓慢,影响用户体验。<br>为了提高用户体验,我们会使用一些懒加载方案,实现加载延迟。这时我们会用到getUserVisibleHint()与setUserVisibleHint()这两个方法。</p>
</summary>
<category term="Android" scheme="http://czhzero.com/categories/Android/"/>
<category term="setUserVisibleHint" scheme="http://czhzero.com/tags/setUserVisibleHint/"/>
</entry>
<entry>
<title>为Android Studio 项目手动下载gradle</title>
<link href="http://czhzero.com/2017/03/10/gradle-manual-download/"/>
<id>http://czhzero.com/2017/03/10/gradle-manual-download/</id>
<published>2017-03-10T03:03:21.000Z</published>
<updated>2017-03-10T13:27:29.000Z</updated>
<content type="html"><p>原文: <a href="http://www.cnblogs.com/duanguyuan/p/3997550.html" target="_blank" rel="external">http://www.cnblogs.com/duanguyuan/p/3997550.html</a></p>
<p>在 <a href="http://developer.android.com/samples/index.html" target="_blank" rel="external">http://developer.android.com/samples/index.html</a> 上下载的例子,导入Android Studio的时候,第一件事就是下载项目对应版本的gradle。gradle是一个主要面向Java应用的build工具,类似于大家熟知的eclipse下的Ant,但比Ant高级。</p>
<a id="more"></a>
<p>Andriod Studio下载gradle的过程很慢,在运行./studio.sh的终端中可以看见进度:</p>
<p>把终端中的网址复制下来,在浏览器中打开,可见有38MB多。Windows下可用迅雷下载,Linux下推荐Firefox + DownThemAll插件。</p>
<p>Android Studio下载的各个版本gradle放在~/.gradle/wrapper/dists/目录下(Windows下目录为C:\Users\用户名.gradle\wrapper\dists)。如下显示了Andriod Studio已经下载了gradle部分文件的大小,可见已经下载了20MB左右:</p>
<figure class="highlight plain"><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><br><span class="line">wy@wy-Inspiron-7420:~/.gradle/wrapper/dists/gradle-1.10-bin/6oa4rff9viiqskhgd6uns5v1f8$ ll</span><br><span class="line">total 21432</span><br><span class="line">drwxrwxr-x 2 wy wy 4096 Sep 28 00:27 ./</span><br><span class="line">drwxrwxr-x 3 wy wy 4096 Sep 28 00:20 ../</span><br><span class="line">-rw-rw-r-- 1 wy wy 0 Sep 28 00:20 gradle-1.10-bin.zip.lck</span><br><span class="line">-rw-rw-r-- 1 wy wy 21931207 Sep 28 00:33 gradle-1.10-bin.zip.part</span><br></pre></td></tr></table></figure>
<p>在Android Studio中取消下载(不过貌似有个bug,取消不了,那就直接在运行studio.sh的终端中按Ctrl + C 退出Android Studio)。</p>
<p>将gradle-1.10-bin.zip.part移除,把自己下载的gradle-1.10-bin.zip复制到这个目录。然后再次启动Andriod Studio,会自动读取gradle并解压,然后用解压得到的gradle工具build你import进来的sample project。</p>
<p>再次查看gradle的下载目录,如下:</p>
<figure class="highlight plain"><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">wy@wy-Inspiron-7420:~/.gradle/wrapper/dists/gradle-1.10-bin/6oa4rff9viiqskhgd6uns5v1f8$ ll</span><br><span class="line">total 39472</span><br><span class="line">drwxrwxr-x 3 wy wy 4096 Sep 28 00:38 ./</span><br><span class="line">drwxrwxr-x 3 wy wy 4096 Sep 28 00:20 ../</span><br><span class="line">drwxrwxr-x 6 wy wy 4096 Sep 28 00:38 gradle-1.10/</span><br><span class="line">-rw-r----- 1 wy wy 40404574 Sep 28 00:37 gradle-1.10-bin.zip</span><br><span class="line">-rw-rw-r-- 1 wy wy 0 Sep 28 00:20 gradle-1.10-bin.zip.lck</span><br><span class="line">-rw-rw-r-- 1 wy wy 0 Sep 28 00:38 gradle-1.10-bin.zip.ok</span><br></pre></td></tr></table></figure>
<p>lck和ok文件大小为0,没有实际内容,起一个标志的作用。ok表示此版本的gradle已经收拾妥当(在下载完毕之前是没有这个ok文件的)。lck文件不知什么作用。(猜测是lock的意思,标记这个版本的gradle是否有project在使用。如果没有被使用,当总的gradle文件达到缓存上限后,此版本的gradle会被删除)</p>
</content>
<summary type="html">
<p>原文: <a href="http://www.cnblogs.com/duanguyuan/p/3997550.html">http://www.cnblogs.com/duanguyuan/p/3997550.html</a></p>
<p>在 <a href="http://developer.android.com/samples/index.html">http://developer.android.com/samples/index.html</a> 上下载的例子,导入Android Studio的时候,第一件事就是下载项目对应版本的gradle。gradle是一个主要面向Java应用的build工具,类似于大家熟知的eclipse下的Ant,但比Ant高级。</p>
</summary>
<category term="Android" scheme="http://czhzero.com/categories/Android/"/>
<category term="gradle" scheme="http://czhzero.com/tags/gradle/"/>
</entry>
</feed>