Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [android]深入理解findViewById原理

[android]深入理解findViewById原理

編輯:關於Android編程

用的太多了,但是不知道原理。Xutils裡面捨棄了findViewById改用注解,當時也很不理解。一步步了解後,發現,相比注解的方式加載控件,findViewById的效率是很低的。注解+反射加載實例的過程看上去效率更高。

 

從activity的onCreate()裡開始:

 

\

點進去看源碼進入Activity.class類裡的方法:

Activity.class

\

發現這個返回的是getWindow()的findViewById方法,這個getWindow()是什麼?

Activity.class

\

返回的是一個Window對象,Window是個抽象類,包含的抽象方法可以管理Activity的UI組件,先這麼理解,這次主要理解findViewById的原理。

 

既然Activity的findViewById,是調用getWindow()(即Window對象)的findViewById方法,進入Window查找它的findViewById。

 

Window.class

\

返回的是getDecorView()的findViewById,前面說Window是個抽象類,不能具體實現管理ActivityUI組件的方法,那麼這個getDecorView()就是返回的是一個具體的View對象,來管理Activity的UI組件。\

這個getDecorView是個抽象類,實現這個類,返回的View可以用來管理UI視圖。

\

然後Activity的findViewById方法,又通過getDecorView()(返回View)一步一步傳入到View的findViewById了。下面是View類。

 

 

View.class

\

 

邏輯很簡單了,直接調用findViewTraversal(),用mID跟傳入的id對比,如果存在就返回當前view,不存在就返回null。findViewTraversal從字面上理解,這個方法的意思是反復尋找view的ID。

\

到這裡我有點沒有頭緒了,憑感覺,查找mID應該是不斷+1比較,如果是ViewGroup,裡面還有View的話,還應該是一個遞歸的過程,從這裡看不出來。所以我看是找mID是如何設置的。

 

這是一個set方法,給子view控件添加ID,用來標識view。這個ID可以在R文件裡看到。

\

先把id給了mID,如果mID為空(就是沒有加ID呢),而且不是作為標簽(不太懂),那麼就給他加一個ID,動態生成控件的ID。

\

 

一個固定地址開始,一個一個找ID,設置的ID值似乎連續的。然後在後面的查找中,找遞歸,找循環。。沒有找到類似的代碼。

看上去,要知道mID才能知道答案。但是這樣分析下去得不到結果。

原因:

請看LinearLayout,RelativeLayout等等layout的繼承結構:

\

 

在ViewGroup中,已經對View的findViewTraversal()方法進行重寫了!

點進去找很快找到答案。

這個是重寫的方法:可以非常清楚的看到,findViewById的原理,是從頭開始找,遇到有子控件的,就遞歸接著找。先不考慮具體細節,到這裡,開始的猜想得到了證實。其中v.findViewById又調用View中的方法,而View的findViewById調用的findViewTraversal()。這樣實現了一個遞歸。

 

尊重作者注明出處:http://blog.csdn.net/bless2015/article/details/46618639

 

\

 

我在找findViewById的過程中,由於開始忽略子類ViewGroup對View方法的重寫,導致在View.class萬行代碼中陷入死循環,找不到想看到的方法。但是還是找到一些有趣的東西,有時間再整理下來。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved