版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/JourneyX/article/details/80462719
【
view繪製、事件分發、listview緩存
>>>View繪製機制:{
view樹的繪製流程、measure、layout、draw
===view樹的繪製流程:[
measure<是否重新計算視圖大小> --->layout<是否重新安置視圖位置>----->draw<是否需要重繪> 是一個遞歸過程
---measure測量:樹的遞歸過程,自上而下有序進行遍歷
--->參數
1、ViewGroup.LayoutParams:設置寬高
2、MeasureSpec:測量規格,包含兩種,一種是測量它的模式;第二種是在這種模式下測量的大小。
--->重要方法
1、measure:最終還是調用了onMeasure方法
2、onMeasure:測量邏輯的方法,兩個參數,寬高的測量規格。抽象方法,需要自定義。
3、setMeasuredDimension():將測量好的規格,完成整個測量過程
---layout:樹的遞歸過程,自上而下有序進行遍歷。根據測量的尺寸來擺放子視圖的位置。
1、layout:最終調用onLayout方法
2、onLayout:抽象方法,需要自定義。分垂直方向和水平方向的佈局。
---onDraw:
---兩個容易混淆的方法<回調>:
1、invalidate():請求系統,如果視圖沒有發生變化就不會繪製。
2、requestLayout():當佈局發生變化的時候<方向、尺寸>會調用,它就會去出發measure和layout方法,但是它不會調用draw方法。
]
}
>>>事件分發:{ 事件傳遞、事件分發:
爲什麼會有事件分發、三個重要的事件分發方法、事件分發流程
===爲什麼會有事件分發:[
Android中的view是以樹型結構擺放的,可能有多個view重疊在一起,點擊重疊的view會同時響應。
安卓上面的view是樹型結構的,View可能會重疊在一起,當我們點擊的地方有多個View都可以響應的時候,這個點擊事件應該給誰呢?爲了解決這一個問題,就有了事件分發機制。
PhoneWindow---DecorView----RootView-----ViewGroupA----View1
沒有View遮擋的部分會顯示主題的顏色,主題的顏色和標題欄是在DecorView中的。
---Window:抽象類,它是所有視圖最頂層的容器,包括了背景的顯示、標題欄和事件的處理。
---PhoneWindow:是Window的唯一實現類,是View的事件管理容器。
---DecorView:是PhoneWindow的內部類,來進行消息的傳遞。
]
===三個重要的事件分發方法:[
Activity和View是沒有第二個攔截的,Activity作爲整個事件的原始分發者,如果Activity攔截了這個事件就會導致整個頁面沒法相應,View作爲整個事件傳遞的末端,要麼消費事件,要麼就不處理進行回傳。
1、dispatchTouchEvent:分發,決定了它的觸摸事件是由自己處理還是分發給子View,讓子View遞歸調用自身dispatchTouchEvent方法來處理。在dispatchTouchEvent源碼中會調用onInterceptTouchEvent來判斷是否要進行攔截。
2、onInterceptTouchEvent:用來攔截事件,當父控件下發事件給子控件進行處理的時候,如果子控件需要對控件進行處理,就會在此方法中進行攔截,然後在子控件中onTouchEvent處理。
3、onTouchEvent:觸摸事件<手勢事件>,是View中的一個方法。
]
===事件分發流程:[
當屏幕被點擊的時候:Activity --->PhoneWindow --->DecorView --->ViewGroup ---->....... ----->View。如果分發到最後一個View,也沒有處理事件,事件會依次返轉,最後迴轉到最高位的Activity,如果Activity還沒處理,事件纔會被拋棄。這是責任鏈設計模式。既保證了事件的有序性,又非常靈活。
]
}
>>>listview緩存:{
什麼是listview、listview適配器模式、listview的recycleBin機制、listview的優化
===什麼是listview:[
ListView就是一個能數據集合以動態滾動的方式展示到用戶界面上的View。
]
===listview適配器模式:[
Adapter是ListView和數據之間的橋樑,爲了保證數據和View的分離。
]
===listview的recycleBin機制:[
--- private View[] mActiveViews = new View[0]; 用於存儲活動的View,代表可見的View,這些View是可以直接被複用。
--- private ArrayList<View>[] mScrapViews; //所有廢棄的View,即劃出屏幕的View。
--- private ArrayList<View> mCurrentScrap; //當前被滑出去的View,被廢棄的View集合。
---public void setViewTypeCount(int viewTypeCount) { //爲ListView中的每一個數據項建立一個recycleBin機制
--- void fillActiveViews(int childCount, int firstActivePosition) { //填充
---View getActiveView(int position) { //獲取相應屏幕上顯示的View
--- void addScrapView(View scrap, int position) { //緩存廢棄的View
ListView中屏幕可見的纔會保存在內存中,移除屏幕後加入RecycleBin,再次進入屏幕的從RecycleBin獲取。
]
===ListView優化:[
public View getView( int position,View convertView,ViewGroup parent ) //convertView 緩存
1、contentView重用 / viewHolder:contentView緩存的作用,複用控件;viewHolder避免多次findViewByid,減少查找控件的次數,佈局二叉樹結構,每次遍歷都很耗時。
2、三級緩存 / 監聽滑動事件: 圖片加載的時候需要用到緩存,儘量在getView中少做耗時操作,保證ListView滑動的流暢性。 如果一定要做耗時操作,可以設置監聽滑動事件,等滑動停止過後再去加載整個圖片。
3、避免使用半透明元素,半透明繪製比不透明更耗時。
4、開啓硬件加速。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.list_item, null);
holder.img = (ImageView) convertView.findViewById(R.id.img);
holder.title = (TextView) convertView.findViewById(R.id.title);
holder.info = (TextView) convertView.findViewById(R.id.info);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText("Hello");
holder.info.setText("World");
return convertView;
}
]
}
】