精選Android中高級面試題 -- 終局之篇:高級乾貨

碼個蛋(codeegg) 第 947 次推文

作者:Focusing

鏈接:https://juejin.im/post/5c984e926fb9a070c975a9b4

1、如何進行單元測試,如何保證App穩定 ?

參考回答:要測試Android應用程序,通常會創建以下類型自動單元測試:

  • 本地測試:只在本地機器JVM上運行,以最小化執行時間,這種單元測試不依賴於Android框架,或者即使有依賴,也很方便使用模擬框架來模擬依賴,以達到隔離Android依賴的目的,模擬框架如Google推薦的Mockito;

  • Android官網-建立本地單元測試(https://developer.android.com/training/testing/unit-testing/local-unit-tests.html)

  • 檢測測試:真機或模擬器上運行的單元測試,由於需要跑到設備上,比較慢,這些測試可以訪問儀器(Android系統)信息,比如被測應用程序的上下文,一般地,依賴不太方便通過模擬框架模擬時採用這種方式;

  • Android官網-建立儀表單元測試(https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests.html)

注意:單元測試不適合測試複雜的UI交互事件

推薦文章:Android 單元測試只看這一篇就夠了(https://juejin.im/post/5b57e3fbf265da0f47352618)

App的穩定主要決定於整體的系統架構設計,同時也不可忽略代碼編程的細節規範,正所謂“千里之堤,潰於蟻穴”,一旦考慮不周,看似無關緊要的代碼片段可能會帶來整體軟件系統的崩潰,所以上線之前除了自己本地化測試之外還需要進行Monkey壓力測試。

少部分面試官可能會延伸,如Gradle自動化測試、機型適配測試等

2、Android中如何查看一個對象的回收情況 ?

參考回答:首先要了解Java四種引用類型的場景和使用(強引用、軟引用、弱引用、虛引用)

舉個場景例子:SoftReference對象是用來保存軟引用的,但它同時也是一個Java對象,所以當軟引用對象被回收之後,雖然這個SoftReference對象的get方法返回,但SoftReference對象本身並不是,而此時這個SoftReference對象已經不再具有存在的價值,需要一個適當的清除機制,避免大量SoftReference對象帶來的內存洩露。

因此,Java提供ReferenceQueue來處理引用對象的回收情況。當SoftReference所引用的對象被GC後,JVM會先將softReference對象添加到ReferenceQueue這個隊列中。當我們調用ReferenceQueue的poll方法,如果這個隊列中不是空隊列,那麼將返回並移除前面添加的那個Reference對象。

精選Android中高級面試題 -- 終局之篇:高級乾貨

推薦文章:Java中的四種引用類型:強引用、軟引用、弱引用和虛引用(https://segmentfault.com/a/1190000015282652#articleHeader3)

3、Apk的大小如何壓縮 ?

參考回答:一個完整APK包含以下目錄(將APK文件拖到Android Studio):

  • META-INF/:包含CERT.SF和CERT.RSA簽名文件以及MANIFEST.MF 清單文件。

  • assets/:包含應用可以使用AssetManager對象檢索的應用資源。

  • res/:包含未編譯到的資源 resources.arsc。

  • lib/:包含特定於處理器軟件層的編譯代碼。該目錄包含了每種平臺的子目錄,像armeabi,armeabi-v7a, arm64-v8a,x86,x86_64,和mips。

  • resources.arsc:包含已編譯的資源。該文件包含res/values/ 文件夾所有配置中的XML內容。打包工具提取此XML內容,將其編譯為二進制格式,並將內容歸檔。此內容包括語言字符串和樣式,以及直接包含在**resources.arsc*8文件中的內容路徑 ,例如佈局文件和圖像。

  • classes.dex:包含以Dalvik / ART虛擬機可理解的DEX文件格式編譯的類。

  • AndroidManifest.xml:包含核心Android清單文件。該文件列出應用程序的名稱,版本,訪問權限和引用的庫文件。該文件使用Android的二進制XML格式。

精選Android中高級面試題 -- 終局之篇:高級乾貨
  • lib、class.dex和res佔用了超過90%的空間,所以這三塊是優化Apk大小的重點(實際情況不唯一)

減少res,壓縮圖文文件:圖片文件壓縮是針對jpg和png格式的圖片。我們通常會放置多套不同分辨率的圖片以適配不同的屏幕,這裡可以進行適當的刪減。在實際使用中,只保留一到兩套就足夠了(保留一套的話建議保留xxhdpi,兩套的話就加上hdpi),然後再對剩餘的圖片進行壓縮(jpg採用優圖壓縮,png嘗試採用pngquant壓縮)

減少dex文件大小

  • 添加資源混淆

精選Android中高級面試題 -- 終局之篇:高級乾貨
  • shrinkResources為true表示移除未引用資源,和代碼壓縮協同工作。

  • minifyEnabled為true表示通過ProGuard啟用代碼壓縮,配合proguardFiles的配置對代碼進行混淆並移除未使用的代碼。

  • 代碼混淆在壓縮apk的同時,也提升了安全性。

推薦文章:Android混淆最佳實踐(https://www.jianshu.com/p/cba8ca7fc36d)

減少lib文件大小:由於引用了很多第三方庫,lib文件夾佔用的空間通常都很大,特別是有so庫的情況下。很多so庫會同時引入armeabi、armeabi-v7a和x86這幾種類型,這裡可以只保留armeabi或armeabi-v7a的其中一個就可以了,實際上微信等主流app都是這麼做的。

只需在build.gradle直接配置即可,NDK配置同理

精選Android中高級面試題 -- 終局之篇:高級乾貨

推薦文章:APK瘦身(https://www.jianshu.com/p/5921e9561f5f)

4、如何通過Gradle配置多渠道包?

參考回答:首先要了解設置多渠道的原因。在安裝包中添加不同的標識,配合自動化埋點,應用在請求網絡的時候攜帶渠道信息,方便後臺做運營統計,比如說統計我們的應用在不同應用市場的下載量等信息

這裡以友盟統計為例:

  • 首先在manifest.xml文件中設置動態渠道變量:

精選Android中高級面試題 -- 終局之篇:高級乾貨
  • 接著在app目錄下的build.gradle中配置productFlavors,也就是配置打包的渠道:

精選Android中高級面試題 -- 終局之篇:高級乾貨

最後在編輯器下方的Teminal輸出命令行:

  • 執行./gradlew assembleRelease ,將會打出所有渠道的release包;

  • 執行./gradlew assembleVIVO,將會打出VIVO渠道的release和debug版的包;

  • 執行./gradlew assembleVIVORelease將生成VIVO的release包。

推薦文章:美團Android自動化之旅—Walle生成渠道包(https://github.com/Meituan-Dianping/walle)

5、插件化原理分析

參考回答:插件化是指將 APK 分為宿主和插件的部分。把需要實現的模塊或功能當做一個獨立的提取出來,在 APP 運行時,我們可以動態的載入或者替換插件部分,減少宿主的規模

  • 宿主: 就是當前運行的APP。

  • 插件: 相對於插件化技術來說,就是要加載運行的apk類文件。

而熱修復則是從修復bug的角度出發,強調的是在不需要二次安裝應用的前提下修復已知的bug。

精選Android中高級面試題 -- 終局之篇:高級乾貨

類加載機制:Android中常用的兩種類加載器,DexClassLoader和PathClassLoader,它們都繼承於BaseDexClassLoader,兩者區別在於PathClassLoader只能加載內部存儲目錄的dex/jar/apk文件。DexClassLoader支持加載指定目錄(不限於內部)的dex/jar/apk文件

插件通信:通過給插件apk生成相應的DexClassLoader便可以訪問其中的類,可分為單DexClassLoader和多DexClassLoader兩種結構。

  • 若使用多ClassLoader機制,主工程引用插件中類需要先通過插件的ClassLoader加載該類再通過反射調用其方法。插件化框架一般會通過統一的入口去管理對各個插件中類的訪問,並且做一定的限制。

  • 若使用單ClassLoader機制,主工程則可以直接通過類名去訪問插件中的類。該方式有個弊端,若兩個不同的插件工程引用了一個庫的不同版本,則程序可能會出錯。

資源加載:原理在於通過反射將插件apk的路徑加入AssetManager中並創建Resource對象加載資源,有兩種處理方式:

  • 合併式:addAssetPath時加入所有插件和主工程的路徑;由於AssetManager中加入了所有插件和主工程的路徑,因此生成的Resource可以同時訪問插件和主工程的資源。但是由於主工程和各個插件都是獨立編譯的,生成的資源id會存在相同的情況,在訪問時會產生資源衝突。

  • 獨立式:各個插件只添加自己apk路徑,各個插件的資源是互相隔離的,不過如果想要實現資源的共享,必須拿到對應的Resource對象。

推薦文章:

Android動態加載技術 簡單易懂的介紹方式(https://segmentfault.com/a/1190000004062866)

深入理解Android插件化技術(https://yq.aliyun.com/articles/361233)

為什麼要做熱更新(https://www.cnblogs.com/baiqiantao/p/9160806.html)

6、組件化原理

參考回答:引入組件化的原因:項目隨著需求的增加規模變得越來越大,規模的增大導致了各種業務錯中複雜的交織在一起, 每個業務模塊之間,代碼沒有約束,帶來了代碼邊界的模糊,代碼衝突時有發生, 更改一個小問題可能引起一些新的問題, 牽一髮而動全身,增加一個新需求,需要熟悉相關的代碼邏輯,增加開發時間

  • 避免重複造輪子,可以節省開發和維護的成本。

  • 可以通過組件和模塊為業務基準合理地安排人力,提高開發效率。

  • 不同的項目可以共用一個組件或模塊,確保整體技術方案的統一性。

  • 為未來插件化共用同一套底層模型做準備。

組件化開發流程就是把一個功能完整的App或模塊拆分成多個子模塊(Module),每個子模塊可以獨立編譯運行,也可以任意組合成另一個新的 App或模塊,每個模塊即不相互依賴但又可以相互交互,但是最終發佈的時候是將這些組件合併統一成一個apk,遇到某些特殊情況甚至可以升級或者降級

舉個簡單的模型例子:

精選Android中高級面試題 -- 終局之篇:高級乾貨
精選Android中高級面試題 -- 終局之篇:高級乾貨

App是主application,ModuleA和ModuleB是兩個業務模塊(相對獨立,互不影響),Library是基礎模塊,包含所有模塊需要的依賴庫,以及一些工具類:如網絡訪問、時間工具等。

注意:提供給各業務模塊的基礎組件,需要根據具體情況拆分成 aar 或者 library,像登錄,基礎網絡層這樣較為穩定的組件,一般直接打包成 aar,減少編譯耗時。而像自定義 View 組件,由於隨著版本迭代會有較多變化,就直接以源碼形式抽離成 Library

推薦文章:乾貨 | 從智行 Android 項目看組件化架構實踐(https://mp.weixin.qq.com/s?__biz=MjM5MDI3MjA5MQ==&mid=2697268363&idx=1&sn=3db2dce36a912936961c671dd1f71c78)

7、跨組件通信

跨組件通信場景

  • 第一種是組件之間的頁面跳轉 (Activity 到 Activity, Fragment 到 Fragment, Activity 到 Fragment, Fragment 到 Activity) 以及跳轉時的數據傳遞 (基礎數據類型和可序列化的自定義類類型)。

  • 第二種是組件之間的自定義類和自定義方法的調用(組件向外提供服務)。

跨組件通信方案分析:第一種組件之間的頁面跳轉實現簡單,跳轉時想傳遞不同類型的數據提供有相應的 API即可。

第二種組件之間的自定義類和自定義方法的調用要稍微複雜點,需要 ARouter 配合架構中的 公共服務(CommonService) 實現:

  • 提供服務的業務模塊:

  • 在公共服務(CommonService) 中聲明 Service 接口 (含有需要被調用的自定義方法), 然後在自己的模塊中實現這個 Service 接口, 再通過 ARouter API 暴露實現類。

  • 使用服務的業務模塊:通過 ARouter 的 API 拿到這個 Service 接口(多態持有, 實際持有實現類), 即可調用 Service 接口中聲明的自定義方法, 這樣就可以達到模塊之間的交互。

  • 此外,可以使用 AndroidEventBus 其獨有的 Tag, 可以在開發時更容易定位發送事件和接受事件的代碼, 如果以組件名來作為 Tag 的前綴進行分組, 也可以更好的統一管理和查看每個組件的事件, 當然也不建議大家過多使用 EventBus。

如何管理過多的路由表?

  • RouterHub 存在於基礎庫, 可以被看作是所有組件都需要遵守的通訊協議, 裡面不僅可以放路由地址常量, 還可以放跨組件傳遞數據時命名的各種 Key 值, 再配以適當註釋, 任何組件開發人員不需要事先溝通只要依賴了這個協議, 就知道了各自該怎樣協同工作, 既提高了效率又降低了出錯風險, 約定的東西自然要比口頭上說強。

  • Tips: 如果您覺得把每個路由地址都寫在基礎庫的 RouterHub 中, 太麻煩了, 也可以在每個組件內部建立一個私有 RouterHub, 將不需要跨組件的路由地址放入私有 RouterHub 中管理, 只將需要跨組件的路由地址放入基礎庫的公有 RouterHub 中管理, 如果您不需要集中管理所有路由地址的話, 這也是比較推薦的一種方式。

ARouter路由原理:ARouter維護了一個路由表Warehouse,其中保存著全部的模塊跳轉關係,ARouter路由跳轉實際上還是調用了startActivity的跳轉,使用了原生的Framework機制,只是通過apt註解的形式製造出跳轉規則,並人為地攔截跳轉和設置跳轉條件。

常見的組件化方案如下:

精選Android中高級面試題 -- 終局之篇:高級乾貨

8、組件化中路由、埋點的實現

參考回答:因為在組件化中,各個業務模塊之間是各自獨立的, 並不會存在相互依賴的關係, 所以一個業務模塊是訪問不了其他業務模塊的代碼的, 如果想從 A 業務模塊的 A 頁面跳轉到 B 業務模塊的 B 頁面, 光靠模塊自身是不能實現的,這就需要一種跨組件通信方案—— 路由(Router)

路由主要有以下兩種場景:

  • 第一種是組件之間的頁面跳轉 (Activity 到 Activity, Fragment 到 Fragment, Activity 到 Fragment, Fragment 到 Activity) 以及跳轉時的數據傳遞 (基礎數據類型和可序列化的自定義類類型)

  • 第二種是組件之間的自定義類和自定義方法的調用(組件向外提供服務)

其原理在於將分佈在不同組件module中的某些類按照一定規則生成映射表(數據結構通常是Map,Key為一個字符串,Value為類或對象),然後在需要用到的時候從映射表中根據字符串從映射表中取出類或對象,本質上是類的查找。

精選Android中高級面試題 -- 終局之篇:高級乾貨

埋點則是在應用中特定的流程收集一些信息,用來跟蹤應用使用的狀況:

  • 代碼埋點:在某個事件發生時調用SDK裡面相應的接口發送埋點數據,百度統計、友盟、TalkingData、Sensors Analytics等第三方數據統計服務商大都採用這種方案

  • 全埋點:全埋點指的是將Web頁面/App內產生的所有的、滿足某個條件的行為,全部上報到後臺服務器

  • 可視化埋點:通過可視化工具(例如Mixpanel)配置採集節點,在Android端自動解析配置並上報埋點數據,從而實現所謂的自動埋點

  • 無埋點:它並不是真正的不需要埋點,而是Android端自動採集全部事件並上報埋點數據,在後端數據計算時過濾出有用數據

推薦文章:安卓組件化開源方案實現(https://juejin.im/post/5a7ab8846fb9a0634514a2f5)

9、Hook以及插樁技術

參考回答:Hook是一種用於改變API執行結果的技術,能夠將系統的API函數執行重定向(應用的觸發事件和後臺邏輯處理是根據事件流程一步步地向下執行。而Hook的意思,就是在事件傳送到終點前截獲並監控事件的傳輸,像個鉤子鉤上事件一樣,並且能夠在鉤上事件時,處理一些自己特定的事件,例如逆向破解App)

精選Android中高級面試題 -- 終局之篇:高級乾貨

Android 中的 Hook 機制,大致有兩個方式:

  • 要 root 權限,直接 Hook 系統,可以幹掉所有的 App。

  • 無 root 權限,但是隻能 Hook 自身app,對系統其它 App 無能為力。

插樁是以靜態的方式修改第三方的代碼,也就是從編譯階段,對源代碼(中間代碼)進行編譯,而後重新打包,是靜態的篡改; 而Hook則不需要再編譯階段修改第三方的源碼或中間代碼,是在運行時通過反射的方式修改調用,是一種動態的篡改

推薦文章:

Android插件化原理解析——Hook機制之動態代理(http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/)

android 插樁基本概念(https://blog.csdn.net/fei20121106/article/details/51879047)

Android逆向之旅(http://www.520monkey.com/)

10、Android的簽名機制?

參考回答:Android的簽名機制包含有消息摘要、數字簽名和數字證書

  • 消息摘要:在消息數據上,執行一個單向的 Hash 函數,生成一個固定長度的Hash值

  • 數字簽名:一種以電子形式存儲消息簽名的方法,一個完整的數字簽名方案應該由兩部分組成:簽名算法和驗證算法

  • 數字證書:一個經證書授權(Certificate Authentication)中心數字簽名的包含公鑰擁有者信息以及公鑰的文件

推薦文章:一篇文章看明白 Android v1 & v2 簽名機制(https://blog.csdn.net/freekiteyu/article/details/84849651)

11、v3簽名key和v2還有v1有什麼區別

參考回答:在v1版本的簽名中,簽名以文件的形式存在於apk包中,這個版本的apk包就是一個標準的zip包,V2和V1的差別是V2是對整個zip包進行簽名,而且在zip包中增加了一個apk signature block,裡面保存簽名信息。

精選Android中高級面試題 -- 終局之篇:高級乾貨

v2版本簽名塊(APK Signing Block)本身又主要分成三部分:

  • SignerData(簽名者數據):主要包括簽名者的證書,整個APK完整性校驗hash,以及一些必要信息

  • Signature(簽名):開發者對SignerData部分數據的簽名數據

  • PublicKey(公鑰):用於驗籤的公鑰數據

v3版本簽名塊也分成同樣的三部分,與v2不同的是在SignerData部分,v3新增了attr塊,其中是由更小的level塊組成。每個level塊中可以存儲一個證書信息。前一個level塊證書驗證下一個level證書,以此類推。最後一個level塊的證書,要符合SignerData中本身的證書,即用來簽名整個APK的公鑰所屬於的證書

精選Android中高級面試題 -- 終局之篇:高級乾貨

推薦文章:

APK 簽名方案 v3(https://source.android.google.cn/security/apksigning/v3)

Android P v3簽名新特性(https://xuanxuanblingbling.github.io/ctf/android/2018/12/30/signature/)

12、Android5.0~10.0之間大的變化

Android 5.0新特性:

  • MaterialDesign設計風格

  • 支持64位ART虛擬機(5.0推出的ART虛擬機,在5.0之前都是Dalvik。他們的區別是:Dalvik,每次運行,字節碼都需要通過即時編譯器轉換成機器碼(JIT)。ART,第一次安裝應用的時候,字節碼就會預先編譯成機器碼(AOT))

  • 通知詳情可以用戶自己設計

Android 6.0新特性

  • 動態權限管理

  • 支持快速充電的切換

  • 支持文件夾拖拽應用

  • 相機新增專業模式

Android 7.0新特性

  • 多窗口支持

  • V2簽名

  • 增強的Java8語言模式

  • 夜間模式

Android 8.0(O)新特性

  • 優化通知:通知渠道 (Notification Channel) 通知標誌 休眠 通知超時 通知設置 通知清除

  • 畫中畫模式:清單中Activity設置android:supportsPictureInPicture

  • 後臺限制

  • 自動填充框架

  • 系統優化等等優化很多

Android 9.0(P)新特性

  • 室內WIFI定位

  • “劉海”屏幕支持

  • 安全增強等等優化很多

Android 10.0(Q)新特性

  • 夜間模式:包括手機上的所有應用都可以為其設置暗黑模式。

  • 桌面模式:提供類似於PC的體驗,但是遠遠不能代替PC。

  • 屏幕錄製:通過長按“電源”菜單中的"屏幕快照"來開啟。

推薦文章:Android Developers 官方文檔(https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels)

13、說下Measurepec這個類

參考回答:作用:通過寬測量值widthMeasureSpec和高測量值heightMeasureSpec決定View的大小

組成:一個32位int值,高2位代表SpecMode(測量模式),低30位代表SpecSize( 某種測量模式下的規格大小)。

三種模式:

  • UNSPECIFIED:父容器不對View有任何限制,要多大有多大。常用於系統內部。

  • EXACTLY(精確模式):父視圖為子視圖指定一個確切的尺寸SpecSize。對應LyaoutParams中的match_parent或具體數值。

  • AT_MOST(最大模式):父容器為子視圖指定一個最大尺寸SpecSize,View的大小不能大於這個值。對應LayoutParams中的wrap_content。

決定因素:值由子View的佈局參數LayoutParams和父容器的MeasureSpec值共同決定。具體規則見下圖:

精選Android中高級面試題 -- 終局之篇:高級乾貨

14、請例舉Android中常用佈局類型,

並簡述其用法以及排版效率

參考回答:Android中常用佈局分為傳統佈局和新型佈局

傳統佈局(編寫XML代碼、代碼生成):

  • 框架佈局(FrameLayout):

  • 線性佈局(LinearLayout):

  • 絕對佈局(AbsoluteLayout):

  • 相對佈局(RelativeLayout):

  • 表格佈局(TableLayout):

新型佈局(可視化拖拽控件、編寫XML代碼、代碼生成):約束佈局(ConstrainLayout):

精選Android中高級面試題 -- 終局之篇:高級乾貨

注:圖片出自Carson_Ho的Android:常用佈局介紹&屬性設置大全(https://blog.csdn.net/carson_ho/article/details/51719519)

對於嵌套多層View而言,其排版效率:LinearLayout = FrameLayout >> RelativeLayout

15、區別Animation和Animator的用法,概述其原理

動畫的種類:前者只有透明度,旋轉,平移,伸縮4種屬性,而對於後者,只要是該控件的屬性,且有setter該屬性的方法就都可以對該屬性執行一種動態變化的效果。

可操作的對象:前者只能對UI組件執行動畫,但屬性動畫幾乎可以對任何對象執行動畫(不管它是否顯示在屏幕上)。

動畫播放順序:在Animator中,AnimatorSet正是通過playTogether、playSequentially、animSet.play.with、before、after這些方法來控制多個動畫協同工作,從而做到對動畫播放順序的精確控制

精選Android中高級面試題 -- 終局之篇:高級乾貨

16、使用過什麼圖片加載庫?

Glide的源碼設計哪裡很微妙?

參考回答:圖片加載庫:Fresco、Glide、Picasso等

Glide的設計微妙在於:

  • Glide的生命週期綁定:可以控制圖片的加載狀態與當前頁面的生命週期同步,使整個加載過程隨著頁面的狀態而啟動/恢復,停止,銷燬

  • Glide的緩存設計:通過(三級緩存,Lru算法,Bitmap複用)對Resource進行緩存設計

  • Glide的完整加載過程:採用Engine引擎類暴露了一系列方法供Request操作

17、如何繞過9.0限制?

參考回答:

精選Android中高級面試題 -- 終局之篇:高級乾貨

18、用過哪些網絡加載庫?

OkHttp、Retrofit實現原理?

參考回答:網絡加載庫:OkHttp、Retrofit、xUtils、Volley等

Android OkHttp源碼解析入門教程(一)(https://juejin.im/post/5c46822c6fb9a049ea394510)

Android OkHttp源碼解析入門教程(二)(https://juejin.im/post/5c4682d2f265da6130752a1d)

19、對於應用更新這塊是如何做的?

(灰度,強制更新、分區域更新)

內部更新

  • 通過接口獲取線上版本號,versionCode

  • 比較線上的versionCode 和本地的versionCode,彈出更新窗口

  • 下載APK文件(文件下載)

  • 安裝APK

灰度更新

  • 找單一渠道投放特別版本。

  • 做升級平臺的改造,允許針對部分用戶推送升級通知甚至版本強制升級。

  • 開放單獨的下載入口。

  • 是兩個版本的代碼都打到app包裡,然後在app端植入測試框架,用來控制顯示哪個版本。測試框架負責與服務器端api通信,由服務器端控制app上A/B版本的分佈,可以實現指定的一組用戶看到A版本,其它用戶看到B版本。服務端會有相應的報表來顯示A/B版本的數量和效果對比。最後可以由服務端的後臺來控制,全部用戶在線切換到A或者B版本~

  • 無論哪種方法都需要做好版本管理工作,分配特別的版本號以示區別。 當然,既然是做灰度,數據監控(常規數據、新特性數據、主要業務數據)還是要做到位,該打的數據樁要打。 還有,灰度版最好有收回的能力,一般就是強制升級下一個正式版。

強制更新:一般的處理就是進入應用就彈窗通知用戶有版本更新,彈窗可以沒有取消按鈕並不能取消。這樣用戶就只能選擇更新或者關閉應用了,當然也可以添加取消按鈕,但是如果用戶選擇取消則直接退出應用。

增量更新:二進制差分工具bsdiff是相應的補丁合成工具,根據兩個不同版本的二進制文件,生成補丁文件.patch文件。通過bspatch使舊的apk文件與不定文件合成新的apk。 注意通過apk文件的md5值進行區分版本。

20、會用Kotlin、Fultter嗎? 談談你的理解

  • Kotlin是一種具有類型推斷的跨平臺,靜態類型的通用編程語言。Kotlin旨在與Java完全互操作,其標準庫的JVM版本依賴於Java類庫,但類型推斷允許其語法更簡潔。

  • Flutter是由Google創建的開源移動應用程序開發框架。它用於開發Android和iOS的應用程序,以及為Google Fuchsia創建應用程序的主要方法

  • 關於kotlin的重要性,相信大家在日常開發可以體會到,應用到實際開發中,需要避免語法糖(例如單列模式、空值判斷、高階函數等)

  • 至於Flutter,目前Google官方文檔還不完善,市面上採用此語言編寫的項目較少,如需要具體深入,請參考閒魚和官方文檔

  • 精選Android中高級面試題 (四):性能優化,JNI,設計模式

  • 原創:討好女朋友的6大技巧

  • 深入探索 Android 包瘦身(中)

面試題給大家已經分享很多了,大家還想學什麼知識?碼仔安排


分享到:


相關文章: