Android高階知識點

weixin_33912445發表於2018-03-22
  • Android動畫框架實現原理

  • Android各個版本API的區別

    Android版本介紹

  • Requestlayout,onlayout,onDraw,DrawChild區別與聯絡

    RequestLayout()方法 :責任鏈模式</br>
    子View呼叫requestLayout方法,會標記當前View及父容器,同時逐層向上提交,直到ViewRootImpl處理該事件,ViewRootImpl會呼叫三大流程,從measure開始,對於每一個含有標記位的view及其子View都會進行測量、佈局、繪製。</br>
    requestLayout如果沒有改變l,t,r,b,那就不會觸發onDraw;但是如果這次重新整理是在動畫裡,mDirty非空,就會導致onDraw。

    invalidate() 只執行自身draw方法

    onLayout()方法(如果該View是ViewGroup物件,需要實現該方法,對每個子檢視進行佈局)

    呼叫onDraw()方法繪製檢視本身

    drawChild()去重新回撥每個子檢視的draw()方法

    1734948-b4493f7b0234dd69.jpg
    呼叫
  • invalidate和postInvalidate的區別及使用

    invalidate:在ui執行緒重新整理view
    postInvalidate:在工作執行緒重新整理view(底層還是handler)

  • Activity-Window-View三者的差別</br>

    1. 在Activity中呼叫attach,建立了一個Window</br>
    2. 建立的window是其子類PhoneWindow,在attach中建立PhoneWindow</br>
    3. 在Activity中呼叫setContentView(R.layout.xxx)實際上是呼叫的getWindow().setContentView()</br>
    4. 呼叫PhoneWindow中的setContentView方法</br>
    5. 建立ParentView:
      作為ViewGroup的子類,實際是建立的DecorView(作為FramLayout的子類)</br>
    6. 將指定的R.layout.xxx進行填充</br>
      通過佈局填充器進行填充【其中的parent指的就是DecorView】
    7. 呼叫到ViewGroup</br>
    8. 呼叫ViewGroup的removeAllView(),先將所有的view移除掉</br>
    9. 新增新的view:addView()</br>
    2412005-b52e5a25eaf57fbc.png
  • 談談對Volley的理解

  • 如何優化自定義View

    降低重新整理頻率,減少不必要的呼叫invalidate()方法,儘量呼叫多參invalidate(),能做到區域性重新整理而不是整體重新整理

    使用好硬體加速(targetpi>=11)

    初始化時建立物件;不要在onDraw方法內建立繪製物件

    做好狀態的儲存與恢復(onsaveinstance onrestoreinstance)

  • 低版本SDK如何實現高版本api?

    在程式碼中加入版本控制邏輯,新增@targetapi使編譯器通過

  • 描述一次網路請求的流程

    域名解析、TCP的三次握手、建立TCP連線後發起HTTP請求、伺服器響應HTTP請求、瀏覽器解析html程式碼,同時請求html程式碼中的資源(如js、css、圖片等)、最後瀏覽器對頁面進行渲染並呈現給使用者

    HTTP請求格式:</br>

    • 請求行: 請求方法(GET/POST/DELETE/PUT/HEAD)、URI路徑、HTTP版本號</br>
    • 請求頭: 快取相關資訊(Cache-Control,If-Modified-Since)
      客戶端身份資訊(User-Agent)等鍵值對資訊</br>
    • 訊息體: 客戶端發給服務端的請求資料,這部分資料並不是每個請求必須的(post put)

    HTTP響應格式:</br>

    • 狀態行:有HTTP協議版本號,狀態碼和狀態說明三部分構成。</br>
    • 響應頭:用於說明資料的一些資訊,比如資料型別、內容長度等鍵值對。</br>
    • 訊息體:服務端返回給客戶端的HTML文字內容。或者其他格式的資料,比如:視訊流、圖片或者音訊資料。
  • HttpUrlConnection 和 okhttp關係

    從Android4.4開始HttpURLConnection的底層實現採用的是okHttp

  • Bitmap物件的理解

    Bitmap物件的記憶體分為兩部分:

    • Bitmap物件

    • Bitmap畫素資料

    佔用記憶體大,多物件易引發OOM</br>

    Bitmap佔用記憶體計算 = 圖片最終顯示出來的寬 * 圖片最終顯示出來的高 * 圖片品質(Bitmap.Config的值)</br>

    減少記憶體消耗:根據View的大小利用BitmapFactory.Options計算合適的inSimpleSize(>1)來對Bitmap進行相對應的裁剪

    Bitmap的優化主要是加快圖片的載入速度和降低圖片佔用記憶體的大小

  • looper架構

    封裝訊息迴圈和訊息佇列的一個類

    (1) Looper類用來為一個執行緒開啟一個訊息迴圈。 預設情況下android中新誕生的執行緒是沒有開啟訊息迴圈的。(主執行緒除外,主執行緒系統會自動為其建立Looper物件,開啟訊息迴圈。) Looper物件通過MessageQueue來存放訊息和事件。一個執行緒只能有一個Looper,對應一個MessageQueue。

    (2) 通常是通過Handler物件來與Looper進行互動的。Handler可看做是Looper的一個介面,用來向指定的Looper傳送訊息及定義處理方法。

    Looper類淺析

  • ActivityThread,AMS,WMS的工作原理

    AMS和WMS都屬於Android中的系統服務,被所有的App公用的

    AMS(ActivityManagerServices)統一排程所有應用程式的Activity,負責系統中所有Activity的生命週期。</br>
    WMS(WindowManagerService)控制所有Window的顯示與隱藏以及要顯示的位置

    Android系統服務 —— WMS與AMS

  • 自定義View如何考慮機型適配

    合理使用warp_content,match_parent.</br>
    儘可能的是使用RelativeLayout</br>
    針對不同的機型,使用不同的佈局檔案放在對應的目錄下,android會自動匹配。</br>
    儘量使用點9圖片。</br>
    使用與密度無關的畫素單位dp,sp</br>
    引入android的百分比佈局。</br>
    切圖的時候切大解析度的圖,應用到佈局當中。在小解析度的手機上也會有很好的顯示效果。</br>

  • 自定義View的事件

    觸控&&繪製

  • AsyncTask+HttpClient 與 AsyncHttpClient有什麼區別?

  • LaunchMode應用場景

    sinngleTop:防抖</br>
    singleTask:入口Activity</br>
    singleInstance:單例項,多應用公用,不常見

  • AsyncTask 如何使用?

    AsyncTask是Android提供的一個助手類,它對Thread和Handler進行了封裝,方便我們使用,asyncTask.execute() 只能在UI主執行緒中呼叫,多工時不併發,執行緒池

    AsyncTask有四個重要的回撥方法,分別是:onPreExecute(主執行緒)、doInBackground(工作執行緒), onProgressUpdate(主執行緒,在doInBackground中手動調publishProgress) 和 onPostExecute(主執行緒 執行完畢)。

    侷限性:

    • 在Android 4.1版本之前,AsyncTask類必須在主執行緒中載入,這意味著對AsyncTask類的第一次訪問必須發生在主執行緒中;在Android 4.1以及以上版本則不存在這一限制,因為ActivityThread(代表了主執行緒)的main方法中會自動載入AsyncTask </br>
    • AsyncTask物件必須在主執行緒中建立 </br>
    • AsyncTask物件的execute方法必須在主執行緒中呼叫 </br>
    • 一個AsyncTask物件只能呼叫一次execute方法
  • SparseArray原理

    當使用HashMap(K, V),如果K為整數型別時,使用SparseArray的效率更高</br>

    mKeys = new int[initialCapacity];
    mValues = new Object[initialCapacity];

key value 分別為一個陣列 key是有序插入的</br>
查詢key時使用二分查詢法,降低了時間複雜度(O(log2n)),根據找到的key的下標取value

  • 請介紹下ContentProvider 是如何實現資料共享的?

    統一了資料訪問方式

  • Android Service與Activity之間通訊的幾種方式

    • bindService 通過Binder得到Service物件
    • 廣播
    • ......
  • IntentService原理及作用是什麼?

    IntentService保留了Service原有的特性,並且將耗時的操作都放在的子執行緒中,通過Handler的回撥方式實現了資料的返回。

    • IntentService繼承Service,專門處理非同步請求。
    • 客戶端通過呼叫startService(Intent)發起請求,自然資料是通過Intent進行傳遞的。
    • 一旦Service啟動後,對於Intent所傳遞的資料操作都通過工作執行緒(worker thread)進行處理。
    • 在完成資料的處理之後,Handler會回撥其處理結果。在任務結束後會將自身服務關閉。

    通過Handler、Message、Looper在Service中實現的非同步執行緒訊息處理的機制。但是由於是通過衍生Service的方式實現的,因此具有Service的生命週期特性。

  • 說說Activity、Intent、Service 是什麼關係

    Activity Service 四大元件,通過Intent傳遞訊息

  • ApplicationContext和ActivityContext的區別

    生命週期長短,使用Activity的Context持有某些靜態引用會引起記憶體洩漏

    10844298-b70f98cd3d717c2c..jpg
    image

    和UI相關的方法基本都不建議或者不可使用Application

    數字1:啟動Activity在這些類中是可以的,但是需要建立一個新的task。一般情況不推薦。

    數字2:在這些類中去layout inflate是合法的,但是會使用系統預設的主題樣式,如果你自定義了某些樣式可能不會被使用。

    數字3:在receiver為null時允許,在4.2或以上的版本中,用於獲取黏性廣播的當前值。(可以無視)

    Context數量 = Activity數量 + Service數量 + 1

  • SP是程式同步的嗎?有什麼方法做到同步?

    不是</br>
    使用 contentprovider

  • 談談多執行緒在Android中的使用

    避免ANR(UI執行緒5s 廣播10s 服務20s)</br>
    防止耗時操作擁堵執行緒 完成持續性長的耗時操作</br>

    thread && runnable:</br>直接繼承Thread和實現Runnable介面實現多執行緒區別
    眾所周知在Java中類僅支援單繼承,當定義一個新的類的時候,它只能擴充套件一個外部類。假如建立自定義執行緒類的時候是通過擴充套件 Thread類的方法來實現的,那麼這個自定義類就不能再去擴充套件其他的類。因此,如果自定義類必須擴充套件其他的類,那麼就可以使用實現Runnable介面的方法來定義該類為執行緒類,這樣就可以避免Java單繼承所帶來的侷限性。但繼承Thread和實現Runnable重要區別並不是在於此,更重要的是實現Runnable介面的方式建立的執行緒可以處理同一資源,從而實現資源的共享。</br>
    實現Runnable介面相對於擴充套件Thread類來說,具有無可比擬的優勢。此方式不僅有助於程式的健壯性,使程式碼能夠被多個執行緒共享,而且程式碼和資料資源相對獨立,從而特別適合多個具有相同程式碼的執行緒去處理同一資源的情況。使得執行緒、程式碼和資料資源三者有效分離,很好地體現了物件導向程式設計的思想。因此,幾乎所有的多執行緒程式都是通過實現Runnable介面的方式來完成的。

    asynctask

    intentservice

  • 程式和 Application 的生命週期

    程式重要級:前臺(foreground)>可視(visible)>服務(service)>背景(background)>空(cache)

    application生命週期:

    public class App extends Application {

    @Override
    public void onCreate() {
        // 程式建立的時候執行
        Log.d(TAG, "onCreate");
        super.onCreate();
    }
    @Override
    public void onTerminate() {
        // 程式終止的時候執行
        Log.d(TAG, "onTerminate");
        super.onTerminate();
    }
    @Override
    public void onLowMemory() {
        // 低記憶體的時候執行
        Log.d(TAG, "onLowMemory");
        super.onLowMemory();
    }
    @Override
    public void onTrimMemory(int level) {
        // 程式在記憶體清理的時候執行
        Log.d(TAG, "onTrimMemory");
        super.onTrimMemory(level);
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.d(TAG, "onConfigurationChanged");
        super.onConfigurationChanged(newConfig);
    }
    
}
  • 封裝View的時候怎麼知道view的大小

    呼叫view寬高時期view.getMeasuredWidth/Height(確保view已經測量完畢):

    • Activity/View#onWindowFocusChanged 它會被呼叫多次,當 Activity的視窗得到焦點和失去焦點均會被呼叫
    • view.post(runnable) 通過post將一個runnable投遞到訊息佇列的尾部,當Looper呼叫此 runnable的時候,View也初始化好了。
    • ViewTreeObserver.addOnGlobalLayoutListener
  • RecyclerView原理

    RecyclerView 剖析

    RecyclerView 剖析 下

  • AndroidManifest的作用與理解

相關文章