-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
1524 lines (760 loc) · 66.4 KB
/
index.html
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
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html class="theme-next pisces use-motion" lang="zh-Hans">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
<link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />
<meta name="keywords" content="Hexo, NexT" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0" />
<meta name="description" content="In me the tiger sniffes the rose">
<meta property="og:type" content="website">
<meta property="og:title" content="Jerry Chan">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="Jerry Chan">
<meta property="og:description" content="In me the tiger sniffes the rose">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Jerry Chan">
<meta name="twitter:description" content="In me the tiger sniffes the rose">
<script type="text/javascript" id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Pisces',
sidebar: {"position":"left","display":"post"},
fancybox: true,
motion: true,
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
</script>
<link rel="canonical" href="http://yoursite.com/"/>
<title> Jerry Chan </title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container one-collumn sidebar-position-left
page-home
">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">Jerry Chan</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle">Android Developer</p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br />
首页
</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories" rel="section">
<i class="menu-item-icon fa fa-fw fa-th"></i> <br />
分类
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
归档
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
标签
</a>
</li>
<li class="menu-item menu-item-about">
<a href="/about" rel="section">
<i class="menu-item-icon fa fa-fw fa-user"></i> <br />
关于
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/04/25/LayoutInflater源码研究学习/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Jerry Chan">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.jpg">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Jerry Chan">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="Jerry Chan" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2017/04/25/LayoutInflater源码研究学习/" itemprop="url">
LayoutInflater源码研究学习
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2017-04-25T14:59:49+08:00">
2017-04-25
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<a href="/2017/04/25/LayoutInflater源码研究学习/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2017/04/25/LayoutInflater源码研究学习/" itemprop="commentCount"></span>
</a>
</span>
<span id="/2017/04/25/LayoutInflater源码研究学习/" class="leancloud_visitors" data-flag-title="LayoutInflater源码研究学习">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数 </span>
<span class="leancloud-visitors-count"></span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>在日常生活开发中,我们一般通过LayoutInflater来将xml文件加载到Activity当中,无论是在<code>setContentView(resId)</code>,或者在代码中直接通过<code>LayoutInflater.from(…)</code>等方法进行,还是换肤框架的基本思路,都是经由LayoutInflater来处理的,因此LayoutInflater在解析视图方面是扮演着一个非常重要的角色,那么既然那么重要,那就有必要学习一下了。</p>
<p>我们一般使用如下方式进行获取LayoutInflater:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> LayoutInflater <span class="title">from</span><span class="params">(Context context)</span> </span>{</div><div class="line"> LayoutInflater LayoutInflater =</div><div class="line"> (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);</div><div class="line"> <span class="keyword">if</span> (LayoutInflater == <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> AssertionError(<span class="string">"LayoutInflater not found."</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> LayoutInflater;</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>可以看到,其实在源码内部还是使用<code>context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)</code>来进行的,那这里其实有个问题,一个Activity是对应一个LayoutInflater还是所有的Activity都是同一个LayoutInflater呢?一开始想到的是既然都是拿来解析xml文件布局,那么用一个实例肯定是最好的,不用分配多余的存储空间,但是其实一个Activity是对应一个LayoutInflater的,答案我们通过源码可以得到。</p>
<p>既然是通过getSystemService(…)获取到的,那么我们就需要找到这个方法的实现类,在Activity当中我们获取到的LayoutInflater来源于ContextThemeWrapper,而Activity是继承自ContextThemeWrapper,LayoutInflater的实现类为PhoneLayoutInflater:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//ContextThemeWrapper.java</span></div><div class="line"><span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> Object <span class="title">getSystemService</span><span class="params">(String name)</span> </span>{</div><div class="line"> <span class="keyword">if</span> (LAYOUT_INFLATER_SERVICE.equals(name)) {</div><div class="line"> <span class="keyword">if</span> (mInflater == <span class="keyword">null</span>) {</div><div class="line"> mInflater = LayoutInflater.from(mBase).cloneInContext(<span class="keyword">this</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> mInflater;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> mBase.getSystemService(name);</div><div class="line"> }</div><div class="line"><span class="comment">//PhoneLayoutInflater</span></div><div class="line"><span class="function"><span class="keyword">public</span> LayoutInflater <span class="title">cloneInContext</span><span class="params">(Context newContext)</span> </span>{</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> PhoneLayoutInflater(<span class="keyword">this</span>, newContext);</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>最终设置的给LayoutInflater的Context是当前Activity的Context,那么其实也就意味着一个Activity是对应一个LayoutInflater,因为每个Activity的Context是不一样的所以对应生成的LayoutInflater也不一样。诶?!突然发现这个问题好弱智- -,推断一下就出来了,算了,就当理解一下获取到LayoutInflater的步骤吧。</p>
<p>上面扯了那么多,只是为了解决再看源码当时突然想到的问题:一个Activity是对应一个LayoutInflater还是所有的Activity都是同一个LayoutInflater呢。接下来就正式的开始深入的研究LayoutInflater的代码。当我们需要使用LayoutInflater去解析一个xml文件的时候,我们都会调用LayoutInflater.inflate(…)方法来进行解析最终获取到一个View,无论调用何种inflate(…)方法(前提是我们传入的是resource),都会最后调用到底下的方法当中:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> View <span class="title">inflate</span><span class="params">(@LayoutRes <span class="keyword">int</span> resource, @Nullable ViewGroup root, <span class="keyword">boolean</span> attachToRoot)</span> </span>{</div><div class="line"> <span class="keyword">final</span> Resources res = getContext().getResources();</div><div class="line"> <span class="comment">//获取一个XmlResourceParser对象</span></div><div class="line"> <span class="keyword">final</span> XmlResourceParser parser = res.getLayout(resource);</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> <span class="keyword">return</span> inflate(parser, root, attachToRoot);</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> parser.close();</div><div class="line"> }</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>XmlResourceParser的作用在于保存解析xml后的数据,然后就进入<code>inflate(parser, root, attachToRoot)</code>:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> View <span class="title">inflate</span><span class="params">(XmlPullParser parser, @Nullable ViewGroup root, <span class="keyword">boolean</span> attachToRoot)</span> </span>{</div><div class="line"> <span class="keyword">synchronized</span> (mConstructorArgs) {</div><div class="line"> ...</div><div class="line"> <span class="keyword">final</span> Context inflaterContext = mContext;</div><div class="line"> <span class="comment">//获取AttributeSet</span></div><div class="line"> <span class="keyword">final</span> AttributeSet attrs = Xml.asAttributeSet(parser);</div><div class="line"> Context lastContext = (Context) mConstructorArgs[<span class="number">0</span>];</div><div class="line"> mConstructorArgs[<span class="number">0</span>] = inflaterContext;</div><div class="line"> View result = root;</div><div class="line"></div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> <span class="comment">// Look for the root node.</span></div><div class="line"> <span class="keyword">int</span> type;</div><div class="line"> <span class="keyword">while</span> ((type = parser.next()) != XmlPullParser.START_TAG &&</div><div class="line"> type != XmlPullParser.END_DOCUMENT) {</div><div class="line"> <span class="comment">// Empty</span></div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="keyword">if</span> (type != XmlPullParser.START_TAG) {</div><div class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> InflateException(parser.getPositionDescription()</div><div class="line"> + <span class="string">": No start tag found!"</span>);</div><div class="line"> }</div><div class="line"> <span class="comment">//找到第一个节点</span></div><div class="line"> <span class="keyword">final</span> String name = parser.getName();</div><div class="line"> <span class="comment">//是否是Merge标签</span></div><div class="line"> <span class="keyword">if</span> (TAG_MERGE.equals(name)) {</div><div class="line"> <span class="keyword">if</span> (root == <span class="keyword">null</span> || !attachToRoot) {</div><div class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> InflateException(<span class="string">"<merge /> can be used only with a valid "</span></div><div class="line"> + <span class="string">"ViewGroup root and attachToRoot=true"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> rInflate(parser, root, inflaterContext, attrs, <span class="keyword">false</span>);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// Temp is the root view that was found in the xml</span></div><div class="line"> <span class="keyword">final</span> View temp = createViewFromTag(root, name, inflaterContext, attrs);</div><div class="line"> ViewGroup.LayoutParams params = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">if</span> (root != <span class="keyword">null</span>) {</div><div class="line"> <span class="comment">// Create layout params that match root, if supplied</span></div><div class="line"> params = root.generateLayoutParams(attrs);</div><div class="line"> <span class="keyword">if</span> (!attachToRoot) {</div><div class="line"> <span class="comment">// Set the layout params for temp if we are not</span></div><div class="line"> <span class="comment">// attaching. (If we are, we use addView, below)</span></div><div class="line"> temp.setLayoutParams(params);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="comment">// Inflate all children under temp against its context.</span></div><div class="line"> rInflateChildren(parser, temp, attrs, <span class="keyword">true</span>);</div><div class="line"> <span class="comment">// We are supposed to attach all the views we found (int temp)</span></div><div class="line"> <span class="comment">// to root. Do that now.</span></div><div class="line"> <span class="keyword">if</span> (root != <span class="keyword">null</span> && attachToRoot) {</div><div class="line"> root.addView(temp, params);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Decide whether to return the root that was passed in or the</span></div><div class="line"> <span class="comment">// top view found in xml.</span></div><div class="line"> <span class="keyword">if</span> (root == <span class="keyword">null</span> || !attachToRoot) {</div><div class="line"> result = temp;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> } <span class="keyword">catch</span> (XmlPullParserException e) {</div><div class="line"> <span class="keyword">final</span> InflateException ie = <span class="keyword">new</span> InflateException(e.getMessage(), e);</div><div class="line"> ie.setStackTrace(EMPTY_STACK_TRACE);</div><div class="line"> <span class="keyword">throw</span> ie;</div><div class="line"> } <span class="keyword">catch</span> (Exception e) {</div><div class="line"> <span class="keyword">final</span> InflateException ie = <span class="keyword">new</span> InflateException(parser.getPositionDescription()</div><div class="line"> + <span class="string">": "</span> + e.getMessage(), e);</div><div class="line"> ie.setStackTrace(EMPTY_STACK_TRACE);</div><div class="line"> <span class="keyword">throw</span> ie;</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> <span class="comment">// Don't retain static reference on context.</span></div><div class="line"> mConstructorArgs[<span class="number">0</span>] = lastContext;</div><div class="line"> mConstructorArgs[<span class="number">1</span>] = <span class="keyword">null</span>;</div><div class="line"></div><div class="line"> Trace.traceEnd(Trace.TRACE_TAG_VIEW);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"> }</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>该方法代码有点长,但也是我们今天要讲解的重点,主要逻辑就是递归解析布局文件并创建View树结构,然后返回该View树结构。该段代码中先通过Xml类的静态方法生成一个AttributeSet实例对象attrs,AttributeSet对象我们应该很熟悉,里边主要包含了相关属性的键值对。接下来就是通过parser解析器循环遍历查询布局文件的根节点,若没有查询到就会抛出异常。遍历完成之后获取到根节点名字存储在变量name中,然后进行判断。如果当前根节点标签名字是mege标签就走if()语句,否则进入else语句。由于我们在布局文件中没有使用merge标签,所以直接进入else语句中。进入else语句后,先定义值为null的临时变量temp,接着开始做判断,如果当前根节点标签名字为BlinkLayout就进入if语句,因为我们没有使用这个标签就进入else语句,在else语句中通过调用createViewFromTag()来创建一个View并赋值给temp。接下来又是条件判断,因为传递进来的root为空,所以跳过if(root != null)的判断语句,接着执行rInflate()方法(该方法是来循环渲染包含的所有的子视图的)。执行完成后返回temp的值。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div></pre></td><td class="code"><pre><div class="line"><span class="function">View <span class="title">createViewFromTag</span><span class="params">(View parent, String name, Context context, AttributeSet attrs,<span class="keyword">boolean</span> ignoreThemeAttr)</span> </span>{</div><div class="line"> <span class="keyword">if</span> (name.equals(<span class="string">"view"</span>)) {</div><div class="line"> name = attrs.getAttributeValue(<span class="keyword">null</span>, <span class="string">"class"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Apply a theme wrapper, if allowed and one is specified.</span></div><div class="line"> <span class="keyword">if</span> (!ignoreThemeAttr) {</div><div class="line"> <span class="keyword">final</span> TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);</div><div class="line"> <span class="keyword">final</span> <span class="keyword">int</span> themeResId = ta.getResourceId(<span class="number">0</span>, <span class="number">0</span>);</div><div class="line"> <span class="keyword">if</span> (themeResId != <span class="number">0</span>) {</div><div class="line"> context = <span class="keyword">new</span> ContextThemeWrapper(context, themeResId);</div><div class="line"> }</div><div class="line"> ta.recycle();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (name.equals(TAG_1995)) {</div><div class="line"> <span class="comment">// Let's party like it's 1995!</span></div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> BlinkLayout(context, attrs);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> View view;</div><div class="line"> <span class="keyword">if</span> (mFactory2 != <span class="keyword">null</span>) {</div><div class="line"> view = mFactory2.onCreateView(parent, name, context, attrs);</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (mFactory != <span class="keyword">null</span>) {</div><div class="line"> view = mFactory.onCreateView(name, context, attrs);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> view = <span class="keyword">null</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (view == <span class="keyword">null</span> && mPrivateFactory != <span class="keyword">null</span>) {</div><div class="line"> view = mPrivateFactory.onCreateView(parent, name, context, attrs);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (view == <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">final</span> Object lastContext = mConstructorArgs[<span class="number">0</span>];</div><div class="line"> mConstructorArgs[<span class="number">0</span>] = context;</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> <span class="keyword">if</span> (-<span class="number">1</span> == name.indexOf(<span class="string">'.'</span>)) {</div><div class="line"> view = onCreateView(parent, name, attrs);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> view = createView(name, <span class="keyword">null</span>, attrs);</div><div class="line"> }</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> mConstructorArgs[<span class="number">0</span>] = lastContext;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> view;</div><div class="line"> } <span class="keyword">catch</span> (InflateException e) {</div><div class="line"> <span class="keyword">throw</span> e;</div><div class="line"></div><div class="line"> } <span class="keyword">catch</span> (ClassNotFoundException e) {</div><div class="line"> <span class="keyword">final</span> InflateException ie = <span class="keyword">new</span> InflateException(attrs.getPositionDescription()</div><div class="line"> + <span class="string">": Error inflating class "</span> + name, e);</div><div class="line"> ie.setStackTrace(EMPTY_STACK_TRACE);</div><div class="line"> <span class="keyword">throw</span> ie;</div><div class="line"></div><div class="line"> } <span class="keyword">catch</span> (Exception e) {</div><div class="line"> <span class="keyword">final</span> InflateException ie = <span class="keyword">new</span> InflateException(attrs.getPositionDescription()</div><div class="line"> + <span class="string">": Error inflating class "</span> + name, e);</div><div class="line"> ie.setStackTrace(EMPTY_STACK_TRACE);</div><div class="line"> <span class="keyword">throw</span> ie;</div><div class="line"> }</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>方法createViewFromTag()主要流程就是通过标签名name来创建相应View实例对象并返回。在该方法中首先根据Factory实例对象来创建View,如果创建成功就直接返回,否则执行系统默认创建View流程。这里需要强调一点,LayoutInflater内部定义了一个boolean类型的mFactorySet开关,其值默认值为false,当我们调用过setFactory()或者是setFactory2()后mFactorySet为true,若我们再次调用这俩方法时会抛出异常,也就是说每一个LayoutInflater实例对象只能赋值一次Factory,若再想赋成其他值只能通过反射先把mFactorySet的值置为false防止抛异常。系统默认创建View流程是先通过判断标签名称中有没有包含”.”,如果没有包含就把标签名添加前缀”android.view.”,最终调用LayoutInflater的createView()方法,注意该方法是public并且是final类型的,是系统默认的创建View的方式,创建完成之后返回该view。</p>
<p>到这里我们已经清楚了LayoutInflater根据xml布局文件来渲染View视图的主要流程:先是通过布局文件的资源ID创建一个XmlResourceParser解析器对象parser,再是利用parser递归解析xml布局文件,然后根据解析出的标签名来创建相关View,最终返回层级视图View。如果LayoutInflater中设置了Factory,那么在创建每一个View时都会调用该Factory的onCreateView()方法,这个方法就是我们的入口点,如果想在每一个View创建之前做点处理,只需要在Factory的onCreateView()方法中做相关逻辑操作</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/03/30/Fragment深入学习/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Jerry Chan">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.jpg">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Jerry Chan">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="Jerry Chan" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2017/03/30/Fragment深入学习/" itemprop="url">
Fragment深入学习
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2017-03-30T10:57:26+08:00">
2017-03-30
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<a href="/2017/03/30/Fragment深入学习/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2017/03/30/Fragment深入学习/" itemprop="commentCount"></span>
</a>
</span>
<span id="/2017/03/30/Fragment深入学习/" class="leancloud_visitors" data-flag-title="Fragment深入学习">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数 </span>
<span class="leancloud-visitors-count"></span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>公司项目是基于插件进行开发的,在开发初期,由于时间成本以及插件框架不完善,所以为了避坑(主要来源于插件),项目中大量利用了<code>Fragment</code>作为核心的展示视图,因此趁这段比较清闲的时间整理学习一下<code>Fragment</code>。</p>
<p>注:本文基于4.4源码</p>
<!--noindex-->
<div class="post-more-link text-center">
<a class="btn" href="/2017/03/30/Fragment深入学习/#more" rel="contents">
阅读全文 »
</a>
</div>
<!--/noindex-->
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/03/13/android-View的探索-三View-Window-Activity之间的关系/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Jerry Chan">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.jpg">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Jerry Chan">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="Jerry Chan" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2017/03/13/android-View的探索-三View-Window-Activity之间的关系/" itemprop="url">
android-View的探索-三View,Window,Activity之间的关系
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2017-03-13T10:35:38+08:00">
2017-03-13
</time>
</span>
<span class="post-category" >
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/Android源码研究/" itemprop="url" rel="index">
<span itemprop="name">Android源码研究</span>
</a>
</span>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<a href="/2017/03/13/android-View的探索-三View-Window-Activity之间的关系/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2017/03/13/android-View的探索-三View-Window-Activity之间的关系/" itemprop="commentCount"></span>
</a>
</span>
<span id="/2017/03/13/android-View的探索-三View-Window-Activity之间的关系/" class="leancloud_visitors" data-flag-title="android-View的探索-三View,Window,Activity之间的关系">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数 </span>
<span class="leancloud-visitors-count"></span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>日常开发中我们接触到的主要是View以及Activity,并且在此基础上开发,但是其实View跟Window是离不开的,所以本文旨在理清View,Window以及Activity之间的关系。</p>
<hr>
<!--noindex-->
<div class="post-more-link text-center">
<a class="btn" href="/2017/03/13/android-View的探索-三View-Window-Activity之间的关系/#more" rel="contents">
阅读全文 »
</a>
</div>
<!--/noindex-->
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/03/04/深入理解计算机系统第一章/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Jerry Chan">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.jpg">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Jerry Chan">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="Jerry Chan" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2017/03/04/深入理解计算机系统第一章/" itemprop="url">
深入理解计算机系统第一章
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2017-03-04T22:14:13+08:00">
2017-03-04
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<a href="/2017/03/04/深入理解计算机系统第一章/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2017/03/04/深入理解计算机系统第一章/" itemprop="commentCount"></span>
</a>
</span>
<span id="/2017/03/04/深入理解计算机系统第一章/" class="leancloud_visitors" data-flag-title="深入理解计算机系统第一章">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数 </span>
<span class="leancloud-visitors-count"></span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3>hello文件的周期过程</h3>
<p>hello.c</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</div><div class="line"> <span class="built_in">printf</span>(<span class="string">"hello ,world\n"</span>);</div><div class="line">}</div></pre></td></tr></table></figure>
<p>hello文件的生命周期:创建->系统上运行->输出消息->终止</p>
<p>hello文件的生命周期由一个源文件开始,我们利用编辑器创建并且保存,这就是一个以.c结尾的文本文件,源程序实际上是由值0到1组成的位(bit)序列,8个位被组织成一组,称为字节。</p>
<p>hello.c以字节序列的方式存储在文件当中,每个字节都由一个整数值进行对应,即ASCII码来对应。</p>
<p>hello程序的生命周期从一个C语言开始,为了在系统上运行hello.c,每条C语言语句都会被转化成低级机器语言,然后这些指令会按照一种<strong>可执行目标程序</strong>的格式打包,以<strong>二进制磁盘文件</strong>的形式存放起来。<strong>目标程序也称为可执行文件</strong></p>
<!--noindex-->
<div class="post-more-link text-center">
<a class="btn" href="/2017/03/04/深入理解计算机系统第一章/#more" rel="contents">
阅读全文 »
</a>
</div>
<!--/noindex-->
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/02/22/疑难杂症汇总/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Jerry Chan">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.jpg">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Jerry Chan">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="Jerry Chan" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2017/02/22/疑难杂症汇总/" itemprop="url">
疑难杂症汇总
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2017-02-22T15:10:22+08:00">
2017-02-22
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<a href="/2017/02/22/疑难杂症汇总/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2017/02/22/疑难杂症汇总/" itemprop="commentCount"></span>
</a>
</span>
<span id="/2017/02/22/疑难杂症汇总/" class="leancloud_visitors" data-flag-title="疑难杂症汇总">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数 </span>
<span class="leancloud-visitors-count"></span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>1.公司需求需要在RecycerView滑动的时候每一个item在可见度>=50%时上报数据,一般的RecyclerView.OnScrollListener中我们做处理,如果自己去计算item的展示可见度那是很麻烦的,解决思路如下:</p>
<p>重点代码:<strong>view.getGlobalVisibleRect()</strong>,getGlobalVisibleRect方法的作用是获取视图在屏幕坐标中的可视区域,那只要在代码OnScrollListener中加入判断即可:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">private</span> RecyclerView.OnScrollListener mOnScrollListener = <span class="keyword">new</span> RecyclerView.OnScrollListener() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onScrolled</span><span class="params">(RecyclerView recyclerView, <span class="keyword">int</span> dx, <span class="keyword">int</span> dy)</span> </span>{</div><div class="line"> <span class="keyword">super</span>.onScrolled(recyclerView, dx, dy);</div><div class="line"> <span class="keyword">int</span> lastVisbile = mLayoutManager.findLastVisibleItemPosition();</div><div class="line"> mLayoutManager.findFirstVisibleItemPosition();</div><div class="line"> <span class="comment">// 只有广告才需要50%上报</span></div><div class="line"> <span class="keyword">if</span> (mAdapter.getItemViewType(lastVisbile) != STYLE_CONTENT_BIG_IMG)</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> View view = mLayoutManager.findViewByPosition(lastVisbile);</div><div class="line"> Rect rect = <span class="keyword">new</span> Rect();</div><div class="line"> view.getGlobalVisibleRect(rect);</div><div class="line"> <span class="keyword">int</span> currentHeight = view.getHeight();</div><div class="line"> <span class="keyword">if</span> (rect.bottom - rect.top >= currentHeight / <span class="number">2</span>) {</div><div class="line"> Log.e(<span class="string">"zzzzzz"</span>, <span class="string">"曝光了---->"</span> + lastVisbile);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> };</div></pre></td></tr></table></figure>
<p>实现的代码如上所示。</p>
<!--noindex-->
<div class="post-more-link text-center">
<a class="btn" href="/2017/02/22/疑难杂症汇总/#more" rel="contents">
阅读全文 »
</a>
</div>
<!--/noindex-->
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/02/22/2017学习计划/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Jerry Chan">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.jpg">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Jerry Chan">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="Jerry Chan" src="">
</span>
</span>