1:int寨辩、Integer有什么區(qū)別梯轻?
Integer是int的包裝類,默認(rèn)是null;int是基本數(shù)據(jù)類型,默認(rèn)值是0圃郊;
2:equals與==區(qū)別,stringBuffer和stringbuilder區(qū)別
equals:比較的是兩個(gè)對(duì)象是否相等
==:比較的是棧內(nèi)存中的值
StringBuffer:線程安全
StringBuilder:線程不安全
既然 StringBuffer 是線程安全的女蜈,它的所有公開方法都是同步的持舆,StringBuilder 是沒有對(duì)方法加鎖同步的,所以毫無疑問伪窖,StringBuilder 的性能要遠(yuǎn)大于 StringBuffer逸寓。
3:A啟動(dòng)B時(shí)activity的兩個(gè)activity生命周期的流程。
A啟動(dòng):
Aactivity oncreate onstart onResume
A進(jìn)入B:
Activity onPause BActivity oncrete onstart onResume Activity onStop
B返回:
Bctivity onPause Activity restart start onResume Bactivity onStop ondestroy
A返回:
Activity onPase onstop ondestroy
4:Activity旋轉(zhuǎn)會(huì)調(diào)用哪些方法惰许?
沒有任何配置的情況下:
onPause()--onStop()--onDestroy()--onCreate()--onStart()--onResume()席覆;
5:android四種啟動(dòng)模式
1:standard標(biāo)準(zhǔn)模式:
每次啟動(dòng)都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例入棧,不管之前是否存在汹买。
2:SingleTop:
棧頂復(fù)用模式佩伤,如果Activity處于棧頂,則不再創(chuàng)建新的activity,如果不存在棧頂則重新創(chuàng)建實(shí)例晦毙。
3:SingleTask:
棧內(nèi)復(fù)用模式生巡,當(dāng)需要?jiǎng)?chuàng)建這個(gè)activity時(shí),如果activity已經(jīng)存在則將所有的在它之上的activity銷毀见妒,讓它處于棧頂孤荣。
4:singleInstance:
單實(shí)例模式,具有此模式的Activity單獨(dú)位于一個(gè)任務(wù)棧中须揣。只能有一個(gè)實(shí)例盐股。
6:startService和bindService區(qū)別,多次啟動(dòng)調(diào)用哪些方法耻卡?
1:生命周期上的區(qū)別:
startService:onCreate-->onStartCommand-->onStop-->onDestory
bindService:onCreate-->onBind-->unBindService-->onDestroy疯汁。
多次調(diào)用startService時(shí)service只能被創(chuàng)建一次,每次調(diào)用startService,onStartCommand都會(huì)執(zhí)行卵酪;
第一次執(zhí)行bindService時(shí)幌蚊,onCreate-->onBind都會(huì)被調(diào)用,多次執(zhí)行時(shí)候溃卡,onCreate-->onBind不會(huì)多次調(diào)用溢豆。
7:IO操作(斷點(diǎn)續(xù)傳原理)
RandomAccessFile:
支持對(duì)隨即訪問文件的讀寫。
8:跨進(jìn)程通信方式
Content Provider
廣播
Binder機(jī)制
Intent
文件讀寫
9:Android動(dòng)畫
逐幀動(dòng)畫(放電影瘸羡,一幀一幀)
補(bǔ)間動(dòng)畫(控制平移漩仙,旋轉(zhuǎn),縮放等)
屬性動(dòng)畫(升級(jí)版的補(bǔ)間動(dòng)畫,支持任意屬性的變化)
SurfaceView實(shí)現(xiàn)動(dòng)畫讯赏。
10:invalidate()和postInvalidate()區(qū)別
invalidate會(huì)刷新整個(gè)View,只能在UI線程中調(diào)用垮兑。
postInvalidate,可以在非UI線程中去調(diào)用刷新UI漱挎,postInvalidate是通過handler將刷新事件通知到handlerMessage中執(zhí)行invalidate的系枪。
11:廣播注冊(cè)后不注銷有什么問題?(內(nèi)存泄漏)
廣播在onReceiver方法中的參數(shù)Context磕谅,所以BroadCastReveiver中持有Activity私爷,
而且廣播不僅被Activity持有,可能還被ActivityManagerService等系統(tǒng)服務(wù)持有膊夹。
當(dāng)Activity調(diào)用onDestroy方法時(shí)候衬浑,Activity并不能被回收,從而導(dǎo)致內(nèi)存泄漏放刨。
所以需要結(jié)束時(shí)候調(diào)用unregisterReceiver()工秩。
onReceive()在10s內(nèi)沒有執(zhí)行完會(huì)ANR。
12:屏幕適配方案
傳統(tǒng)方案:
在res下建不同的values文件夾进统,創(chuàng)建不同的dimens助币。
今日頭條:
通過反射適配系統(tǒng)的density(密度)值
密度=屏幕中1dp所占的多少像素點(diǎn)
限定符適配:
smallestwidth,通過寬高限定符,配置在manifast.xml中螟碎,程序啟動(dòng)時(shí)候讀取xml設(shè)值眉菱。
13:如何監(jiān)聽activity是否后臺(tái)切換到前臺(tái)?不是在onReusme()中處理掉分。
1:ActivityManager中處理:
getRunningTasks返回一個(gè)list集合俭缓,通過getClassName獲取在前臺(tái)的Activity。
2:OnResume中和onPause中記錄一個(gè)變量酥郭。
14:FragmentPageAdater和FragmentStateAdapter區(qū)別华坦?
FragmentPageAdater:fragment對(duì)象會(huì)一直在內(nèi)存中,適用于少數(shù)的page情況不从。
FargmentStateAdapter:默認(rèn)保存三個(gè)fragment惜姐,上一個(gè)當(dāng)前的和下一個(gè),一起對(duì)象的fragment會(huì)被銷毀消返,但是在執(zhí)行ondestroy時(shí)先調(diào)用onSaveInstenceState()來保存Fragment的狀態(tài)载弄,當(dāng)fragment執(zhí)行oncreate時(shí)候再把Bundle中的值取出來耘拇,比較適合多頁面撵颊。
15:Servie&IntentService
Servie不能做耗時(shí)操作
IntentService繼承自service,可以做后臺(tái)下載等耗時(shí)操作。
16:Android常用性能調(diào)優(yōu)
1:內(nèi)存優(yōu)化
GC釋放對(duì)象包含(引用點(diǎn)):java棧中引用的對(duì)象惫叛;靜態(tài)方法引用的對(duì)象倡勇;靜態(tài)常量引用的對(duì)象;Native中JNI引用的對(duì)象,Thread妻熊。
內(nèi)存溢出原因:瞬間申請(qǐng)了大量?jī)?nèi)存導(dǎo)致OOM夸浅;長(zhǎng)期不能釋放導(dǎo)致超過閾值導(dǎo)致OOM;小范圍累積不能釋放導(dǎo)致卡頓的OOM扔役。
優(yōu)化方式:利用profiler查看堆椃快照,具體查看波動(dòng)內(nèi)存是哪里導(dǎo)致的亿胸。
利用leakCanary工具查看生成的dump文件坯钦。
2:UI布局優(yōu)化
UI卡頓的情況:View過渡繪制;Layout過于復(fù)雜侈玄,無法在16ms內(nèi)完成渲染婉刀;View頻繁出發(fā)measure,layout。
優(yōu)化方式:開啟GPU過渡繪制工具查看當(dāng)前布局的繪制情況序仙。
a:用RealtiveLayout代替LinearLayout
b:include,ViewStub,merge標(biāo)簽的使用
3:代碼質(zhì)量?jī)?yōu)化
a:使用as自帶的unused resource清理無用資源
b:代碼混淆
4:網(wǎng)絡(luò)優(yōu)化
a:用as自帶的profiler進(jìn)行網(wǎng)絡(luò)監(jiān)聽突颊。
ANR產(chǎn)生的原因:
Activity5s內(nèi)無響應(yīng);廣播10s無法處理完潘悼;服務(wù)service20s無法處理完律秃。
網(wǎng)絡(luò)請(qǐng)求中的圖片可以用webp格式,質(zhì)量相同的情況下減少流量挥等。
優(yōu)化方式:
一般多線程可以通過Asynctask處理友绝,可以控制線程的順序,執(zhí)行完A后根據(jù)A返回的參數(shù)執(zhí)行B線程肝劲。
5:耗電優(yōu)化
a:需要進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí)先判斷當(dāng)前的網(wǎng)絡(luò)狀態(tài)迁客。
b:當(dāng)有wifi和移動(dòng)網(wǎng)絡(luò)時(shí)候,優(yōu)先選擇wifi比移動(dòng)網(wǎng)絡(luò)耗電低辞槐。
c:減少后臺(tái)任務(wù)的喚醒操作掷漱。
6:?jiǎn)?dòng)優(yōu)化
a:冷啟動(dòng),殺死進(jìn)程后啟動(dòng)或程序第一次啟動(dòng)榄檬,耗時(shí)最久卜范,因?yàn)橐匦陆?jīng)歷application初始化,啟動(dòng)ui線程鹿榜,創(chuàng)建Activity,導(dǎo)入視圖繪制視圖等海雪。
b:暖啟動(dòng),當(dāng)activity被銷毀舱殿,但在內(nèi)存中常駐時(shí)奥裸,啟動(dòng)減少了對(duì)象的初始化,布局加載等沪袭,啟動(dòng)時(shí)間短湾宙。
c:熱啟動(dòng),啟動(dòng)時(shí)間最短,比如按home鍵重新回到應(yīng)用侠鳄。
優(yōu)化方式:Application創(chuàng)建過程盡量少埠啃,減少布局層次,啟動(dòng)頁預(yù)加載等伟恶。
17:Java常用設(shè)計(jì)模式
1.單一職責(zé)原則:不要存在多于一個(gè)導(dǎo)致類變更的原因碴开。
通俗的說:即一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé)。
2.里氏替換原則:所有引用基類的地方必須能透明地使用其子類
通俗的說:當(dāng)使用繼承時(shí)博秫。類 B 繼承類 A 時(shí)叹螟,除添加新的方法完成新增功能外,盡量不要重寫父類 A 的方法台盯,也盡量不要重載父類 A 的方法罢绽。如果子類
對(duì)這些非抽象方法任意修改,就會(huì)對(duì)整個(gè)繼承體系造成破壞静盅。子類可以擴(kuò)展父類
的功能良价,但不能改變父類原有的功能。
3.依賴倒置原則:高層模塊不應(yīng)該依賴低層模塊蒿叠,二者都應(yīng)該依
賴其抽象明垢;抽象不應(yīng)該依賴細(xì)節(jié);細(xì)節(jié)應(yīng)該依賴抽象市咽。
通俗的說:在 java 中痊银,抽象指的是接口或者抽象類,細(xì)節(jié)就是具體的實(shí)現(xiàn)類施绎,
使用接口或者抽象類的目的 ,是制定好規(guī)范和契約溯革,而不去涉及任何具體的操作,
把展現(xiàn)細(xì)節(jié)的任務(wù)交給他們的實(shí)現(xiàn)類去完成谷醉。依賴倒置原則的核心思想是面向接
口編程.
4.接口隔離原則:客戶端不應(yīng)該依賴它不需要的接口致稀;一個(gè)類對(duì)
另一個(gè)類的依賴應(yīng)該建立在最小的接口上。
通俗的說:建立單一接口俱尼,不要建立龐大臃腫的接口抖单,盡量細(xì)化接口,接口中的
方法盡量少遇八。也就是說矛绘,我們要為各個(gè)類建立專用的接口,而不要試圖去建立一
個(gè)很龐大的接口供所有依賴它的類去調(diào)用刃永。
5.迪米特法則:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解
通俗的說:盡量降低類與類之間的耦合货矮。
6.開閉原則:一個(gè)軟件實(shí)體如類、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開放揽碘,
對(duì)修改關(guān)閉次屠。
通俗的說:用抽象構(gòu)建框架,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)雳刺。因?yàn)槌橄箪`活性好劫灶,適應(yīng)性廣,
只要抽象的合理掖桦,可以基本保持軟件架構(gòu)的穩(wěn)定本昏。而軟件中易變的細(xì)節(jié),我們用
從抽象派生的實(shí)現(xiàn)類來進(jìn)行擴(kuò)展枪汪,當(dāng)軟件需要發(fā)生變化時(shí)涌穆,我們只需要根據(jù)需求
重新派生一個(gè)實(shí)現(xiàn)類來擴(kuò)展就可以了。
單例模式:某個(gè)類只能有一個(gè)實(shí)例雀久,提供一個(gè)全局的訪問點(diǎn)宿稀。避免對(duì)象的重復(fù)創(chuàng)建,提高資源的有效利用赖捌。(餓漢式)
代理模式:為其他對(duì)象提供一個(gè)代理祝沸,以便控制這個(gè)對(duì)象的訪問。
工廠模式:定義一個(gè)創(chuàng)建對(duì)象的接口越庇,讓子類決定實(shí)例化哪個(gè)類罩锐。
觀察者模式:對(duì)象間的一對(duì)多的依賴關(guān)系。
18:Android常用開發(fā)架構(gòu)
1.mvc:數(shù)據(jù)卤唉、View涩惑、Activity,View 將操作反饋給 Activity桑驱,Activitiy 去獲取數(shù)據(jù)竭恬,數(shù)
據(jù)通過觀察者模式刷新給 View。循環(huán)依賴
1.Activity 重熬的,很難單元測(cè)試
2.View 和 Model 耦合嚴(yán)重
2.mvp:數(shù)據(jù)萍聊、View、Presenter悦析,View 將操作給 Presenter寿桨,Presenter 去獲取數(shù)據(jù),數(shù)
據(jù)獲取好了返回給 Presenter强戴,Presenter 去刷新 View亭螟。PV,PM 雙向依賴
1.接口爆炸
2.Presenter 很重
3.mvvm:數(shù)據(jù)骑歹、View酌住、ViewModel,View 將操作給 ViewModel呛每,ViewModel 去獲取數(shù)
據(jù)回窘,數(shù)據(jù)和界面綁定了翘县,數(shù)據(jù)更新界面更新。
1.viewModel 的業(yè)務(wù)邏輯可以單獨(dú)拿來測(cè)試
2.一個(gè) view 對(duì)應(yīng)一個(gè) viewModel 業(yè)務(wù)邏輯可以分離谴分,不會(huì)出現(xiàn)全能類
3.數(shù)據(jù)和界面綁定了锈麸,不用寫垃圾代碼,但是復(fù)用起來不舒服viewmodel不能持有上下文牺蹄。
19:自定義控件
自定義View:繼承View
基于現(xiàn)有組件:繼承View的派生類
組合方式:自定義控件中包含了其他的組件
onMeasure:測(cè)量View的大小寬高
根據(jù)父View和MeasureSpec加上子view自己的LayoutParams,通過相應(yīng)的轉(zhuǎn)化規(guī)則而得到大小忘伞。
MeasureSpec代表寬度或高度的要求,每個(gè)MeasureSpec都包含了size和mode,MeasureSpec的模式主要分為:
(1)exactly:父容器已經(jīng)測(cè)量出子view的大小沙兰,對(duì)應(yīng)view的layoutparams的match_parent氓奈。
(2)at_most:父容器已經(jīng)限制了view的大小,對(duì)應(yīng)view的layoutParams的wrap_content鼎天。
onLayout:計(jì)算顯示位置舀奶。
對(duì)View進(jìn)行排版布局,要看父容器斋射,也就是viewGroup伪节。
onDraw:繪制背景,內(nèi)容绩鸣,繪制子view等
20:事件分發(fā)機(jī)制怀大?
Activity/View處理事件分發(fā)的方法:
dispatchTouchEvent()
onTouchEvent()
ViewGroup事件分發(fā)處理:
dispatchTouchEvent()
onInterceptTouchEvent()
onTouchEvent()
在activity中當(dāng)用戶屏幕點(diǎn)擊了后會(huì)先觸發(fā)dispatchTouchEvent()如果view處理該事件則返回true,事件傳遞結(jié)束。如果返回false則調(diào)用onTouchEvent()處理該事件呀闻。
在ViewGroup中ViewGroup的dispatchTouchEvent先判斷ViewGroup是否攔截Touch事件化借,如果攔截了則不向下傳遞直接調(diào)用TouchEvent處理事件,如果沒有攔截則遍歷所有子view找到點(diǎn)擊的那個(gè)View把touch事件傳遞給它捡多。viewgroup的onInterceptTouchEvent方法默認(rèn)false,viewgroup事件分發(fā)都會(huì)調(diào)用它蓖康,一旦onInterceptTouchEvent返回true則表示攔截了事件,后續(xù)進(jìn)行事件分發(fā)不再調(diào)用onInterceptTouchEvent方法垒手。
總體優(yōu)先級(jí) setTouchListener > onTouchEvent > onClick > setClickListener
注意:DOWN或UP就是一個(gè)事件蒜焊,不是DOWM+MOVE+UP才是一個(gè)事件,加起來是我們稱作一系列事件
重寫onTouchEvent時(shí)千萬別刪了super.onTouchEvent(event)——本人手賤科贬,為此付出過慘痛代價(jià)泳梆。
getParent().requestDisallowInterceptTouchEvent(true):父控件不會(huì)攔截事件
getParent().requestDisallowInterceptTouchEvent(false):父控件會(huì)根據(jù)自身的判斷來決定是否攔截
21:如何計(jì)算View大小&如何對(duì)子控件進(jìn)行布局
計(jì)算View大小:
view在測(cè)量過程和activity生命周期不是同步的榜掌,所以在onCreate/onStart/onResume獲取view寬高是0优妙。
在onWindowFocusChanged里面獲取。(getMeasuredWidth(),getMesureHeight())
子View布局:
可以通過addView方式憎账,infalte布局
22:RecyclerView優(yōu)缺點(diǎn)
RecyclerView卡頓情況:布局復(fù)雜套硼,多層嵌套,設(shè)置setNestedScrollingEnable(false)胞皱;含視頻邪意,滑動(dòng)到item時(shí)加載九妈,item滑出界面釋放資源;含圖片雾鬼,圖片懶加載(默認(rèn)圖占位)
RecyclerView4級(jí)緩存:
第一級(jí)ChangedScrap匹配position或者id獲取holder緩存萌朱。可見緩存 x(無限制) ArrayList 用于屏幕中可見View的回收和復(fù)用
第二級(jí)從CachedViews 緩存列表 2 ArrayList 用于移除屏幕的View的回收和復(fù)用呆贿,不會(huì)清空數(shù)據(jù)
第三級(jí)ViewCacheExtension自定義緩存 x 一般不使用這個(gè)
第四級(jí)通過RecyclerViewPool 緩存池 5 SparseArray 用于移除屏幕的View的回收和復(fù)用,會(huì)將ViewHolder的數(shù)據(jù)重置
23:Http&Socket編程,TCP/IP原理
TCP 建立連接要進(jìn)行 3 次握手,而斷開連接要進(jìn)行 4 次
1.基于連接與無連接森渐;
2.對(duì)系統(tǒng)資源的要求(TCP 較多做入,UDP 少);
3.UDP 程序結(jié)構(gòu)較簡(jiǎn)單同衣;
4.流模式與數(shù)據(jù)報(bào)模式 竟块;
5.TCP 保證數(shù)據(jù)正確性,UDP 可能丟包耐齐,TCP 保證數(shù)據(jù)順序浪秘,UDP 不
保證。
三次握手:
A:你好我是A埠况。
B:你好A耸携,我是B。
A:你好B
四次揮手:
A:B啊辕翰,我不想玩了夺衍。
B:哦,你不想玩了喜命,我知道了沟沙。(這個(gè)時(shí)候,只是A不想玩了壁榕,A不再發(fā)送數(shù)據(jù)矛紫,但B可能有未完成的數(shù)據(jù),所以需要等待)
B:A啊牌里,好吧颊咬,我也不玩了,拜拜牡辽。
A:好的贪染,拜拜。
Http和Https區(qū)別:
https是具有安全性的ssl加密身份認(rèn)證的傳輸協(xié)議催享,需要到ca申請(qǐng)證書杭隙。端口443。
http是超文本傳輸協(xié)議因妙,信息是明文傳輸痰憎。端口是80票髓,是無狀態(tài)連接。
24:圖片優(yōu)化
bitmap占用內(nèi)存=圖片長(zhǎng)*圖片寬*一個(gè)像素點(diǎn)占用的字節(jié)數(shù)铣耘。
bitmap.config中argb_4444和argb_8888代表一個(gè)像素點(diǎn)占用多少位洽沟。
圖片壓縮方式:
a:質(zhì)量壓縮,bitmap.compress不會(huì)改變圖片所在內(nèi)存大小蜗细,改變的是圖片所占磁盤大小裆操。
b:設(shè)置圖片格式,png無損炉媒,jpeg有損踪区,webp有損和無損,體積更小吊骤。
c:采樣率壓縮inSampleSize寬高壓縮缎岗。
d:縮放壓縮,減少圖片的像素來降低磁盤和內(nèi)存大小白粉,可用于縮略圖传泊。
e:JNI調(diào)用JPEG庫。(圖片引擎采用skia鸭巴,去掉了壓縮算法導(dǎo)致)
Glide:
用法是with().load().into()眷细。用法和pissco一致,是pissco的升級(jí)版鹃祖。
SupportRequestManagerFragment是一致存在于棧中的fragment薪鹦。不管上下文是用activity還是application的基本不會(huì)造成OOM,LruCache通過鍵值對(duì)形式存儲(chǔ)bitmap惯豆,通過linkedHashmap保證插入順序池磁,Gilde可以從LruCache獲取圖片,從弱引用中獲取緩存楷兽,從網(wǎng)絡(luò)請(qǐng)求中獲取圖片地熄。
25:Handle機(jī)制(postDelay),postDelay執(zhí)行時(shí)候是什么時(shí)候把message添加Queue中的芯杀?
1.MessageQueue:讀取會(huì)自動(dòng)刪除消息端考,單鏈表維護(hù),在插入和刪除上有優(yōu)勢(shì)揭厚。在
其 next()中會(huì)無限循環(huán)却特,不斷判斷是否有消息,有就返回這條消息并移除筛圆。
2.Looper:Looper 創(chuàng)建的時(shí)候會(huì)創(chuàng)建一個(gè) MessageQueue裂明,調(diào)用 loop()方法的時(shí)候消
息循環(huán)開始,loop()也是一個(gè)死循環(huán)太援,會(huì)不斷調(diào)用 messageQueue 的 next()闽晦,當(dāng)有消
息就處理扳碍,否則阻塞在 messageQueue 的 next()中。當(dāng) Looper 的 quit()被調(diào)用的時(shí)候
會(huì)調(diào)用 messageQueue 的 quit(),此時(shí) next()會(huì)返回 null仙蛉,然后 loop()方法也跟著退出笋敞。
3.Handler:在主線程構(gòu)造一個(gè) Handler,然后在其他線程調(diào)用 sendMessage(),此時(shí)主
線程的 MessageQueue 中會(huì)插入一條 message荠瘪,然后被 Looper 使用夯巷。
4.系統(tǒng)的主線程在 ActivityThread 的 main()為入口開啟主線程,其中定義了內(nèi)部類
Activity.H 定義了一系列消息類型哀墓,包含四大組件的啟動(dòng)停止趁餐。
5.MessageQueue 和 Looper 是一對(duì)一關(guān)系,Handler 和 Looper 是多對(duì)一
http://www.reibang.com/p/c7b87f8ed0c7(問題1)
https://blog.csdn.net/cmyperson/article/details/98970586 (問題2)
總的來說麸祷,一個(gè)線程中可以創(chuàng)建許多 Handler澎怒,然而這些 Handler 對(duì)象持有的 Looer褒搔、MessageQueue 引用指向的都是相同的對(duì)象(線程中唯一的的)阶牍;這樣一來,在其他線程中用這些 Handler 對(duì)象去發(fā)送消息(發(fā)出的消息持有發(fā)消息的 Handler 對(duì)象的引用)星瘾,發(fā)出去的消息最終都是被放到了創(chuàng)建 Handler 線程中對(duì)應(yīng)那個(gè) MessageQueue 中
而創(chuàng)建 Handler 的線程中通過 Looper.loop 死循環(huán)不斷地從消息隊(duì)列中取出消息走孽,這樣便實(shí)現(xiàn)了線程之間的通信;由于對(duì)消息的入隊(duì)和出隊(duì)操作都是加了鎖的琳状,因此便保證了通信的安全性
為什么loop死循環(huán)不會(huì)卡死:
線程是一段可執(zhí)行的代碼磕瓷,當(dāng)執(zhí)行完后線程的生命周期便終止,線程退出念逞。而主線程我們希望一直運(yùn)行下去困食,死循環(huán)便能保證不會(huì)被退出。真正導(dǎo)致卡死主線程的操作是在回調(diào)onCreate/onStart/onResume等操作時(shí)間過長(zhǎng)導(dǎo)致ANR翎承,looper.loop本身不會(huì)導(dǎo)致應(yīng)用卡死硕盹。
26:EventBus原理
register注冊(cè),post發(fā)送消息叨咖。
EventBus解耦其實(shí)是使用了反射瘩例,在register時(shí)候會(huì)通過反射將信息記錄下來。
觀察者模式:通過subscrible訂閱消息甸各,Observer觀察者垛贤。
源碼解析:
EventBus發(fā)送事件原理是,subscriptionsByEventType通過事件類型EventType.class獲取到訂閱方法包裝類List集合趣倾。
然后通過postToSubscription方法聘惦,在方法中匹配發(fā)送事件的線程模式threadMode,
例如匹配到主線程時(shí)儒恋,會(huì)直接通過反射調(diào)用訂閱方法subscription.subscriberMethod.method.invoke(subscription.subscriber, event)
實(shí)現(xiàn)事件的發(fā)布-訂閱執(zhí)行部凑。
EventBus事件的解注冊(cè)
EventBus解注冊(cè)原理則是清空typesBySubscriber和subscriptionsByEventType露乏。
EventBus發(fā)送粘性事件
EventBus在處理粘性事件的原理,先通過postSticky方法將鍵值對(duì)(key=事件類型class涂邀,value=事件實(shí)例)存入字典stickyEvents中瘟仿。
而真實(shí)的執(zhí)行粘性事件的訂閱方法,則是通過EventBus.register()來實(shí)現(xiàn)的比勉。
發(fā)布事件的訂閱類在注冊(cè)時(shí)如果判斷得知該事件屬于粘性事件劳较,那么就會(huì)通過循環(huán)遍歷字典stickyEvents,
以執(zhí)行訂閱方法的執(zhí)行~ 【在執(zhí)行訂閱方法進(jìn)入方法postToSubscription時(shí)浩聋,跟非粘性事件處理就一致了】
27:jvm模型,java內(nèi)存模型观蜗,垃圾回收機(jī)制,垃圾回收哪個(gè)區(qū)域衣洁,對(duì)象在內(nèi)存哪個(gè)區(qū)域墓捻。
jvm內(nèi)存模型:方法區(qū),堆坊夫,程序計(jì)數(shù)器砖第,本地方法棧。
垃圾回收機(jī)制執(zhí)行:
1:年老代被寫滿
2:持久帶被寫滿
3:System.gc()被顯示調(diào)用
4:上一次gc之后heap的分配策略動(dòng)態(tài)變化环凿。
對(duì)象在內(nèi)存中的堆里面梧兼。JVM所有對(duì)象都是在堆中分配內(nèi)存空間,棧只是保存局部變量和臨時(shí)變量智听,如果是對(duì)象只保存引用羽杰。
28:Parcelable和Serializable區(qū)別
Parcelable:
Android提供的,代碼多到推,速度高
Parcelable中的三大過程介紹(序列化,反序列化,描述)
什么是序列化
序列化考赛,表示將一個(gè)對(duì)象轉(zhuǎn)換成可存儲(chǔ)或可傳輸?shù)臓顟B(tài)。序列化后的對(duì)象可以在網(wǎng)絡(luò)上進(jìn)行傳輸莉测,也可以存儲(chǔ)到本地颜骤。
Parcelable和Serializable的區(qū)別和比較
Parcelable和Serializable都是實(shí)現(xiàn)序列化并且都可以用于Intent間傳遞數(shù)據(jù),Serializable是Java的實(shí)現(xiàn)方式,可能會(huì)頻繁的IO操作,所以消耗比較大,但是實(shí)現(xiàn)方式簡(jiǎn)單 Parcelable是Android提供的方式,效率比較高,但是實(shí)現(xiàn)起來復(fù)雜一些 , 二者的選取規(guī)則是:內(nèi)存序列化上選擇Parcelable, 存儲(chǔ)到設(shè)備或者網(wǎng)絡(luò)傳輸上選擇Serializable(當(dāng)然Parcelable也可以但是稍顯復(fù)雜)
選擇序列化方法的原則
1)在使用內(nèi)存的時(shí)候,Parcelable比Serializable性能高悔雹,所以推薦使用Parcelable复哆。
2)Serializable在序列化的時(shí)候會(huì)產(chǎn)生大量的臨時(shí)變量,從而引起頻繁的GC腌零。
3)Parcelable不能使用在要將數(shù)據(jù)存儲(chǔ)在磁盤上的情況梯找,因?yàn)镻arcelable不能很好的保證數(shù)據(jù)的持續(xù)性在外界有變化的情況下。盡管Serializable效率低點(diǎn)益涧,但此時(shí)還是建議使用Serializable 锈锤。
Serializable:
java自帶的,代碼量少,速度低
29:ContentProvider實(shí)現(xiàn)原理久免,如何進(jìn)行批量操作浅辙?
ContentProvider可以作為數(shù)據(jù)訪問接口之外,還可以在不同應(yīng)用程序之間進(jìn)行數(shù)據(jù)共享阎姥。因?yàn)锽inder傳遞數(shù)據(jù)有大小限制记舆,所以用ContentProvider來處理比較高效。
ContentProvider必須在Manifest中聲明呼巴。訪問provider需要知道它的URI泽腮,所以把provider的URI作為公共常量出來。
ContentProviderOperation:
可以批量更新衣赶,插入诊赊,刪除數(shù)據(jù)。
ContentProviderOperation.Builder:
newInsert 插入操作
newUpdate 更新操作
newDelete 刪除操作
newAssertQuery 查詢沒有符合條件的數(shù)據(jù)
30:Android動(dòng)態(tài)權(quán)限府瞄?各版本差異性碧磅?
5.0
沉浸式狀態(tài)欄
6.0
動(dòng)態(tài)權(quán)限,httpclient刪除。
7.0 8.0 9.0
更注重耗電和后臺(tái)優(yōu)化遵馆。將bitmap中的像素點(diǎn)放在native層等鲸郊。
10.0
不再需要任何權(quán)限即可在外部存儲(chǔ)設(shè)備中訪問和保存自己的文件,谷歌官方推薦應(yīng)用在沙盒內(nèi)存儲(chǔ)文件的地址為Context.getExternalFilesDir()下的文件夾
11
安裝app動(dòng)態(tài)權(quán)限
12
隱私,存儲(chǔ)团搞,權(quán)限優(yōu)化
13
優(yōu)化藍(lán)牙严望、音頻多艇,為大屏設(shè)備和平板做優(yōu)化
31:SurfaceView和View
SurfaceView是從View基類中派生出來的顯示類逻恐,他和View的區(qū)別有:
View需要在UI線程對(duì)畫面進(jìn)行刷新,而SurfaceView可在子線程進(jìn)行頁面的刷新峻黍,View適用于主動(dòng)更新的情況复隆,View頻繁刷新會(huì)阻塞主線程,導(dǎo)致界面卡頓
SurfaceView在底層已實(shí)現(xiàn)雙緩沖機(jī)制姆涩,而View沒有挽拂,因此SurfaceView更適用于被動(dòng)更新,需要頻繁刷新骨饿、刷新時(shí)數(shù)據(jù)處理量很大的頁面
32:AsyncTask異步任務(wù)
更新UI操作必須在主線程進(jìn)行亏栈,下載圖片,文件宏赘,網(wǎng)絡(luò)請(qǐng)求需要在子線程進(jìn)行绒北,可以用handler機(jī)制。
Asynctask:
對(duì)線程和Handler進(jìn)行了封裝察署,可以直接對(duì)UI進(jìn)行更新操作闷游。
1:onPreExecute():執(zhí)行在后臺(tái)下載操作之前,與現(xiàn)行在主線程中。
2:doInBackground:核心方法脐往,運(yùn)行在子線程中
3:onPostExecute():后臺(tái)下載完成后回調(diào)休吠,運(yùn)行在主線程中。
4:onProgressUpdate():在下載操作中調(diào)用publicProgress用于更新下載進(jìn)度业簿,運(yùn)行在主線程中瘤礁。
別再傻傻得認(rèn)為AsyncTask只可以在主線程中創(chuàng)建實(shí)例和調(diào)用execute方法
總結(jié)一下就是,可以在子線程中創(chuàng)建AsyncTask實(shí)例,并執(zhí)行execute. 注意在哪個(gè)線程執(zhí)行AsyncTask的execute(),onPreExecute會(huì)運(yùn)行在執(zhí)行在哪個(gè)線程中梅尤,onPostExecute方法還是會(huì)執(zhí)行在主線程中蔚携,doInBackground方法會(huì)執(zhí)行在AsyncTask創(chuàng)建的線程中。
這個(gè)問題的核心是, Handler實(shí)例化需要用到線程的Looper克饶,而我自己新建的Thread并沒有調(diào)用Looper.prepare()酝蜒,所以新開的線程Looper肯定為空,怎么會(huì)運(yùn)行正常呢?
因?yàn)锳syncTask源碼里Handler持有的主線程的Looper
sHandler = new InternalHandler(Looper.getMainLooper());
33:Android強(qiáng)軟弱虛引用的應(yīng)用場(chǎng)景
private String a="test";
1:強(qiáng)引用矾湃,定義的常量屬于強(qiáng)引用亡脑,內(nèi)存不足OOM時(shí)候也不會(huì)去回收該對(duì)象。
2:軟引用邀跃,內(nèi)存足夠就不回收霉咨,不足是進(jìn)行回收
3:弱引用,比軟引用生命周期更短拍屑,只要被垃圾回收器線程發(fā)現(xiàn)途戒,就會(huì)被回收。
4:虛引用僵驰,任何時(shí)候都可能會(huì)回收喷斋。
34:混淆的優(yōu)點(diǎn)和使用場(chǎng)景
nimifyEnabled true開啟混淆
優(yōu)點(diǎn):
1:增加對(duì)apk反編譯的困難性
2:減少apk體積
注意:
1:避免混淆Android基本組件,避免混淆get/set方法蒜茴,避免混淆枚舉類星爪,序列化類等。
35:java反射
反射:
對(duì)于任意一個(gè)類粉私,都能得到它的屬性和方法顽腾。通過setAccessible(true),可以得到私有屬性
36:android安全性
安全性诺核,可以通過混淆代碼形式抄肖。
防止抓包,可以通過指紋碼或者公鑰證書窖杀,配合okhttp里面的sslFactory做防止中間人攻擊漓摩。
AES
1、AES加密是一種對(duì)稱式加密陈瘦,即加密和解密所需秘鑰是相同的幌甘,你可以生成一組秘鑰潮售,然后利用該秘鑰加密數(shù)據(jù),然后發(fā)給合作伙伴锅风,同時(shí)也需要把秘鑰發(fā)送給合作伙伴酥诽,這樣你的合作伙伴才能解密。
相比RSA加密來說皱埠,好處是不會(huì)限制加密字符串的長(zhǎng)度
RES
2肮帐、RSA加密,是一種非對(duì)稱式加密.
加殼原理(愛加密):
37:SharedPrefrence原理边器,能否夸進(jìn)程训枢,如何實(shí)現(xiàn)?
不能跨進(jìn)程忘巧,默認(rèn)模式mode_private恒界,其他支持跨境成模式已經(jīng)被廢棄,可以用contentProvider跨進(jìn)程通信砚嘴。
SharedPrefrence是基于xml實(shí)現(xiàn)的一種數(shù)據(jù)持久化手段十酣。
SharedPrefrence不支持多進(jìn)程。
SharedPrefrence的commit與apply一個(gè)是同步一個(gè)是異步际长。
SharedPrefrence不要存儲(chǔ)過大數(shù)據(jù)耸采。
SharedPreferences 也有其自身缺陷,比如其職能存儲(chǔ) boolean工育,int虾宇,float,long 和 String 五種簡(jiǎn)單的數(shù)據(jù)類
38:webView加載h5的優(yōu)化,webView內(nèi)存泄漏是否了解如绸。
頁面加載速度優(yōu)化:
1:選擇合適的瀏覽器緩存機(jī)制
2:常用資源預(yù)加載嘱朽,常用JS本地化及延遲加載,放在本地加載竭沫。
導(dǎo)致內(nèi)存泄漏:
系統(tǒng)在attachTowindow和detachFromWindow處進(jìn)行注冊(cè)和反注冊(cè)component callback導(dǎo)致燥翅。
封裝自己的webView,不再xml中聲明骑篙,在代碼中直接new WebView,傳入Application的上下文防止acitivty被濫用。
WebView webView = new WebView(getContext().getApplicationContext());
webFrameLayout.addView(webView, 0);
39:插件化
騰訊的tinker和阿里的andfix。
本地?zé)嵝迯?fù)
1:修改好代碼后編譯后生成.class文件
2:用sdk中提供的dx工具將需要替換的.class文件轉(zhuǎn)化成dex默色。
3:將.dex文件放入磁盤藤韵,創(chuàng)建一個(gè)DexClassLoader,通過PathClassLoader遍歷出需要修改的dexElements杨名,設(shè)值新的參數(shù)脏榆。
4:?jiǎn)?dòng)時(shí)候重新loadFixdex()
問題:
模塊間耦合度過大溝通成本高,app方法數(shù)超過65535等問題
解決:
將一個(gè)apk拆分成多個(gè)小apk,每個(gè)小apk能單獨(dú)運(yùn)行台谍。業(yè)務(wù)模塊基本完全解耦须喂。
1:dex加載原理
dexClassLoader:可以加載文件系統(tǒng)上的jar、dex、apk坞生。
PathClassLoader:可以加載/data/app目錄下的apk,只能加載已安裝的apk仔役。
PathClassLoader和DexClassLoader都是Android提供給我們的ClassLoader,都能加載dex
網(wǎng)上很多文章都說PathClassLoader只能加載已經(jīng)被系統(tǒng)安裝過的apk是己,DexClassLoader無此限制又兵,然而我自己測(cè)試是都可以
根據(jù)art源碼來看,兩者都繼承自BaseDexClassLoader卒废,最終都會(huì)創(chuàng)建一個(gè)DexFile沛厨,不同點(diǎn)是一個(gè)關(guān)鍵的參數(shù):optimizedDirectory,PathClassLoader為null摔认,DexClassLoader則使用傳遞進(jìn)來的
然后會(huì)根據(jù)optimizedDirectory判斷對(duì)應(yīng)的oat文件是否已經(jīng)生成(null則使用/data/dalvik-cache/)逆皮,如果有且該oat對(duì)應(yīng)的dex正確則直接加載,否則觸發(fā)dex2oat(就是這家伙耗了我們寶貴的時(shí)間2胃ぁR惩馈),成功則用生成的oat蓖柔,失敗則走解釋執(zhí)行
ps:貌似Q版做了優(yōu)化辰企,不會(huì)再卡死在dex2oat里了
根據(jù)加載外部dex的實(shí)驗(yàn),DexClassLoader會(huì)觸發(fā)dex2oat况鸣,而PathClassLoader不會(huì)
40:線程池
wait:線程睡眠時(shí)牢贸,釋放對(duì)象鎖,其他線程可以訪問镐捧。
sleep:線程睡眠時(shí)潜索,仍然占有該鎖,其他線程無法訪問懂酱。
線程池是用來存放線程的池子竹习,里面的線程可以被重復(fù)利用,不浪費(fèi)列牺。
創(chuàng)建線程池:用Executors 整陌。
singleThreadPool單一線程
fixedThreadPool固定數(shù)量的線程池
scheduleThreadPool周期任務(wù)
cacheThreadPool想建幾個(gè)就建幾個(gè)
41:Glide源碼分析
42:okhttp源碼分析
43:LeakCanary源碼分析
44:RxJava操作符
45:HashMap原理
46:framework層AMS、PMS瞎领、WMS
activity啟動(dòng)過程:
1:通過Launcher啟動(dòng)Activity或者startActivity來啟動(dòng)泌辫,都是通過Binder進(jìn)程間通信進(jìn)入到ActivityManagerService進(jìn)程中,并且調(diào)用ActivityManagerService.startActivity接口九默;
2:ActivityManagerService調(diào)用ActivityStack.startActivityMayWait來做準(zhǔn)備要啟動(dòng)activity的相關(guān)信息震放;
3:ActivityStack通知Application Thread要進(jìn)行Activity啟動(dòng)調(diào)度了。
4:Application Thread不執(zhí)行真正的啟動(dòng)操作驼修,它通過調(diào)用ActivityManagerService.activityPaused接口進(jìn)入到ActivityManagerService進(jìn)程中殿遂,看看是否需要?jiǎng)?chuàng)建新的進(jìn)程來啟動(dòng)Activity诈铛;
5:如果是通過Launcher的情況,ActivityManagerService會(huì)調(diào)用startProcessLocked來創(chuàng)建新的進(jìn)程墨礁,對(duì)于startActivity來啟動(dòng)的情況癌瘾,這一步不需要執(zhí)行,直接在原來Activity所在的進(jìn)程中啟動(dòng)饵溅。
6:ActivityManagerService調(diào)用Application Thread.scheduleLaunchActivity接口妨退,通知相應(yīng)的進(jìn)程啟動(dòng)Activity;
7:Application Thread把這個(gè)啟動(dòng)Activity的操作轉(zhuǎn)發(fā)給ActivityThread,ActivityThread通過ClassLoader導(dǎo)入相應(yīng)的Activity類蜕企,然后啟動(dòng)起來了咬荷。
安裝過程:
復(fù)制APK安裝包到/data/app目錄下,
解壓并掃描安裝包轻掩,
向資源管理器注入APK資源幸乒,
解析manifest文件,
在data/data目錄下創(chuàng)建應(yīng)用數(shù)據(jù)目錄唇牧,
針對(duì)dalvik環(huán)境優(yōu)化dex文件罕扎,
保存到dalvik-cache目錄,
將manifest文件解析出的組件權(quán)限注冊(cè)到packgeManagerService并發(fā)送廣播丐重。
47:binder機(jī)制原理
48:flutter原理優(yōu)勢(shì)扮惦,kotlin協(xié)程
flutter都是write once臀蛛,run everywhere。
Flutter崖蜜,基于Dart語言浊仆,基于獨(dú)有的圖形引擎Skia,不需要要橋接豫领,不基于webkit抡柿,解決比較徹底。
摒棄JSBridge等恐,F(xiàn)lutter是直接編譯成本地代碼洲劣,用skia渲染展示。熱重載hot reload鼠锈,jsBridge需要build打包闪檬。flutter不支持熱更新,適合整體app開發(fā)购笆。
49:冒泡排序&手寫單例
冒泡:
public static void main(String[] arg) {
int arry[] = {2, 3, 1, 4};
for (int i = 0; i < arry.length; i++) {
boolean isOver = false;
for (int j = 1; j < arry.length - i; j++) {
if (arry[j - 1] > arry[j]) {
int temp = arry[j - 1];
arry[j - 1] = arry[j];
arry[j] = temp;
isOver = true;
}
}
if (!isOver) {
break;
}
}
for (int num : arry) {
System.out.println(num);
}
}
單例:(餓漢式)
public class Singleton {
// 直接創(chuàng)建對(duì)象
public static Singleton instance = new Singleton();
// 私有化構(gòu)造函數(shù)
private Singleton() {
}
// 返回對(duì)象實(shí)例
public static Singleton getInstance() {
return instance;
}
}