1. 程式人生 > >Android拿高薪面試題必看

Android拿高薪面試題必看

外掛化、熱修復 、熱更新的理解

  • 外掛化 – apk 分為宿主和外掛部分,外掛在需要的時候才載入進來

  • 熱修復 – 更新的類或者外掛粒度較小的時候,我們會稱之為熱修復,一般用於修復bug

  • 熱更新 – 2016 Google 的 Android Studio 推出了Instant Run 功能 同時提出了3個名詞

    • “ 熱部署” – 方法內的簡單修改,無需重啟app和Activity。
    • “暖部署” – app無需重啟,但是activity需要重啟,比如資源的修改。

      • “冷部署” – app需要重啟,比如繼承關係的改變或方法的簽名變化等。
  • 站在app開發者角度的“熱”是指在不發版的情況來實現更新

  • 而Google提出的“熱”是指值是否需要重新啟動。 - 同時在開發外掛化的時候也有兩種情景
  • 一種是外掛與宿主apk沒有互動,只是在使用者使用到的時候進行一次吊起
  • 還有一種是與宿主有很多的互動

你認為android熱更新框架哪個好:

  • 1.阿里的熱更新框架已經開源 了。但已經很久沒有更新過新版本了。當前的版本只支援到了 Android 4.4。由於 5.0 起新的 ART 虛擬機器、更嚴格的 SELinux 策略以及對 64 位的支援之類的事,使得 Xposed 都在開發上做了很多調整。我不知道 Dexposed 現在是否支援,但至少阿里沒有開源。

  • 2.在本地動態執行遠端下發的程式碼是極度危險的行為。利用此方法執行非法程式碼等或用於繞過 Google Play 等市場的審查是違反相關協議的,也是對使用者極度不負責任的行為。

  • 3.在一些訪問非常密集的地方使用熱更新可能會對效率產生相對比較大的影響,應該避免使用.

  • 4.我們可以對 Java 的 ScriptEngine 進行一些封裝成為一個 HotPatch 類使得它更適合做熱更新的工作。

  • 5.首先,檢查熱更新補丁的管道一定要建立在 https 上,因為下發程式碼是極其危險的,如果被劫持,後果是無法想象的。其次,請求時最好自動帶上 Android 版本、手機型號、地區、版本號等資訊,以方便更精確地下發,千萬不能下發錯。

  • 6.Java在執行時載入對應的類是通過ClassLoader來實現的,ClassLoader本身是一個抽象來,Android中使用PathClassLoader類作為Android的預設的類載入器

  • 7.我們的如果想做hotpatch,一定要保證我們的hotpacth dex檔案出現在dexElements列表的前面。

    二.常用的熱更新技術框架:

  • 基於QQ空間的HotFix →→ 要使用到android dex分包方案→拆分dex的專案的話,可以參考一下谷歌的multidex方案實現.

  • 大眾點評的NuWa←專案補丁自動化做的很完整

  • alibaba/AndFix

  • 阿里巴巴的DexPosed

  • dalvik_patch實現multidex

  • 使用React-Native實現app熱部署的一次實踐

  • alibaba/AndFix

基礎

activity生命週期圖解

Markdown
Markdown

注意

鎖定屏與解鎖螢幕 只會呼叫onPause(),而不會呼叫onStop方法,開屏後則呼叫onResume()。在實際操作中會有所出入,比如在三星手機測試的時候鎖定手機呼叫了onPause()和onStop()方法,解鎖時候呼叫的是:onRestart(),onStart()和 onResume()方法。

介紹不同場景下Activity生命週期的變化過程

  • 啟動Activity:

    onCreate()—>onStart()—>onResume(),Activity進入執行狀態。

  • Activity退居後臺:

    當前Activity轉到新的Activity介面或按Home鍵回到主屏: onPause()—>onStop(),進入停滯狀態。

  • Activity返回前臺:
    onRestart()—>onStart()—>onResume(),再次回到執行狀態。

  • Activity退居後臺,且系統記憶體不足,

    系統會殺死這個後臺狀態的Activity,若再次回到這個Activity,則會走onCreate()–>onStart()—>onResume()

  • 鎖定屏與解鎖螢幕

    只會呼叫onPause(),而不會呼叫onStop方法,開屏後則呼叫onResume()

Activity銷燬但Task如果沒有銷燬掉,當Activity重啟時這個AsyncTask該如何解決?

比如螢幕旋轉這個例子,在重建Activity的時候,會回撥

Activity.onRetainNonConfigurationInstance()

重新傳遞一個新的物件給AsyncTask,完成引用的更新

若Activity已經銷燬,此時AsynTask執行完並返回結果,會報異常麼?

  • 當一個App旋轉時,整個Activity會被銷燬和重建。

  • 當Activity重啟時,AsyncTask中對該Activity的引用是無效的,因此onPostExecute()就不會起作用

  • 若AsynTask正在執行,折會報 view not attached to window manager 異常

  • 同樣也是生命週期的問題,在 Activity 的onDestory()方法中呼叫Asyntask.cancal方法,讓二者的生命週期同步

記憶體不足時,系統會殺死後臺的Activity,如果需要進行一些臨時狀態的儲存,在哪個方法進行

  • Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並不是生命週期方法,不同於 onCreate()、onPause()等生命週期方法,它們並不一定會被觸發。
  • 當應用遇到意外情況(如:記憶體不足、使用者直接按Home鍵)由系統銷燬一個Activity,onSaveInstanceState() 會被呼叫。

  • 但是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被呼叫。除非該activity是被使用者主動銷燬的

  • 通常onSaveInstanceState()只適合用於儲存一些臨時性的狀態,而onPause()適合用於資料的持久化儲存。

介紹Activity 四中launchMode:

我們可以在AndroidManifest.xml配置的android:launchMode屬性為以下四種之一。

  • 1、standard

    standard模式是預設的啟動模式,不用為配置android:launchMode屬性即可,當然也可以指定值為standard。standard啟動模式,不管有沒有已存在的例項,都生成新的例項。

  • 2、 singleTop

    我們在上面的基礎上為指定屬性android:launchMode=”singleTop”,系統就會按照singleTop啟動模式處理跳轉行為。跳轉時系統會先在棧結構中尋找是否有一個Activity例項正位於棧頂,如果有則不再生成新的,而是直接使用。如果系統發現存在有Activity例項,但不是位於棧頂,重新生成一個例項。 這就是singleTop啟動模式,如果發現有對應的Activity例項正位於棧頂,則重複利用,不再生成新的例項。

  • 3、 singleTask

    如果發現有對應的Activity例項,則使此Activity例項之上的其他Activity例項統統出棧,使此Activity例項成為棧頂物件,顯示到幕前。

  • 4、singleInstance

    這種啟動模式比較特殊,因為它會啟用一個新的棧結構,將Acitvity放置於這個新的棧結構中,並保證不再有其他Activity例項進入。

LaunchMode使用場景

  • singleTop適合接收通知啟動的內容顯示頁面。

    例如,某個新聞客戶端的新聞內容頁面,如果收到10個新聞推送,每次都開啟一個新聞內容頁面是很煩人的。

  • singleTask適合作為程式入口點。

    例如瀏覽器的主介面。不管從多少個應用啟動瀏覽器,只會啟動主介面一次,其餘情況都會走onNewIntent,並且會清空主介面上面的其他頁面。

  • singleInstance應用場景:

    鬧鈴的響鈴介面。 你以前設定了一個鬧鈴:上午6點。在上午5點58分,你啟動了鬧鈴設定介面,並按 Home 鍵回桌面;在上午5點59分時,你在微信和朋友聊天;在6點時,鬧鈴響了,並且彈出了一個對話方塊形式的 Activity(名為 AlarmAlertActivity) 提示你到6點了(這個 Activity 就是以

  • SingleInstance

    載入模式開啟的),你按返回鍵,回到的是微信的聊天介面,這是因為 AlarmAlertActivity 所在的 Task 的棧只有他一個元素, 因此退出之後這個 Task 的棧空了。如果是以 SingleTask 開啟 AlarmAlertActivity,那麼當鬧鈴響了的時候,按返回鍵應該進入鬧鈴設定介面。

如何把一個應用設定為系統應用

  • Android設定是Debug版本,且root,直接將該apk用adb工具push到system/app或system/priv-app

  • 如果是非root裝置,需要編譯後燒寫映象

  • 有些許可權(如WRITE_SECURE_SETTINGS)不開放給第三方應用,只能在對應裝置原始碼總編譯然後作為系統app使用

Activity,Window,View三者的聯絡和區別?

  • Activity像一個工匠(控制單元)

  • Window像窗戶(承載模型)

  • View像窗花(顯示檢視)

  • LayoutInflater像剪刀

  • Xml配置像窗花圖紙。

Activity啟動Service的兩種方式

  • startService:生命週期和呼叫者不同.啟動後若呼叫者未呼叫stopService而直接退出,Service仍會執行

  • bindService:生命週期與呼叫者繫結,呼叫者一旦退出,Service就會呼叫unBind->onDestory

Android兩個應用能在同一個任務棧嗎?

棧一般以包名命名,兩個應用的簽名和udid要相同

Fragment是什麼?你曾經遇到哪些有關Fragment的問題?

  • Fragment可以作為Activity介面的一部分組成出現

    • 其作用是:

      碎片整理,區域性重新整理。

  • 一個Activity中可以同時出現多個Fragment,並一個Fragment也可以在多個Activity中使用.

  • 在Activity中可以新增,刪除,替換Fragment.Fragment可以響應自己的輸入時間,並且有自己的生命週期,但其生命週期收Activity影響.

Fragment生命週期

Markdown
Markdown

如何實現Activity視窗快速變暗

利用只讀屬性動畫+WindowManager

 /* 
  *@param from\>=0&&from\<=1.0f
  * @param to\>=0&&to\<=1.0f
  * 
  * */
 private void dimBackground(final float from, final float to) {
 final Window window = getWindow();
 ValueAnimator valueAnimator = ValueAnimator.ofFloat(from, to);
 valueAnimator.setDuration(500);
 valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
 @Override
 public void onAnimationUpdate(ValueAnimator animation) {
 WindowManager.LayoutParams params = window.getAttributes();
 params.alpha = (Float) animation.getAnimatedValue();
 window.setAttributes(params);
 }
 });

 valueAnimator.start();
 }

是否使用過本地廣播,和全域性廣播有什麼區別?

本地廣播在本應用範圍內傳播,不用擔心隱私資料洩露,不用擔心別的應用偽造廣播.相比全域性廣播,本地廣播更高效.

註冊廣播的幾種方法?

  • 1.靜態註冊:在清單檔案中註冊, 常見的有監聽裝置啟動,常駐註冊不會隨程式生命週期改變

  • 2.動態註冊:在程式碼中註冊,隨著程式的結束,也就停止接受廣播了

    補充一點:有些廣播只能通過動態方式註冊,比如時間變化事件、螢幕亮滅事件、電量變更事件,因為這些事件觸發頻率通常很高,如果允許後臺監聽,會導致程序頻繁建立和銷燬,從而影響系統整體效能

為什麼Android引入廣播機制?
  • a:從MVC的角度考慮(應用程式內) 其實回答這個問題的時候還可以這樣問,android為什麼要有那4大元件,現在的移動開發模型基本上也是照搬的web那一套MVC架構,只不過是改了點嫁妝而已。

    • android的四大元件本質上就是為了實現移動或者說嵌入式裝置上的MVC架構

      • 它們之間有時候是一種相互依存的關係,有時候又是一種補充關係,引入廣播機制可以方便幾大元件的資訊和資料互動。
  • b:程式間互通訊息(例如在自己的應用程式內監聽系統來電)

  • c:效率上(參考UDP的廣播協議在區域網的方便性)

  • d:設計模式上(反轉控制的一種應用,類似監聽者模式)

瞭解IntentServices嗎?

  • IntentService是Service的子類,是一個非同步的,會自動停止的服務,很好解決了傳統的Service中處理完耗時操作忘記停止並銷燬Service的問題

  • 生成一個預設的且與執行緒相互獨立的工作執行緒執行所有傳送到onStartCommand()方法的Intent,可以在onHandleIntent()中處理.

  • 序列佇列,每次只執行一個任務,不存線上程安全問題,所有任務執行完後自動停止服務,不需要自己手動呼叫stopSelf()來停止.

如何提升Service程序優先順序

在AndroidManifest.xml檔案中對於intent-filter可以通過android:priority = “1000”這個屬性設定最高優先順序,1000是最高值,如果數字越小則優先順序越低,同時適用於廣播。

ContentProvider和sql的區別

ContentProvider的主要還是用於資料共享,其可以對Sqlite,SharePreferences,File等進行資料操作用來共享資料。而sql的可以理解為資料庫的一門語言,可以使用它完成CRUD等一系列的操作

資料儲存相關
  • 檔案儲存:

    通過Java.io.FileInputStream和java.io.FileOutputStream這兩個類來實現對檔案的讀寫,java.io.File類則用來構造一個具體指向某個檔案或者資料夾的物件。

  • SharedPreferences:

    SharedPreferences是一種輕量級的資料儲存機制,他將一些簡單的資料型別的資料,包括boolean型別,int型別,float型別,long型別以及String型別的資料,以鍵值對的形式儲存在應用程式的私有Preferences目錄(/data/data/<包名>/shared_prefs/)中,這種Preferences機制廣泛應用於儲存應用程式中的配置資訊。

  • SQLite資料庫:

    當應用程式需要處理的資料量比較大時,為了更加合理地儲存、管理、查詢資料,我們往往使用關係資料庫來儲存資料。Android系統的很多使用者資料,如聯絡人資訊,通話記錄,簡訊息等,都是儲存在SQLite資料庫當中的,所以利用操作SQLite資料庫的API可以同樣方便的訪問和修改這些資料。

  • ContentProvider:

    主要用於在不同的應用程式之間實現資料共享的功能,不同於sharepreference和檔案儲存中的兩種全域性可讀寫操作模式,內容提供其可以選擇只對哪一部分資料進行共享,從而保證我們程式中的隱私資料不會有洩漏的風險

如何將開啟res aw目錄中的資料庫檔案?

  • 在Android中不能直接開啟res aw目錄中的資料庫檔案,而需要在程式第一次啟動時將該檔案複製到手機記憶體或SD卡的某個目錄中,然後再開啟該資料庫檔案。

  • 複製的基本方法是使用getResources().openRawResource方法獲得res aw目錄中資源的 InputStream物件,然後將該InputStream物件中的資料寫入其他的目錄中相應檔案中。

  • 在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法來開啟任意目錄中的SQLite資料庫檔案。

什麼是aar?aar是jar有什麼區別?

“aar”包是 Android 的類庫專案的二進位制發行包。
副檔名是.aar,maven 專案型別應該也是aar,但檔案本身是帶有以下各項的 zip 檔案:

  • /AndroidManifest.xml (mandatory)
  • /classes.jar (mandatory)
  • /res/ (mandatory)
  • /R.txt (mandatory)
  • /assets/ (optional)
  • /libs/*.jar (optional)
  • /jni//*.so (optional)
  • /proguard.txt (optional)
  • /lint.jar (optional)

這些條目是直接位於 zip 檔案根目錄的。 其中R.txt 檔案是aapt帶引數–output-text-symbols的輸出結果。

jar打包不能包含資原始檔,比如一些drawable檔案、xml資原始檔之類的,aar可以。

SQLite支援事務嗎?新增刪除如何提高效能?

SQLite作為輕量級的資料庫,比MySQL還小,但支援SQL語句查詢,提高效能可以考慮通過原始經過優化的SQL查詢語句方式處理

如何將SQLite資料庫(dictionary.db檔案)與apk檔案一起釋出?

可以將dictionary.db檔案複製到Eclipse Android工程中的res aw目錄中。所有在res aw目錄中的檔案不會被壓縮,這樣可以直接提取該目錄中的檔案。可以將dictionary.db檔案複製到res aw目錄中

如何保證Service在後臺不被kill

  • Service設定成START_STICKY kill 後會被重啟(等待5秒左右),重傳Intent,保持與重啟前一樣

  • 通過 startForeground將程序設定為前臺程序, 做前臺服務,優先順序和前臺應用一個級別​,除非在系統記憶體非常缺,否則此程序不會被 kill

  • 雙程序Service: 讓2個程序互相保護**,其中一個Service被清理後,另外沒被清理的程序可以立即重啟程序

  • QQ黑科技: 在應用退到後臺後,另起一個只有 1 畫素的頁面停留在桌面上,讓自己保持前臺狀態,保護自己不被後臺清理工具殺死

  • 在已經root的裝置下,修改相應的許可權檔案,將App偽裝成系統級的應用 Android4.0系列的一個漏洞,已經確認可行

  • 用C編寫守護程序(即子程序) : Android系統中當前程序(Process)fork出來的子程序,被系統認為是兩個不同的程序。當父程序被殺死的時候,子程序仍然可以存活,並不受影響。*鑑於目前提到的在Android->- Service層做雙守護都會失敗*,我們可以fork出c程序,多程序守護。死迴圈在那檢查是否還存在,具體的思路如下(Android5.0以上的版本不可行)

  • 用C編寫守護程序(即子程序),守護程序做的事情就是迴圈檢查目標程序是否存在,不存在則啟動它。
    在NDK環境中將1中編寫的C程式碼編譯打包成可執行檔案(BUILD_EXECUTABLE)。主程序啟動時將守護程序放入私有目錄下,賦予可執行許可權,啟動它即可。

  • 聯絡廠商,加入白名單

Android中如何獲得手機的唯一標示.

  • 1 首先嚐試讀取IMEI、Mac地址、CPU號等物理資訊(有不少工具可以修改IMEI);

  • 2 如果均失敗,可以自己生成UUID然後儲存到檔案(檔案也可能被篡改或刪除)

mipmap資料夾和drawable資料夾的區別

它只是用來放啟動圖示的,好處就是,你只用放一個mipmap圖示,它就會給你各種版本(比如平板,手機)的apk自動生成相應解析度的圖示,以節約空間。

ListView卡頓的原因以及優化策略

  • 重用converView: 通過複用converview來減少不必要的view的建立,另外Infalte操作會把xml檔案例項化成相應的View例項,屬於IO操作,是耗時操作。

  • 減少findViewById()操作: 將xml檔案中的元素封裝成viewholder靜態類,通過converview的setTag和getTag方法將view與相應的holder物件繫結在一起,避免不必要的findviewbyid操作

  • 避免在 getView 方法中做耗時的操作: 例如載入本地 Image 需要載入記憶體以及解析 Bitmap ,都是比較耗時的操作,如果使用者快速滑動listview,會因為getview邏輯過於複雜耗時而造成滑動卡頓現象。使用者滑動時候不要載入圖片,待滑動完成再載入,可以使用這個第三方庫glide

  • Item的佈局層次結構儘量簡單,避免佈局太深或者不必要的重繪

  • 儘量能保證 Adapter 的 hasStableIds() 返回 true 這樣在 notifyDataSetChanged() 的時候,如果item內容並沒有變化,ListView 將不會重新繪製這個 View,達到優化的目的

  • 在一些場景中,ScollView內會包含多個ListView,可以把listview的高度寫死固定下來。 由於ScollView在快速滑動過程中需要大量計算每一個listview的高度,阻塞了UI執行緒導致卡頓現象出現,如果我們每一個item的高度都是均勻的,可以通過計算把listview的高度確定下來,避免卡頓現象出現

  • 使用 RecycleView 代替listview: 每個item內容的變動,listview都需要去呼叫notifyDataSetChanged來更新全部的item,太浪費效能了。RecycleView可以實現當個item的區域性重新整理,並且引入了增加和刪除的動態效果,在效能上和定製上都有很大的改善

  • ListView 中元素避免半透明: 半透明繪製需要大量乘法計算,在滑動時不停重繪會造成大量的計算,在比較差的機子上會比較卡。 在設計上能不半透明就不不半透明。實在要弄就把在滑動的時候把半透明設定成不透明,滑動完再重新設定成半透明。

  • 儘量開啟硬體加速: 硬體加速提升巨大,避免使用一些不支援的函式導致含淚關閉某個地方的硬體加速。當然這一條不只是對 ListView。

ViewHolder為什麼要被宣告成靜態內部類

  • 這個是考靜態內部類和非靜態內部類的主要區別之一。非靜態內部類會隱式持有外部類的引用,就像大家經常將自定義的adapter在Activity類裡,然後在adapter類裡面是可以隨意呼叫外部activity的方法的。

  • 當你將內部類定義為static時,你就調用不了外部類的例項方法了,因為這時候靜態內部類是不持有外部類的引用的。宣告ViewHolder靜態內部類,可以將ViewHolder和外部類解引用。

  • 大家會說一般ViewHolder都很簡單,不定義為static也沒事吧。確實如此,但是如果你將它定義為static的,說明你懂這些含義。萬一有一天你在這個ViewHolder加入一些複雜邏輯,做了一些耗時工作,那麼如果ViewHolder是非靜態內部類的話,就很容易出現記憶體洩露。

  • 如果是靜態的話,你就不能直接引用外部類,迫使你關注如何避免相互引用。 所以將 ViewHolder內部類 定義為靜態的,是一種好習慣

動畫相關

Android中的動畫有哪些?

  • 逐幀動畫(Drawable Animation):

    載入一系列Drawable資源來建立動畫,簡單來說就是播放一系列的圖片來實現動畫效果,可以自定義每張圖片的持續時間

  • 補間動畫(Tween Animation):

    Tween可以對View物件實現一系列簡單的動畫效果,比如位移,縮放,旋轉,透明度等等。但是它並不會改變View屬性的值,只是改變了View的繪製的位置,比如,一個按鈕在動畫過後,不在原來的位置,但是觸發點選事件的仍然是原來的座標。

  • 屬性動畫(Property Animation):

    動畫的物件除了傳統的View物件,還可以是Object物件,動畫結束後,Object物件的屬性值被實實在在的改變了

Android動畫原理

  • Animation框架定義了透明度,旋轉,縮放和位移幾種常見的動畫,而且控制的是整個View
  • 實現原理是每次繪製檢視時View所在的ViewGroup中的drawChild函式獲取該View的Animation的Transformation值

  • 然後呼叫canvas.concat(transformToApply.getMatrix()),通過矩陣運算完成動畫幀,如果動畫沒有完成,繼續呼叫invalidate()函式,啟動下次繪製來驅動動畫

  • 動畫過程中的幀之間間隙時間是繪製函式所消耗的時間,可能會導致動畫消耗比較多的CPU資源,最重要的是,動畫改變的只是顯示,並不能相應事件

View繪製相關

SurfaceView和View的區別

  • SurfaceView中採用了雙快取技術,在單獨的執行緒中更新介面

  • View在UI執行緒中更新介面

介紹下自定義view的基本流程

  • 1、 明確需求,確定你想實現的效果

  • 2、確定是使用組合控制元件的形式還是全新自定義的形式,組合控制元件即使用多個系統控制元件來合成一個新控制元件,你比如titilebar,這種形式相對簡單,參考

  • 3、如果是完全自定義一個view的話,你首先需要考慮繼承哪個類,是View呢,還是ImageView等子類。

  • 4、根據需要去複寫View#onDraw、View#onMeasure、View#onLayout方法

  • 5.根據需要去複寫dispatchTouchEvent、onTouchEvent方法

  • 6、根據需要為你的自定義view提供自定義屬性,即編寫attr.xml,然後在程式碼中通過TypedArray等類獲取到自定義屬性值

  • 7、需要處理滑動衝突、畫素轉換等問題
    談談View的繪製流程

談談View的繪製流程

Markdown
Markdown

measure()方法,layout(),draw()三個方法主要存放了一些識別符號,來判斷每個View是否需要再重新測量,佈局或者繪製,主要的繪製過程還是在onMeasure,onLayout,onDraw這個三個方法中

  • 1.onMesarue() 為整個View樹計算實際的大小,即設定實際的高(對應屬性:mMeasuredHeight)和寬(對應屬性: mMeasureWidth),每個View的控制元件的實際寬高都是由父檢視和本身檢視決定的。

  • 2.onLayout() 為將整個根據子檢視的大小以及佈局引數將View樹放到合適的位置上。

  • 3.onDraw() 開始繪製圖像,繪製的流程如下

    • 首先繪製該View的背景
    • 呼叫onDraw()方法繪製檢視本身 (每個View都需要過載該方法,ViewGroup不需要實現該方法)
    • 如果該View是ViewGroup,呼叫dispatchDraw ()方法繪製子檢視
      繪製滾動條

自定義View執行invalidate()方法,為什麼有時候不會回撥onDraw()

  • 自定義一個view時,重寫onDraw。呼叫view.invalidate(),會觸發onDraw和computeScroll()。前提是該view被附加在當前視窗.
    view.postInvalidate(); //是在非UI執行緒上呼叫的

  • 自定義一個ViewGroup,重寫onDraw。onDraw可能不會被呼叫,原因是需要先設定一個背景(顏色或圖)。表示這個group有東西需要繪製了,才會觸發draw,之後是onDraw。因此,一般直接重寫dispatchDraw來繪製viewGroup.自定義一個ViewGroup,dispatchDraw會呼叫drawChild.

事件傳遞機制

談談touch事件的傳遞流程

Markdown
Markdown
  • 所有Touch事件都被封裝成了MotionEvent物件,包括Touch的位置、時間、歷史記錄以及第幾個手指(多指觸控)等。

  • 事件型別分為ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每個事件都是以ACTION_DOWN開始ACTION_UP結束。

  • 對事件的處理包括三類,分別為傳遞——dispatchTouchEvent()函式、攔截——onInterceptTouchEvent()函式、消費——onTouchEvent()函式和OnTouchListener()

簡單來說:

  • 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被停止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View可以通過onTouchEvent()對事件進行處理。

  • 事件由父View(ViewGroup)傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()對事件做攔截,停止其往下傳遞。

  • 如果事件從上往下傳遞過程中一直沒有被停止,且最底層子View沒有消費事件,事件會反向往上傳遞,這時父View(ViewGroup)可以進行消費,如果還是沒有被消費的話,最後會到Activity的onTouchEvent()函式。

  • 如果View沒有對ACTION_DOWN進行消費,之後的其他事件不會傳遞過來。

= OnTouchListener優先於onTouchEvent()對事件進行消費。
上面的消費即表示相應函式返回值為true。

View中setOnTouchListener中的onTouch,onTouchEvent,onClick的執行順序

onTouch優於onTouchEvent,onTouchEvent優於onClick

觸控事件的分發機制詳見:

什麼是Dalvik虛擬機器

  • Dalvik虛擬機器是Android平臺的核心。

  • 它可以支援.dex格式的程式的執行

  • .dex格式是專為Dalvik設計的一種壓縮格式
  • 可以減少整體檔案尺寸
  • 提高I/O操作的速度
  • 適合記憶體和處理器速度有限的系統

Dalvik虛擬機器和JVM有什麼區別

  • Dalvik 基於暫存器,而 JVM 基於棧。基於暫存器的虛擬機器對於更大的程式來說,在它們編譯的時候,花費的時間更短。

  • Dalvik執行.dex格式的位元組碼,而JVM執行.class格式的位元組碼

Android為每個應用程式分配的記憶體大小是多少

  • 一般是16m或者24m,但是可以通過android:largeHeap申請更多記憶體

具體參考:

使用Android Studio 的gradle 可以構建MutilDex

相信自己,沒有做不到的,只有想不到的

如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :232203809
微信公眾號:終端研發部

技術+職場
技術+職場