您好,登錄后才能下訂單哦!
回想起前年左右,自己去社招的時候,一連串下來問了好多現在都是歷歷在目。回想起以前才覺得紙上得來終覺淺,絕知此事要躬行
所有的面試題答案并不是百分百的標準,要靠你自己的感悟和有自己的想法,才能獨樹一幟脫穎而出的。所有僅供參考
所有的都在這個PDF中有所匯總,983頁花了幾十個小時整理出來的。還是比較全面的有Android,Java小知識,到性能優化.線程.View.OpenCV.NDK.大廠面試,算法等等,大家可以聯系我看看對自身有沒有用
(更多完整項目下載。未完待續。源碼。圖文知識后續上傳github。)
可以聯系我獲取完整PDF
(VX:mm14525201314)
Mockito;
注意: 單元測試不適合測試復雜的 UI 交互事件
Gradle
自動化測試、機型適配測試等
首先要了解 Java 四種引用類型的場景和使用(強引用、軟引用、弱引用、虛引用)
SoftReference
對象是用來保存軟引用的,但它同時也是一個 Java 對象,所以當軟引用對象被回收之后,雖然這個 SoftReference
對象的 get 方法返回null,但 SoftReference
對象本身并不是 null,而此時這個 SoftReference
對象已經不再具有存在的價值,需要一個適當的清除機制,避免大量SoftReference
對象帶來的內存泄露因此,Java 提供 ReferenceQueue
來處理引用對象的回收情況。當 SoftReference
所引用的對象被 GC 后,JVM 會先將 softReference
對象添加到ReferenceQueue
這個隊列中。當我們調用 ReferenceQueue
的 的 poll() 方法,如果這個隊列中不是空隊列,那么將返回并移除前面添加的那個Reference
對象
public static void main(String[] args) throws InterruptedException {
//假設當前JVM內存只有8m
Person person = new Person( "/K=" );
ReferenceQueue Person> queue = new ReferenceQueue>( );
Sof tReference Person> softReference = new SoftReference<Person>(person, queue );
реr?оn = null;// 去掉強引用, new Person ( "/K=" );的這個對象只有軟引用了
Person anotherPerson = new Person( "/L=" )//沒有足夠的空間同事保留兩個Person對象,所以觸發GC機制
Thread.sleep(1000);
Sys tem. err . println( "軟引用的對象 ------" > softReference.get( ));
Reference softPollRef = queue . poll( );
if (softPollRef != null) f
System.err.println( " SoftReference對象中保存的軟引用對象已經被GC,準備清理SoftReference對象");
//清理softReference
}
}
CERT.SF
和 CERT.RSA
簽名文件以及 MANIFEST.MF
清單文件。AssetManager
對象檢索的應用資源。resources.arsc
。armeabi
armeabi-v7a
, arm64-v8a
, x86
, x86_64
,和mips
。resources.arsc
: 包含已編譯的資源。該文件包含res/values/ 文件夾所有配置中的 XML 內容。打包工具提取此 XML 內容,將其編譯為二進制格式,并將內容歸檔。此內容包括語言字符串和樣式,以及直接包含在resources.arsc8
文件中的內容路徑 ,例如布局文件和圖像。Dalvik / ART
虛擬機可理解的X DEX 文件格式編譯的類。AndroidManifest.xml
: 包含核心 Android 清單文件。該文件列出應用程序的名稱,版本,訪問權限和引用的庫文件.該文件使用 Android 的二進制XML 格式。lib
、class.dex
和 res 占用了超過 90%的空間,所以這三塊是優化 Apk
大小的重點(實際情況不唯一)圖片文件壓縮是針對 jpg
和 png
格式的圖片。我們通常會放置多套不同分辨率的圖片以適配不同的屏幕,這里可以進行適當的刪減。在實際使用中,只保留一到兩套就足夠了(保留一套的話建議保留xxhdpi
,兩套的話就加上 hdpi
),然后再對剩余的圖片進行壓縮(jpg
采用優圖壓縮,png
嘗試采用pngquant
壓縮)
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile("proguard-android. txt"),’proguard-rules.pro’
}
}
shrinkResources
為 true 表示移除未引用資源,和代碼壓縮協同工作。minifyEnabled
為 true 表示通過 ProGuard
啟用代碼壓縮,配合 proguardFiles
的配置對代碼進行混淆并移除未使用的代碼。apk
的同時,也提升了安全性。
armeabi
、armeabi-v7a
和 x86
這幾種類型,這里可以只保留 armeabi
或 armeabi-v7a
的其中一個就可以了,實際上微信等主流 app 都是這么做的。build.gradle
直接配置即可,NDK
配置同理
defaultConfig {
ndk {
abiFilters 'armeabi'
}
}
插件化是指將 APK
分為 宿主和 插件的部分。把需要實現的模塊或功能當做一個獨立的提取出來,在 APP 運行時,我們可以動態的 載入或者 替換插件部分,減少 宿主的規模
而 熱修復則是從修復 bug 的角度出發,強調的是在不需要二次安裝應用的前提下修復已知的 bug。
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
對象。
引入組件化的原因: 項目隨著需求的增加規模變得越來越大,規模的增大導致了各種業務錯中復雜的交織在一起,每個業務模塊之間,代碼沒有約束,帶來了代碼邊界的模糊,代碼沖突時有發生, 更改一個小問題可能引起一些新的問題, 牽一發而動全身,增加一個新需求,需要熟悉相關的代碼邏輯,增加開發時間
組件化開發流程就是把一個功能完整的 App 或模塊拆分成多個子模塊( Module ),每個子模塊可以 獨立編譯運行,也可以任意組合成另一個新的 App 或模塊,每個模塊即不相互依賴但又可以相互交互,但是最終發布的時候是將這些組件合并統一成一個 apk,遇到某些特殊情況甚至可以升級或者
ARouter
配合架構中的 公共服務(CommonService
) 實現:
CommonService
) 中聲明 Service
接口 (含有需要被調用的自定義方法), 然后在自己的模塊中實現這個 Service 接口, 再通過 ARouter API
暴露實現類。ARouter
的 API 拿到這個Service
接口(多態持有, 實際持有實現類), 即可調用 Service
接口中聲明的自定義方法, 這樣就可以達到模塊之間的交互。AndroidEventBus
其獨有的Tag, 可以在開發時更容易定位發送事件和接受事件的代碼, 如果以組件名來作為 Tag 的前綴進行分組, 也可以更好的統一管理和查看每個組件的事件, 當然也不建議大家過多使用 EventBus
。RouterHub
存在于基礎庫, 可以被看作是所有組件都需要遵守的通訊協議, 里面不僅可以放路由地址常量, 還可以放跨組件傳遞數據時命名的各種 Key 值,再配以適當注釋, 任何組件開發人員不需要事先溝通只要依賴了這個協議, 就知道了各自該怎樣協同工作, 既提高了效率又降低了出錯風險, 約定的東西自然要比口頭上說強。RouterHub
中, 太麻煩了, 也可以在每個組件內部建立一個私有 RouterHub
, 將不需要跨組件的路由地址放入私有 RouterHub
中管理, 只將需要跨組件的路由地址放入基礎庫的公有 RouterHub
中管理, 如果您不需要集中管理所有路由地址的話, 這也是比較推薦的一種方式。
ARouter
路由原理:ARouter
維護了一個路由表 Warehouse,其中保存著全部的模塊跳轉關系,ARouter
路由跳轉實際上還是調用了 startActivity
的跳轉,使用了原生的Framework 機制,只是通過 apt 注解的形式制造出跳轉規則,并人為地攔截跳轉和設置跳轉條件
Hook 是一種用于 改變 API執行結果的技術,能夠將系統的API 函數執行 重定向(應用的 觸發事件和 后臺邏輯處理是根據事件流程一步步地向下執行。而 Hook 的意思,就是在事件傳送到終點前截獲并監控事件的傳輸,像個鉤子鉤上事件一樣,并且能夠在鉤上事件時,處理一些自己特定的事件,例如逆向破解 App)
插樁是以靜態的方式修改第三方的代碼,也就是從編譯階段,對源代碼(中間代碼)進行編譯,而后重新打包,是靜態的篡改; 而 Hook則不需要再編譯階段修改第三方的源碼或中間代碼,是在運行時通過反射的方式修改調用,是一種 動態的篡改
作用: 通過寬測量值 widthMeasureSpec
和高測量值heightMeasureSpec
決定 View 的大小
組成: 一個 32 位 int 值,高 2 位代表 SpecMode
(測量模式),低 30 位代表 SpecSize( 某種測量模式下的規格大小)。
三種模式:
SpecSize
。對應 LyaoutParams
中的match_parent 或具體數值。SpecSize
,View 的大小不能大于這個值。對應LayoutParams
中的 wrap_content。圖片加載庫:Fresco 丶Glide 、o Picasso 等
AnimatorSet
正是通過playTogether()
、playSequentially()
、animSet.play().with()
、before()
、after()
這些方法來控制多個動畫協同工作,從而做到對動畫播放順序的精確控制// animation主要用于tween動畫
//根據資源得到動畫
Animation roitateAnimation = AnimationUtils.loadAnimation(this,R.anim.rotata_anim);
//播放動畫完成之后,保留動畫最后的狀態
rotateAnimation.setFillAfter(true);
//播放動畫
btnRotate.startAnimation(rotateAnimation);
// animator主要用于屬性動畫
objectAnimator animator = objectanimator.ofFloat(textview,"alpha,1f,0f,1f);
animator.setDuration(5000);
animator,start();
AnimatorSet animatorSet = new AnimatorSet();
//移動
objectAnimator ty = object Animator.ofFloat(btn,"translationY",0,300);
ty.setDuration(1000);
//旋轉
objectAnimator ty = objectAnimator.ofFloat(btn, "rotationY", 0,1080);
//透明度
objectAnimator alpha = objectAnimator.ofFloat(btn, "alpha", 1,0,0.5f,1);
//縮放
objectAnimator sx = objectAnimator.ofFloat(btn, "scaleX",1,0.5f);
//一起播放
// animatorSet.playTogether(items);
animatorSet.play(ry),with(sx).after(ty).before(alpha);
animatorSet.start();
請查看完整的PDF版
(更多完整項目下載。未完待續。源碼。圖文知識后續上傳github。)
可以聯系我獲取完整PDF
(VX:mm14525201314)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。