基本上全部 Android 開發都會接觸到 onCreate()
、onDestory()
、onStart()
、onStop()
等這些生命週期方法,但卻不是全部人都會去關注到 onAttachXXX()
這樣的方法羣體,今天,筆者就但願用簡短的文章對此進行必定講解。佈局
首先在 Activity
中咱們能夠重寫 onAttachedToWindow()
和 onDetachedFromWindow()
這一對方法。顧名思義,"Attached" 就是附加的意思,因此咱們能夠肯定 onAttachedToWindow()
就是在 View
附加到 window
上的時候進行回調,而 onDetachedFromWindow()
就恰好相反。post
這一對方法會在咱們熟悉的 Activity
生命週期的 onResume()
和 onPause()
中間,但並非每一次 onResume()
和 onPause()
回調的時候都會在接下來回調它們。應該比較好理解,咱們固然不須要頻繁往 window
中附加和分離 View
嘛。線程
這裏天然咱們容易產生一個問題,在 onAttachedToWindow()
回調的時候,咱們能拿到 View
的寬高麼?換句話說就是這時候 View
是否已經通過了測量和繪製呢?日誌
咱們編寫一個 Demo 進行日誌打印看看。
code
能夠看到,並無。咱們只有在 onWindowFocusChanged
回調的時候才能真正的拿到 View
的寬高值。blog
因此,在 Activity
的 onAttachedToWindow()
回調以後,佈局中的 View
會回調 onAttachedToWindow()
,而後纔會去進行測量和繪製等。那麼咱們要獲取一個 View
的寬高就最好是 View.post()
了。生命週期
View
的 onAttachedToWindow()
的調用時機會發生在 onMeasure()
以前,那麼它們到底有什麼使用場景呢?圖片
咱們在自定義 View 的時候,某些比較重量級的資源,並且不能與其餘 View
通用的時候,就能夠重寫這兩個方法,並在 onAttachedToWindow()
中進行初始化,onDetachedFromWindow()
方法裏釋放掉。內存
好比 Bitmap
,雖然說如今不用主動調用 recycle()
方法來回收,但在 8.0 及以上系統,手動調用是會當即釋放所佔用的內存的,因此我的認爲仍是有必要手動回收的,固然了,若是圖片比較小,對內存沒什麼影響的就不用了。資源
再好比一些用做計算的子線程,或其餘跟 View
顯示有關的任務,在 onDetachedFromWindow()
中也能夠停掉了,由於大多數狀況下,這些實時數據對於被分離後 View
已經沒有意義了。
細心的小夥伴會發現,在 RecyclerView.Adapter
中也會有這麼一個 onViewAttachedToWindow()
和 onViewAttachedToWindow()
。
這兩個方法在列表佈局的時候,用做曝光埋點很是好用,當 Adapter
建立的 View
被窗口分離(即滑動離開了當前窗口界面的)的時候,onViewAttachedToWindow()
會被直接回調,反之,在列表項 View
在被滑動進屏幕的時候,onViewAttachedToWindow()
會立馬被調用。
有了這樣的屬性,對於咱們的曝光埋點,就手到擒來了,直接在裏面作就完事兒了。
說到 Adapter
的 onViewAttachedToWindow
,咋發現這裏面居然還有一個 onAttachedToRecyclerView
方法,根據源碼咱們能夠發現,onAttachedToRecyclerView()
是在 setAdapter()
的時候觸發。
對比一下,咱們便能得出如下它們的使用場景:
RecyclerView
本質上也是一個 ViewGroup
,那麼它的 Item
要顯示出來,天然須要 addView()
進來,移出的時候,固然也要 removeView()
出去,因此對應的天然是 onViewAttachedToWindow()
和 onViewAttachedToWindow()
了。因此在必定場景下,能夠經過這兩個回調來處理一些 Item 移出屏幕,移進屏幕鎖須要的工做。爲何說必定場景下呢,由於若是調用了 notifyDataSetChanged()
方法的話,會觸發當前在屏幕中的全部 Item 的 onViewAttachedToWindow()
。onAttachedToRecyclerView
和 onAttachedToRecyclerView()
的話,就更加適合作一些資源回收的工做啦。可能會有小夥伴會遇到這個問題,在遇到這個問題前,先檢查一下你這個 RecyclerView
是不是一個正常滾動的 View
,你若是是被別人嵌套滾動,把本身設置了 isNestedScrollingEnabled
爲 false 的話,那你都失去了 Recyclerview
的功用了,那天然是不行的。
可能又有小夥伴說了,因爲需求歷史緣由,我就是用了 NestedScrollView
嵌套了 Recyclerview
,並禁掉了 Recyclerview
的滑動功能,但又想作上面的曝光埋點功能,那如何是好?
若是是這樣的話,大概你就只能經過相似 View
的 getGlobalVisibleRect()
這樣的方法來判斷 View
的可見性來處理了。關於 View
的可見性分析,這裏就點到爲止,你們就自行 Google 吧。