Android面試-View相關

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 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;
        }
]

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章