本系列出于AWeiLoveAndroid的分享,在此感謝,再結(jié)合自身經(jīng)驗查漏補缺,完善答案。以成系統(tǒng)。
圖片
- 圖片庫對比,1280*720的圖片占用內(nèi)存情況
圖片占用內(nèi)存.jpeg
- ImageLoader原理+源碼
- LruCache基于LruCache原理,但是是自己實現(xiàn)的默認為LruMemoryCache
http://www.itdecent.cn/p/980d0df2faae
ImagerLoader原理圖
ImagerLoader源碼圖
- Picasso基本使用與源碼解析
- Glide源碼/原理解析(用的什么緩存,如何控制緩存大小)
- Picasso 與 Glide比較?
https://blog.csdn.net/abrazen_zz/article/details/52562153
Glide ARGB565 Picasso ARGB8888
Glide 之加載ImageView大小的 Picasso 加載整張
Glide asGif Picasso 沒有gif功能
Glide 源碼 > Picasso
Glide 是純HttpUrlConnection Picasso 如果有Okhttp會用Okhttp
- 自己實現(xiàn)圖片庫思路
接口-加載 顯示
加載 內(nèi)存--本地--網(wǎng)絡--本地--內(nèi)存
顯示 顯示規(guī)則,是否壓縮 顯示后回收
android 滾動 拖拽
- 手寫ScrollView/ScrollView源碼分析
- ViewDragHelper
- Material design
網(wǎng)絡和安全機制
- 網(wǎng)絡框架對比和源碼分析
- 自己去設計網(wǎng)絡請求框架,怎么做?
網(wǎng)絡引擎+自由切換網(wǎng)絡請求框架
- 從網(wǎng)絡加載一個10M的圖片,說下注意事項
oom
- 六大設計原則
http://www.cnblogs.com/dolphin0520/p/3919839.html
單一職責,開閉,理式替換,依賴倒置,接口隔離,迪米特法則
- 設計模式
- TCP的3次握手和四次揮手
- TCP與UDP的區(qū)別與應用
- HTTP協(xié)議
https://www.cnblogs.com/ranyonsue/p/5984001.html
報文格式.jpeg
- HTTP1.0 1. 2.0 Https
http://www.itdecent.cn/p/52d86558ca57
1.1 長連接,多站點,斷電續(xù)傳,
- HTTP與HTTPS的區(qū)別以及如何實現(xiàn)安全性
image
- 如何驗證證書的合法性?
- https中哪里用了對稱加密,哪里用了非對稱加密,對加密算法(如RSA)等是否有了解?
client如何確定自己發(fā)送的消息被server收到?
談談你對WebSocket的理解
是HTML5一種新的協(xié)議。它實現(xiàn)了瀏覽器與服務器全雙工通信
- WebSocket與socket的區(qū)別
https://blog.csdn.net/wwd0501/article/details/54582912
Socket其實并不是一個協(xié)議,而是為了方便使用TCP或UDP而抽象出來的一層,是位于應用層和傳輸控制層之間的一組接口。
WebSocket
談談你對安卓簽名的理解。
請解釋安卓為啥要加簽名機制?
1.防止惡意替換
2.系統(tǒng)強制要求
視頻加密傳輸
App 是如何沙箱化,為什么要這么做?
- 權限管理系統(tǒng)(底層的權限是如何進行 grant 的)?
https://blog.csdn.net/gan303/article/details/50669035
https://blog.csdn.net/zy00000000001/article/details/51956883
安裝應用啟動應用會解析apk(parsePackage),這時候會解析清單配置文件中的<uses-permission>標簽,解析完后會調(diào)用updatePermissionsLPw進行權限設定,然后進行grantPermissionsLPw授權,授權的本質(zhì)是為應用程序授予權限名對應的組id,擁有組id的應用就擁有了相應的權限。
數(shù)據(jù)庫
- sqlite升級,增加字段的語句
/**
* 方法1:檢查某表列是否存在
* @param db
* @param tableName 表名
* @param columnName 列名
* @return
*/
private static boolean checkColumnExist1(SQLiteDatabase db, String tableName
, String columnName) {
boolean result = false ;
Cursor cursor = null ;
try{
//查詢一行
cursor = db.rawQuery( "SELECT * FROM " + tableName + " LIMIT 0", null );
result = cursor != null && cursor.getColumnIndex(columnName) != -1 ;
}catch (Exception e){
LogUtil.logErrorMessage("checkColumnExists1..." + e.getMessage());
}finally{
if(null != cursor && !cursor.isClosed()){
cursor.close() ;
}
}
return result ;
}
//如果不存在再執(zhí)行修改表的語句
alert table ‘tableName’ add ‘clumName’ clumType
- 數(shù)據(jù)庫框架對比和源碼分析
- 數(shù)據(jù)庫的優(yōu)化
https://blog.csdn.net/u014608640/article/details/52511310
索引 事務 單線程池 其它(StringBulider,記錄cloumIndex,少字段查詢)
- 數(shù)據(jù)庫數(shù)據(jù)遷移問題
https://blog.csdn.net/it_talk/article/details/47124645
利用事務的原子特性,保證所有的SQL能全部執(zhí)行完成。主要思路是:首先將原來的表進行改名稱rename table(臨時表),接著創(chuàng)建新的表create table,再者將舊表內(nèi)的數(shù)據(jù)遷移到新表內(nèi),最后drop table刪除臨時表。
算法
- 排序算法有哪些?
- 最快的排序算法是哪個?
平均時間復雜度是快速排序最快
- 手寫一個冒泡排序
private static void bubleSort(int[] a){
int n = a.length;
int j,k;
int flag = n;//記錄最后交換的位置
while (flag > 0){//排序未結(jié)束標志
k = flag;// 來記錄遍歷的尾界
flag = 0;
for(j=1;j<k;j++){
if(a[j-1] > a[j]){
//交換
int temp;
temp = a[j -1];
a[j-1] = a[j];
a[j] = temp;
flag = j;
}
}
}
}
- 手寫快速排序代碼
//算出中軸
private static int partition(int[] num,int left,int right){
if(num==null || num.length<=0 || left<0 || right>=num.length){
return 0;
}
int prio=num[left]; //獲取數(shù)組中間元素的下標
while (left<right){ //從兩端交替向中間掃描
//從右往左掃
while (left<right && num[right]>=prio)
right--;
swap(num,left,right);
//從左往右掃
while (left<right && num[left]<=prio)
left++;
swap(num,left,right);
}
return left;
}
//交換
private static void swap(int[] num,int left,int right){
int temp = num[left];
num[left] = num[right];
num[right] = temp;
}
//快速排序
private static void sort(int num[],int left,int right){
if (left<right){
int index=partition(num,left,right); //算出樞軸值
sort(num,left,index-1); //對低子表遞歸排序
sort(num,index+1,right); //對高子表遞歸排序
}
}
- 快速排序的過程、時間復雜度、空間復雜度
- 二分查找
手寫堆排序
堆排序過程、時間復雜度及空間復雜度
寫出你所知道的排序算法及時空復雜度,穩(wěn)定性
二叉樹給出根節(jié)點和目標節(jié)點,找出從根節(jié)點到目標節(jié)點的路徑
給阿里2萬多名員工按年齡排序應該選擇哪個算法?
GC算法(各種算法的優(yōu)缺點以及應用場景)
蟻群算法與蒙特卡洛算法
子串包含問題(KMP 算法)寫代碼實現(xiàn)
一個無序,不重復數(shù)組,輸出N個元素,使得N個元素的和相加為M,給出時間復雜度、空間復雜度。手寫算法
萬億級別的兩個URL文件A和B,如何求出A和B的差集C(提示:Bit映射->hash分組->多文件讀寫效率->磁盤尋址以及應用層面對尋址的優(yōu)化)
百度POI中如何試下查找最近的商家功能(提示:坐標鏡像+R樹)。
兩個不重復的數(shù)組集合中,求共同的元素。
兩個不重復的數(shù)組集合中,這兩個集合都是海量數(shù)據(jù),內(nèi)存中放不下,怎么求共同的元素?
一個文件中有100萬個整數(shù),由空格分開,在程序中判斷用戶輸入的整數(shù)是否在此文件中。說出最優(yōu)的方法
一張Bitmap所占內(nèi)存以及內(nèi)存占用的計算
2000萬個整數(shù),找出第五十大的數(shù)字?
燒一根不均勻的繩,從頭燒到尾總共需要1個小時?,F(xiàn)在有若干條材質(zhì)相同的繩子,問如何用燒繩的方法來計時一個小時十五分鐘呢?
求1000以內(nèi)的水仙花數(shù)以及40億以內(nèi)的水仙花數(shù)
5枚硬幣,2正3反如何劃分為兩堆然后通過翻轉(zhuǎn)讓兩堆中正面向上的硬8幣和反面向上的硬幣個數(shù)相同
時針走一圈,時針分針重合幾次
N*N的方格紙,里面有多少個正方形
x個蘋果,一天只能吃一個、兩個、或者三個,問多少天可以吃完?
插件化、模塊化、組件化、熱修復、增量更新、Gradle
- 對插件化的理解
https://blog.csdn.net/jiangwei0910410003/article/details/48104581
- 在android的Dalivk的definClass方法被閹割
- DexClassLoader 和 PathClassLoader都是雙親委派模型的本質(zhì)是沒有重寫loadclass方法,里面有這么一行
clazz = parent.loadClass(className, false);- 動態(tài)加載的本質(zhì)是使用DexClassLoader和PathClassLoader的loadClass方法進行加載。兩者的區(qū)別是構造函數(shù)所體現(xiàn)的,DexCLassLoader能將源路徑文件(可能是apk,jar,zip)進行解壓得到dex文件,然后進行進行加載,而PathClassLoader只能直接通過dex文件進行加載,在android中默認的是PathClassLoader,因為apk在安裝后會自動解壓出我們要用的dex文件存放在/data/dalvik-cache中。
插件化一般由三個工程 插件接口工程,插件工程和宿主工程。這三的關系如下圖
image
這里要注意一點就是宿主工程通過libs的方式集成接口工程,而插件工程一定不能通過libs的方式集成接口工程
- 資源的動態(tài)加載,關鍵是反射操控AssetManager的addAssetPath將資源的路徑改為插件的,然后用這個AssetManager對象去創(chuàng)建自己的Resources對象,我們代碼中就是用這個自己的Resources對象去加載資源。
- Activity的動態(tài)加載,一個重要的問題是保證能正常走生命周期,主要有三種種思路
a. 通過反射得到ActivityThread中的mPackages,然后通過mPackages得到應用的LoadApk對象,然后將LoadApk對象中的mClassLoader對象替換成我們自己定義的關聯(lián)了系統(tǒng)PathClassLoader的且加載了插件的DexClassLoader對象。但是這種方式必須要預先在清單配置文件中生命好要加載的插件中的Activity。
b. 通過反射去將DexClassLoader中的class合并到應用PathClassLoader中的elements數(shù)組中
b. 靜態(tài)代理的方式,應用中提供一個ProxActivity,插件工程中提供一個只有生命周期殼子的Activity,這個Activity持有一個我們的代理Activity,在代理Activity通過反射去獲取插件工程的Activity,然后將此代理給插件Activity,并在代理的各個方法中取調(diào)用插件的Activity的方法。
- 熱修復
http://www.itdecent.cn/p/e61a4d10e122
《深入探索Android熱修復技術原理7.3Q.pdf》
主要分兩種級別,一種是方法修復,代表Andfix,原理是改變虛擬機中方法的索引指向。一種是類級別修復,利用的是類的動態(tài)加載中改變應用BootClassLoader中的elements數(shù)組,代表是Tinker
- Sophix 修復方法
本質(zhì)是native層整體替換ArtMethod。這個方法的局限是修改不能有方法和字段的增減,以及不能修復反射調(diào)用的非靜態(tài)方法。局限場景如下
- 外部類訪問內(nèi)部類的private,或者內(nèi)部類訪問外部類的private,本質(zhì)是編譯時會為private增加一個access**方法。導致方法數(shù)增加,解決方法,就是有內(nèi)部類是雙方不使用private修飾屬性和方法
- 匿名內(nèi)部類的前插入和刪除。原因是匿名內(nèi)部類編譯會按順序生成一個帶有外部類名和序號的名字。
- 不支持<clinit>修復,注意 final static 的 基本類型和 String不會被收集到<clinit>方法中
- 混淆導致的方法內(nèi)聯(lián)(沒用的,簡單的,只有一個地方用的會被內(nèi)聯(lián))和裁剪(聲明了參數(shù),但是沒有用該參數(shù)會被裁剪)。會影響最終的方法數(shù)。解決方案是在配置混淆文件是加上-dontoptimize參數(shù)
- switch case 連續(xù)為packed_switch 不連續(xù) spare_switch ,資源id為packed_switch 這樣會導致不完全,所以解決方案就是反編譯將packed_switch指令改為spare_switch指令。
- 泛型的橋接(重寫泛型父類方法時編譯器自動生成的一個橋接方法,以此來解決泛型的類型擦除而導致與多態(tài)沖突的問題)會導致方法數(shù)增加
- Lambda 會引起方法數(shù)的增加和減少,原因是Lambda會將函數(shù)式接口編譯成一個靜態(tài)內(nèi)部方法,同時還會生成一個新的輔助類
- Sophix冷啟動修復方案:
davlik虛擬機全量Dex方法(去掉原來變動的class,這里不是真刪而是移除定義的入口)
art虛擬機 補丁為classes.dex 改原來的為classes1.dex...- Sophix資源修復方案:
增加一個packageId為0x66的純補丁資源包,配合代碼層id的引用實現(xiàn)資源的修復。在AssetManager上則是通過析構,重新初始化,重新增加path的方式保證不用到處替換原有的AssetManagerSophix的so庫修復方案
so修復方案.jpeg
- Thinker的原理與源碼
- Android中dex文件的加載與優(yōu)化流程
- 模塊化實現(xiàn)(好處,原因)
- 項目組件化的理解
- 描述清點擊 Android Studio 的 build 按鈕后發(fā)生了什么
https://blog.csdn.net/zheng548/article/details/54864765
build.jpeg
image
架構設計和設計模式
- 談談你對Android設計模式的理解
https://segmentfault.com/p/1210000008721369/read
- 六大設計原則
- 一個類只負責一個職責-單一職責
- 基類引用可以透明的換為子類對象-理式替換
- 抽象不依賴細節(jié),細節(jié)依賴抽象-依賴倒置
- 客戶端不應該依賴其不需要的接口-接口隔離
- 最少知道-迪米特法則
- 對擴展開發(fā),對修改關閉-開閉原則
- MVC MVP MVVM原理和區(qū)別
框架模式.jpeg
- 手寫生產(chǎn)者/消費者模式
//核心屬性定義
private volatile boolean isRunning = true;
private BlockingQueue<PCData> queue;// 內(nèi)存緩沖區(qū)
private static AtomicInteger count = new AtomicInteger();// 總數(shù) 原子操作
- 寫出觀察者模式的代碼
- 適配器模式,裝飾者模式,外觀模式的異同?
用到的一些開源框架,介紹一個看過源碼的,內(nèi)部實現(xiàn)過程。
談談對RxJava的理解
RxJava的功能與原理實現(xiàn)
RxJava的作用,與平時使用的異步操作來比的優(yōu)缺點
說說EventBus作用,實現(xiàn)方式,代替EventBus的方式
從0設計一款App整體架構,如何去做?
說一款你認為當前比較火的應用并設計(比如:直播APP,P2P金融,小視頻等)
談談對java狀態(tài)機理解
Fragment如果在Adapter中使用應該如何解耦?
Binder機制及底層實現(xiàn)
對于應用更新這塊是如何做的?(解答:灰度,強制更新,分區(qū)域更新)?
實現(xiàn)一個Json解析器(可以通過正則提高速度)
統(tǒng)計啟動時長,標準
https://blog.csdn.net/beyond_liyy/article/details/52273740
- 本地
abd shell am start -W com.gjg/com.gjg.SplashActivity
totaltime 進程 和 Activity的時間 不包含pause時間- 線上
Application attachBaseContext 起點 Activity的onWindowFocusChanged終點
- 談談對Kotlin的理解
性能優(yōu)化
- 如何對Android 應用進行性能分析以及優(yōu)化?
- ddms 和 traceView
性能優(yōu)化如何分析systrace?
用IDE如何分析內(nèi)存泄漏?
Java多線程引發(fā)的性能問題,怎么解決?
啟動頁白屏及黑屏解決,啟動太慢怎么解決,怎么保證應用啟動不卡頓?
- App啟動崩潰異常捕捉
UncaughtExceptionHandler
自定義View注意事項
現(xiàn)在下載速度很慢,試從網(wǎng)絡協(xié)議的角度分析原因,并優(yōu)化(提示:網(wǎng)絡的5層都可以涉及)。
Https請求慢的解決辦法(提示:DNS,攜帶數(shù)據(jù),直接訪問IP)
如何保持應用的穩(wěn)定性
RecyclerView和ListView的性能對比
ListView的優(yōu)化
RecycleView優(yōu)化
View渲染
Bitmap如何處理大圖,如一張30M的大圖,如何預防OOM
java中的四種引用的區(qū)別以及使用場景
強引用置為null,會不會被回收?
NDK、jni、Binder、AIDL、進程通信有關
請介紹一下NDK
什么是NDK庫?
jni用過嗎?
如何在jni中注冊native函數(shù),有幾種注冊方式?
Java如何調(diào)用c、c++語言?
jni如何調(diào)用java層代碼?
進程間通信的方式?
Binder機制
簡述IPC?
什么是AIDL?
AIDL解決了什么問題?
AIDL如何使用?
Android 上的 Inter-Process-Communication 跨進程通信時如何工作的?
多進程場景遇見過么?
Android進程分類?
進程和 Application 的生命周期?
進程調(diào)度
談談對進程共享和線程安全的認識
談談對多進程開發(fā)的理解以及多進程應用場景
什么是協(xié)程?
framework層、ROM定制、Ubuntu、Linux之類的問題
java虛擬機的特性
談談對jvm的理解
JVM內(nèi)存區(qū)域,開線程影響哪塊內(nèi)存
對Dalvik、ART虛擬機有什么了解?
Art和Dalvik對比
虛擬機原理,如何自己設計一個虛擬機(內(nèi)存管理,類加載,雙親委派)
談談你對雙親委派模型理解
JVM內(nèi)存模型,內(nèi)存區(qū)域
類加載機制
談談對ClassLoader(類加載器)的理解
談談對動態(tài)加載(OSGI)的理解
內(nèi)存對象的循環(huán)引用及避免
內(nèi)存回收機制、GC回收策略、GC原理時機以及GC對象
垃圾回收機制與調(diào)用System.gc()區(qū)別
Ubuntu編譯安卓系統(tǒng)
系統(tǒng)啟動流程是什么?(提示:Zygote進程 –> SystemServer進程 –> 各種系統(tǒng)服務 –> 應用進程)
大體說清一個應用程序安裝到手機上時發(fā)生了什么
簡述Activity啟動全部過程
App啟動流程,從點擊桌面開始
邏輯地址與物理地址,為什么使用邏輯地址?
Android為每個應用程序分配的內(nèi)存大小是多少?
Android中進程內(nèi)存的分配,能不能自己分配定額內(nèi)存?
進程?;畹姆绞?/p>
如何保證一個后臺服務不被殺死?(相同問題:如何保證service在后臺不被kill?)比較省電的方式是什么?
App中喚醒其他進程的實現(xiàn)方式





