呻待、主要分為以下幾部分:
(1)java面試題
(2)Android面試題
(3)高級開發(fā)技術面試題
(4)跨平臺Hybrid 開發(fā)
一腊徙、java面試題
熟練掌握java是很關鍵的粉私,大公司不僅僅要求你會使用幾個api正什,更多的是要你熟悉源碼實現(xiàn)原理泛源,甚至要你知道有哪些不足篙挽,怎么改進冲秽,還有一些java有關的一些算法舍咖,設計模式等等。
(一) java基礎面試知識點
java中==和equals和hashCode的區(qū)別
equals是Object的方法可以重寫 锉桑,僅僅用來判斷兩個對象的值
==是操作符排霉,主要用來判斷兩個對象的地址
hashCode用來獲取對象的哈希碼,用于確定對象在哈希表中的位置民轴。
int攻柠、char、long各占多少字節(jié)數(shù)
一個字節(jié)占8位:
char:1個字節(jié)后裸,8位
short:2字節(jié)瑰钮,16位
int:4個字節(jié),32位
long:8個字節(jié)微驶, 64位
int與integer的區(qū)別
int是值類型浪谴,Integer是引用類型
Integer必須實例化后才能使用,而int不需要
int默認是0因苹,Integer默認是null
探探對java多態(tài)的理解
多態(tài)的定義:同一消息可以根據(jù)發(fā)送對象的不同而采用多種不同的行為方式
多態(tài)的好處:消除類型之間的耦合關系
多態(tài)的條件:要有繼承较店,要有重寫,父類引用指向子類對象
String容燕、StringBuffer梁呈、StringBuilder區(qū)別
1:是否從可變的角度
String是final類既不允許繼承也不允許改變對象
StringBuffer、StringBuilder 都繼承AbstractStringBuilder蘸秘,沒有final修飾官卡,對象可變
2、從線程安全角度來看
String因為被final修飾因此不可變醋虏,自然也就是線程安全的
StringBuffer 內部append方法添加了同步鎖synchronized 寻咒,因此它也是線程安全的
StringBuilder內部append方法沒有同步鎖,因此它不是線程安全的
什么是內部類颈嚼?內部類的作用
定義:可以把一個類定義到另一個類的內部毛秘,當作外部類的成員,這個類就叫做內部類
作用:根據(jù)內部類的分類說一下各個內部類的作用
? ? ? ? 成員內部類:可以訪問外部類的所有方法、屬性叫挟、甚至包括私有方法屬性艰匙。
? ? ? ? 局部內部類:定義在某個方法或者一個作用域里面的類,只能訪問該方法或者作用域里面的對象
? ? ? ? 靜態(tài)內部類:不依賴于外部類而存在抹恳,只能訪問外部類的靜態(tài)成員
? ? ? ? 匿名內部類:無名內部類员凝,常見于定義控件事件中
抽象類和接口區(qū)別
默認方法實現(xiàn):抽象類可以有默認方法實現(xiàn),接口沒有
訪問修飾符:抽象類public奋献、protected健霹;接口只能public
構造器:抽象類可以有構造器,接口沒有
抽象類的意義
1瓶蚂、為子類提供一個公共的類型
2糖埋、封裝子類中重復的方法和屬性
3、定義有抽象方法窃这,子類雖然有不同的實現(xiàn)阶捆,但該方法的定義是一致的
抽象類與接口的應用場景
如果你擁有一些方法并且想讓它們中的一些有默認實現(xiàn),那么使用抽象類吧钦听。
如果你想實現(xiàn)多重繼承洒试,那么你必須使用接口。由于Java不支持多繼承朴上,子類不能夠繼承多個類垒棋,但可以實現(xiàn)多個接口。因此你就可以使用接口來解決它痪宰。
如果基本功能在不斷改變叼架,那么就需要使用抽象類。如果不斷改變基本功能并且使用接口衣撬,那么就需要改變所有實現(xiàn)了該接口的類
抽象類是否可以沒有方法和屬性乖订?
可以
接口的意義
使用接口可以達到一定的解耦和作用,比如:我們在接口中定義一個變量具练,所有繼承它的子類乍构,都用到這個變量,那么當需求改變時只需要修改著一個變量即可扛点;
解決java中不能多繼承的缺點
泛型中extends和super的區(qū)別
<? extends T>限定參數(shù)類型的上界:參數(shù)類型必須是T或T的子類型
<? super T> 限定參數(shù)類型的下界:參數(shù)類型必須是T或T的超類型
父類的靜態(tài)方法能否被子類重寫
父類的靜態(tài)方法可以被子類繼承哥遮,但是不能被重寫
進程和線程的區(qū)別
進程是指一個執(zhí)行單元,一般指一個程序或者應用
線程是cpu調度的最小單元陵究,主要用于執(zhí)行耗時操作眠饮,一個進程可以有多個線程
final,finally铜邮,finalize的區(qū)別
final:修飾符仪召,使用final修飾的類寨蹋、方法、屬性不能被繼承扔茅、重寫和改變變量的值
finally:作為異常處理的一部分已旧,通常配合try catch一起使用,標識最終被執(zhí)行的意思
finalize:Object的一個方法咖摹,意為假定該對象被回收评姨,什么意思呢难述?我們先了解一下java中垃圾回收器(GC)的工作原理萤晴,我們都知道java中的GC只回收JVM分配的內存,如果對象使用jni底層c胁后、c++來進行分配的內存那么finalize就是負責回收這部分內存的店读,在GC工作時先調用finalize()方法,并在下一次垃圾回收發(fā)生攀芯,才真正回收該對象占用的內存屯断。
Serializable 和Parcelable 的區(qū)別
????????????????????????????????????Serializable? ? ? ? ?????????????????????????Parcelable? ? ? ? ? ? ? ? ? ?
? ? ? ? ? 平臺:? ? ? ? ? ? ? ?java自帶? ? ? ? ? ? ? ? ????????????????????????Android自帶
序列化原理:? ? ? ? ? ? ? ?將對象轉化為可存儲的狀態(tài) ????????將對象進行分解,分解的部門都是傳遞可支持的數(shù)據(jù)類型
? ? ? ?優(yōu)缺點:? ? ? ? ? ? ? ?簡單但是效率低? ? ? ? ? ? ? ? ? ? ? ? ? ?高效但是使用復雜
靜態(tài)屬性和靜態(tài)方法是否可以被繼承侣诺?是否可以被重寫殖演?以及原因?
可以被繼承年鸳,但是不能被重寫趴久,靜態(tài)屬性和方法只屬于當前類。通過類名.屬性搔确,類名.方法()調用
靜態(tài)內部類的設計意圖
非靜態(tài)內部類在創(chuàng)建的時候會持有外部的引用彼棍,而靜態(tài)內部類沒有
因此非靜態(tài)內部類有兩個重要的作用:
1、它的創(chuàng)建不需要外圍膳算,不支持外部類的引用
2座硕、靜態(tài)內部類不能訪問外部任何非靜態(tài)屬性和方法
談談對kotlin的理解
1、kotlin是一門靜態(tài)語言涕蜂,支持多種平臺 移動端华匾、服務端、以及瀏覽器端
2机隙、空安全的語言瘦真,支持泛型,空指針的判斷黍瞧,支持與java進行完全的交互
3诸尽、代碼末尾沒有分號、被調用的方法放在上邊等特點
閉包和局部內部類的區(qū)別
閉包是一個可調用的對象印颤,它包含了一些信息您机,這些信息來自創(chuàng)建它的作用域,就是我們常見的lambda 表達式()=>{ 作用域 };
局部內部類是定義在某個方法或者某個局部中的類,它只能訪問該方法中的變量
string 轉換成 integer的方式及原理
1际看、循環(huán)調用string的每個字符的十進制數(shù)值
2咸产、通過*=或/=進行計算拼接
3、最后判斷是否為正負值仲闽,返回結果
(二) java深入源碼級的面試題(有難度)
哪些情況下的對象會被垃圾回收機制處理掉脑溢?
GC確定哪些對象回收有兩種算法:
1、引用計數(shù)法
對象頭處維護了一個引用計數(shù)去counter一個對象被引用一次計數(shù)器就會+1赖欣,不會引用就會-1屑彻,為0的時候GC工作的時候就會被回收,但是它不能解決循環(huán)引用帶來的問題
2顶吮、可達性算法
java默認的垃圾回收算法社牲,虛擬機會先將一些對象定義為 GC Roots,沿著GC Roots向下尋找悴了,如果對象不能通過GC Roots尋找到搏恤,那么虛擬機就認為該對象是被回收的
講一下常見編碼方式?
ASCII:我理解為中文中的GB2312湃交,使用8為二進制來表示字母和字符
UTF-8:英文一個字符一個字節(jié)熟空,中文占用3/4字節(jié)
UTF-16:定長編碼,所有字符占兩個字節(jié)
utf-8編碼中的中文占幾個字節(jié)搞莺;int型幾個字節(jié)息罗?
中文少數(shù)占3個字節(jié),多數(shù)占4個字節(jié)腮敌,int型數(shù)字占1個字節(jié)
靜態(tài)代理和動態(tài)代理的區(qū)別阱当,什么場景使用?
靜態(tài)代理:在程序運行前已經(jīng)存在的糜工,提前寫好的弊添。代理類和委托類的關系提前確定好的。
優(yōu)點:業(yè)務只關注業(yè)務本身捌木,專一性
缺點:代理對象只能服務一種類型的對象油坝,代理需要新的方法,每個委托都要實現(xiàn)
動態(tài)代理:源碼在運行期間JVM根據(jù)反射等機制動態(tài)的生成
Java的異常體系
最近在看java編程思想刨裆,根據(jù)自己編碼經(jīng)歷澈圈,談談對異常的理解:
首先我們都知道java每個對象都有一個異常的超類Throwable,它由兩個子類Error(錯誤)和Exception(異常)
Error:嚴重的不可處理的異常帆啃,會導致程序直接掛掉瞬女,比如內存溢出、類定義錯誤等
Exception:可處理異常努潘,可以捕獲并處理诽偷,比如對象空指針坤学,文件找不到路徑等
????????????運行時異常:時在程序運行前編譯前檢查語法錯誤來提醒
? ? ? ? ? ??編譯時異常:主要是程序在運行后出現(xiàn)的邏輯錯誤或者內存溢出而導致的異常,?
1报慕、除非你能解決處理異常深浮,否則不要捕獲它,如果是記錄錯誤消息眠冈,別忘了把它在拋出去
2飞苇、異常即代表一種錯誤 也代表一種消息
Java中實現(xiàn)多態(tài)的機制是什么?
多態(tài)的實現(xiàn)有三個必要條件:
繼承:再多態(tài)中必須有繼承關系的子類蜗顽、父類
重寫:子類重寫父類中的方法布卡,調用這些方法就會調用子類的方法
向上轉型:將子類的引用賦給父類,這樣可以調用父類中的方法诫舅,和父類中沒有羽利,子類中有的方法
如何將一個Java對象序列化到文件里宫患?
FileOutputStream fileOutputStream = new FileOutputStream("d://test.out");
ObjectOutputStream objectOutputStream= new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject("object");
objectOutputStream.close();?
說說你對Java反射的理解
定義:反射就是程序運行時動態(tài)的獲取類和對象的方法或者屬性
作用:通過反射刊懈,我們可以獲取相應的屬性和方法或者資源,比如我們在程序中想獲取第三方的資源文件娃闲,就不能通過R.id的方式獲取虚汛,必須通過反射才能拿到資源文件
使用:可以通過對象.getClass()、類.class皇帮、Class.forName("")
說說你對Java注解的理解
定義:注解也稱為元數(shù)據(jù)卷哩,是一種代碼的級別說明,聲明在包属拾、類、字段、方法舔示、局部變量粪狼、方法參數(shù)等前面,來對這些元素進行說明纯衍,注釋等
作用:
?1)編寫文檔:通過代碼里的標識的元數(shù)據(jù)生成文檔【生成文檔doc文檔】
2)代碼分析:通過代碼里的標識的元數(shù)據(jù)對代碼進行分析【使用反射】
3)編譯檢查:通過代碼里的標識的元數(shù)據(jù)讓編譯器能過實現(xiàn)基本的編譯檢查
java提供了四種元注解:
1.@Target,:規(guī)定注解所修飾的對象范圍
2.@Retention:表示注解的生命周期
3.@Documented:用于描述
4.@Inherited:主要說明了一種繼承性栋齿,子類可以繼承父類注解
說說你對依賴注入的理解
我理解的依賴注入是你不需要關心對象的生命周期,什么時候調用襟诸、銷毀等過程瓦堵,只需要關注,調用它的外部類即可:
代碼舉例說明:對象注入歌亲、屬性注入
說一下泛型原理菇用,并舉例說明
泛型的本質是參數(shù)化類型,它可以用在接口陷揪,方法和類中惋鸥,泛型接口泉唁、泛型方法、泛型類
比如List<String>:
1揩慕、它的好處就是在編譯時期就幫我們檢查類型是否安全亭畜,不需要運行,并且所有的強轉都是自動和隱士的迎卤,效率高
Java中String的了解
String為什么要設計成不可變的拴鸵?
final修飾,不可被繼承蜗搔,不可被重寫劲藐,類型安全,
Object類的equal和hashCode方法重寫樟凄,為什么聘芜?
1、如果兩個對象的equal相同缝龄,那么hashCode一定相同汰现,
2、如果hashCode相同叔壤。equal并不一定相同
如果equal重寫瞎饲,hashCode沒有被重寫,可能會導致兩個沒有關系的對象equal相同炼绘。
(四) 線程嗅战、多線程和線程池
開啟線程的三種方式?
繼承Thread類俺亮,調用run()或start()方法
實現(xiàn)Runnable接口驮捍,調用run()方法? ? ?沒有返回值,不能進行容錯處理
Callable接口實現(xiàn)類脚曾,調用call()實現(xiàn)? ? ? 有返回值东且,并且能容錯處理,拋出錯誤信息
線程和進程的區(qū)別斟珊?
進程是程序的執(zhí)行單元苇倡,一般指一個應用或程序
線程是cpu調度的最小單元,是一種有限的系統(tǒng)資源囤踩,分為UI線程和子線程
一個進程可以有多個線程旨椒。
為什么要有線程,而不是僅僅用進程堵漱?
進程的缺點:
????進程在同一時間只能干一件事综慎,如果同時干多件事就無能為力
????進程在處理任務一旦遇到阻塞,當前程序就會掛起勤庐,下一步操作就無法繼續(xù)進行
線程的優(yōu)點:
? ? 減少程序的響應時間示惊,同時執(zhí)行多個耗時操作好港,充分利用系統(tǒng)資源,避免閑置浪費米罚。
run()和start()方法區(qū)別
我們首先來了解一下線程的五個狀態(tài):
創(chuàng)建:new Thread(new Runnable);這是線程的創(chuàng)建階段钧汹,等待被執(zhí)行
就緒:調用線程的start()方法,當前線程就會告知虛擬機我已準備就緒录择,由JVM進行調度
運行:線程會調用實現(xiàn)runnable的run()方法拔莱,此時線程才真正執(zhí)行
阻塞:執(zhí)行過程中的暫停等操作。sleep
死亡:run方法執(zhí)行完畢隘竭,線程死亡
總結:start()方法只是讓線程處于就緒狀態(tài)塘秦,告訴cpu我已準備好了,請開始執(zhí)行动看,然后調用run方法按順序執(zhí)行尊剔。
如何控制某個方法允許并發(fā)訪問線程的個數(shù)?
java中有一個叫做信號量的類Semaphore菱皆,負責控制線程的載入须误、釋放以及最大并發(fā)訪問的個數(shù),只需要在構造函數(shù)中傳入一個最大的并發(fā)數(shù)就可以搔预。
在Java中wait和sleep方法的不同霹期;
sleep:睡眠叶组,一直持有鎖拯田,事件過后任務繼續(xù)執(zhí)行,Thread方法
wait:等待甩十,會釋放鎖船庇,需要notify()喚醒才能繼續(xù)持有,Object方法
什么導致線程阻塞侣监?
Thread.sleep() 線程睡眠
Object.wait() 線程等待
Thread.yeild() 線程禮讓
Thread.join() 線程自閉
線程如何關閉鸭轮?
通常情況下線程運行完畢會自動結束,但是有時候需要提前讓用戶取消操作等橄霉。
1窃爷、通過退出標識,自定義一個isFlag標識姓蜂,在Run方法中進行判斷
2按厘、?線程提供interrupted()方法判斷線程是否已經(jīng)中斷來停止
講一下java中的同步的方法
java允許多線程并發(fā)操作,在多線程并發(fā)中同時操作一個可共享的變量是容易造成數(shù)據(jù)不準確钱慢,比如數(shù)據(jù)庫增刪查改逮京,java引入同步來保持數(shù)據(jù)的一致性final:變量的唯一性,不可變synchronized:作用域代碼塊束莫,方法懒棉,通過線程互斥草描,同一時間只允許一個線程操作。Volatile:修飾變量變化保證立即對線程可見
數(shù)據(jù)一致性如何保證策严?
java允許多線程并發(fā)操作穗慕,在多線程并發(fā)中同時操作一個可共享的變量是容易造成數(shù)據(jù)不準確,比如數(shù)據(jù)庫增刪查改妻导,java引入同步來保持數(shù)據(jù)的一致性
final:變量的唯一性揍诽,不可變
synchronized:作用域代碼塊,方法栗竖,通過線程互斥暑脆,同一時間只允許一個線程操作。
Volatile:修飾變量變化保證立即對線程可見
如何保證線程安全狐肢?
java中死鎖和臟數(shù)據(jù)就是典型的線程安全問題添吗,只有存在共享數(shù)據(jù)時才需要考慮線程安全問題
synchronized:作用域代碼塊,方法份名,通過線程互斥碟联,同一時間只允許一個線程操作。Volatile:修飾變量變化保證立即對線程可見
如何實現(xiàn)線程同步僵腺?
三種方式:
synchronized 同步代碼塊鲤孵,同一時間只允許一個線程操作
Lock,手動獲取鎖辰如,釋放鎖
synchronized? 通過方法普监。
兩個進程同時要求寫或者讀,能不能實現(xiàn)琉兜?如何防止進程的同步凯正?
線程間操作List
多線程操作list容易引起并發(fā)操作導致數(shù)據(jù)的不一致性,
Java中對象的生命周期
1.??????創(chuàng)建階段(Created) New一個對象豌蟋,有jvm分配內存
2.??????應用階段(In Use)? 至少被一個強引用持有
3.??????不可見階段(Invisible)? ?是指該對象不在當前作用域中被訪問廊散,編譯直接報錯
4.??????不可達階段(Unreachable)? 不再持有,但是會被靜態(tài)變量或者jni底層引用
5.??????收集階段(Collected)?
6.??????終結階段(Finalized)??對象運行完finalize()等待被回收
7.??????對象空間重分配階段(De-allocated)?對象徹底消失了
Synchronized用法
Synchronized(this){代碼塊}:其他想要訪問此處代碼時梧疲,會被阻塞
public syncchronized void method(){...} 修飾一個方法允睹,表示其他任務訪問該方法會被阻塞
synchronize的原理
Java對象頭和monitor是實現(xiàn)synchronized的基礎
對象頭:通過對象頭來確定對象是哪個類的實例
monitor:對象監(jiān)視器,用來監(jiān)視對象狀態(tài)幌氮,它是一種同步機制
談談對Synchronized關鍵字缭受,類鎖,方法鎖浩销,重入鎖的理解
Synchronized是同步的一種機制贯涎,主要用來解決并發(fā)訪問同一對象所造成的安全問題。
Synchronized 修飾靜態(tài)方法獲取到的就是類鎖慢洋,修飾整個類
Synchronized 修飾代碼塊修飾一個方法獲取到的就是方法鎖塘雳,修飾當前方法
沖入所:子類繼承父類的方法陆盘,子類父類都有方法鎖,
static synchronized 方法的多線程訪問和作用
static? synchronized標識當前鎖的整個類的靜態(tài)方法败明,修飾的是整個類隘马,也成為類鎖。
作用:它可以對類的所有對象實例起作用妻顶,
同一個類里面兩個synchronized方法酸员,兩個線程同時訪問的問題
不能同步執(zhí)行,多線程同時訪問同一個類的兩個synchronized方法時讳嘱,jvm會檢測到當前類對象前面的synchronized關鍵字幔嗦,會對對象ID加鎖,因此沥潭,兩個線程同時訪問邀泉,會等待一個執(zhí)行完成才能執(zhí)行另一個。
談談volatile關鍵字的作用
禁止指令重排钝鸽,修飾變量變化立即對線程可見汇恤,線程每次使用的時候都會使用修改后的值
synchronized 和volatile 關鍵字的區(qū)別
synchronized 作用于方法,代碼塊拔恰,volatile只能修飾變量
synchronized 會造成線程阻塞因谎,volatile不會
synchronized只要用于并發(fā)操作是保證數(shù)據(jù)的唯一性,volatile主要是變量變化時立馬對其他線程可見颜懊。
synchronized與Lock的區(qū)別
synchronized 時java內置鎖财岔,Lock不是java內置
synchronized不需要用戶去手動的釋放鎖,使用完后會自動釋放饭冬,Lock需要用戶手動釋放使鹅,不手動釋放會造成死鎖現(xiàn)象
ReentrantLock 、synchronized和volatile比較
ReentrantLock的內部實現(xiàn)
lock原理
死鎖的四個必要條件昌抠?
互斥:某個資源一次只能有一個進程訪問,其他進程需要先等待
占有且等待鲁僚,當前進程本身占有著一種資源炊苫,同時也需要其他進程正在訪問的其他資源,需要等待
不可搶占:別人已經(jīng)占有冰沙,不可使用
循環(huán)等待:
怎么避免死鎖侨艾?
1、避免一個線程同時獲取多個鎖拓挥;
2唠梨、避免一個線程在鎖內同時占用多個資源,盡量保證每個鎖只占用一個資源
對象鎖和類鎖是否會互相影響侥啤?
類鎖和對象鎖不是同1個東西当叭,一個是類的Class對象的鎖茬故,一個是類的實例的鎖。也就是說:1個線程訪問靜態(tài)synchronized的時候蚁鳖,允許另一個線程訪問對象的實例synchronized方法磺芭。反過來也是成立的,因為他們需要的鎖是不同的
什么是線程池醉箕,如何使用?
線程池就是將任務添加到隊列中順序或并發(fā)執(zhí)行的一個集合钾腺,android線程池一般有這幾個參數(shù):核心線程數(shù),緩沖線程數(shù)讥裤,最大線程數(shù)
Java的并發(fā)放棒、多線程、線程模型
談談對多線程的理解
優(yōu)點:多線程可以處理耗時操作己英,方便多任務同時執(zhí)行哨查,比如網(wǎng)絡操作,后臺下載等剧辐。
缺點:線程是一種有限的系統(tǒng)資源寒亥,因此,需要避免大量線程的開銷以及內存泄漏
多線程有什么要注意的問題荧关?
多線程是一種有限的系統(tǒng)資源溉奕,大量的創(chuàng)建會導致資源消耗,盡量使用線程池
Android中容易引起內存泄漏:持有外部類的引用忍啤。
談談你對并發(fā)編程的理解并舉例說明
cpu在同一時間只能處理一件事加勤,因此并發(fā)看似是同時執(zhí)行,實際上實在不停的切換進程
談談你對多線程同步機制的理解同波?
線程同步是一種安全機制鳄梅,它主要是解決多線程同時訪問統(tǒng)一資源導致的數(shù)據(jù)安全問題。
synchronized未檩;volatile
如何保證多線程讀寫文件的安全戴尸?
多線程 同時訪問同一個文件回導致數(shù)據(jù)安全問題,因此可以使用同步鎖來解決這種問題冤狡。
可以使用synchronzied來保證在同一時間只能由一個線程來操作
斷點續(xù)傳原理及實現(xiàn)
斷點續(xù)傳分為單線程斷點續(xù)傳和多線程斷點續(xù)傳孙蒙,
單線程斷點續(xù)傳:比較簡單,至開啟一個線程下載某一個文件起始位置是0-文件總大小悲雳,網(wǎng)絡斷開記住當前所下載的位置挎峦,下次下載重新定義http的Range
多線程斷點續(xù)傳:開啟多個線程同時下載某個文件中的某一個部分,舉例說明
實現(xiàn):
不管是單線程還是多線程都要用到:
1合瓢、斷點續(xù)傳需要指定http的Range和Content-Rang
2坦胶、如果檢測到網(wǎng)絡斷開則要記錄當前下載的位置也就是Range,等待下次重新連接的時候,指定當前Range?
二顿苇、Android面試題
Android面試題包括Android基礎峭咒,還有一些源碼級別的、原理這些等岖圈。所以想去大公司面試讹语,一定要多看看源碼和實現(xiàn)方式,常用框架可以試試自己能不能手寫實現(xiàn)一下蜂科,鍛煉一下自己顽决。
(一)Android基礎知識點
四大組件是什么
Activity:Service:BoradcastReceiver:ContentProvider:
四大組件的生命周期和簡單用法
Activity之間的通信方式
1、通過Intent傳遞导匣,大小限制1Mb
2才菠、通過類靜態(tài)變量
3、通過全局變量
4贡定、通過SharedPreferences赋访、文件等用的較少
Activity各種情況下的生命周期
橫豎屏切換的時候,Activity 各種情況下的生命周期
橫屏:onSaveInstanceState->onPause()->onStop->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()
豎屏:橫屏*2
對android:configChanges屬性缓待,一般認為有以下幾點:
1蚓耽、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期旋炒,切橫屏時會執(zhí)行一次步悠,切豎屏時會執(zhí)行兩次
2、設置Activity的android:configChanges="orientation"時瘫镇,切屏還是會重新調用各個生命周期鼎兽,切橫、豎屏時只會執(zhí)行一次
3铣除、設置Activity的android:configChanges="orientation|keyboardHidden"時谚咬,切屏不會重新調用各個生命周期,只會執(zhí)行onConfigurationChanged方法?
Activity與Fragment之間生命周期比較
Activity:onCreate尚粘、onStart择卦、onResume、onPause背苦、onStop、onDestroy行剂、onRestart
Fragment:
onAttach(與Activyty關聯(lián)時調用)、 onCreate钳降、onCreateView(創(chuàng)建Fragment視圖時調用)厚宰、onActivityCreated(Activity 的Create方法調用時調用)
onStart、
onResume、
onPause铲觉、
onStop澈蝙、
onDestroyView(Fragment視圖被移除時調用)、onDestroy撵幽、onDetach(與Activity取消關聯(lián)時調用)
Activity上有Dialog的時候按Home鍵時的生命周期
onPause()灯荧、onStop()
兩個Activity 之間跳轉時必然會執(zhí)行的是哪幾個方法?
A:onPause盐杂、B:onCreate逗载、onStart某弦、onResume洲赵、A:onStop
前臺切換到后臺申窘,然后再回到前臺敞临,Activity生命周期回調方法抗果。
A->B:
A:onPause端盆、B:onCreate切黔、onStart暮的、onResume漩勤、A:onStop
B返回A:
B:onPause感挥、A:onRestart、onStart越败、onResume触幼、B:onStop、onDestroy
彈出Dialog眉尸,生命值周期回調方法域蜗。
A:onPause、B:onCreate噪猾、onStart霉祸、onResume
Activity的四種啟動模式對比
standard:默認模式,每次都會創(chuàng)建一個新的頁面
singleTop:棧頂模式袱蜡,創(chuàng)建時優(yōu)先檢查棧頂是否存在相同的活動丝蹭,有展示,沒有創(chuàng)建
singleTask:棧內模式坪蚁,創(chuàng)建時優(yōu)先檢查棧內是否存在相同的活動奔穿,有展示并清除當前活動以上所有頁面,沒有創(chuàng)建
singleInstance:單利模式敏晤,存在于單獨的棧中贱田,且只有一個實例
Activity狀態(tài)保存于恢復
一般我們指的狀態(tài)保存和恢復是指的非正常狀態(tài)下的activity生命周期
onSaveInstanceState
onRetoreInstanceState
如何實現(xiàn)Fragment的滑動?
Fragment和Viewpager配合使用
給Viewpager設置setAdapter和setOnPageChangeListener即可
fragment之間傳遞數(shù)據(jù)的方式嘴脾?
調用getFragmentManager()的findFragmentById()獲取fragment對象男摧,根據(jù)對象調用方法來實現(xiàn)
Activity 怎么和Service 綁定蔬墩?
Activity-Intent-Service
bindService(new Intent(Activity,Service.class),)
怎么在Activity 中啟動自己對應的Service?
startService(new Intent(...))
service和activity怎么進行數(shù)據(jù)交互耗拓?
通過Intent進行傳值
Service的開啟方式 以及Service 的生命周期
startService:
startService拇颅、onCreate、onStart乔询、service running樟插、onStop、onDestroy
bindService竿刁、onCreate黄锤、onBind、service running们妥,onUnBind猜扮,onDestroy
談談你對ContentProvider的理解
定義:
ContentProvider它是一種數(shù)據(jù)共享性組件,用戶向其他組件乃至其他應用共享數(shù)據(jù)监婶,和廣播一樣無法被用戶感知旅赢,他內部需要實現(xiàn)增刪查改方法,內部維護了一個數(shù)據(jù)集合惑惶,通過數(shù)據(jù)庫來實現(xiàn)
日常開發(fā):自定義類繼承ContentProvider煮盼,實現(xiàn)增刪查改方法,處理好線程同步带污,對外實現(xiàn)URL來實現(xiàn)僵控。
說說ContentProvider、ContentResolver鱼冀、ContentObserver 之間的關系
ContentProvider 內容提供者报破,向外提供共享數(shù)據(jù)
ContentResolver:內容解析者,對內容提供者提供的數(shù)據(jù)進行分析
ContentObserver:內容觀察者千绪,觀察內容在各個階段的狀態(tài)
請描述一下廣播BroadcastReceiver的理解
1充易、BroadcastReceiver 時一種消息型組件,在不同組件乃至不同應用之間傳遞消息荸型,無法被用戶感知盹靴,因為它工作在系統(tǒng)內部,
2瑞妇、廣播有兩種注冊方式:靜態(tài)注冊和動態(tài)注冊稿静。生命周期也根據(jù)注冊不同
3、廣播默認運行在主線程中辕狰,不支持耗時操作改备。
廣播的分類
有序廣播:消息的照發(fā)送的順序接收
無序廣播:所有設備幾乎在同一時刻接收到廣播
本地廣播:只能在當前應用中接收到廣播
粘性廣播:先發(fā)送,后注冊
在manifest 和代碼中如何注冊和使用BroadcastReceiver?
靜態(tài)注冊:mainfest中<receiver android:name=".MyReceiver">action</receiver>
動態(tài)注冊:regeisterReceiver(new MyReceiver(),filter);
廣播發(fā)送的原理:
1蔓倍、首先自定義一個廣播接收者BroadcastRecevier绍妨,并重寫onReceiver()润脸;
2柬脸、通過Binder機制像AMS進行注冊他去;
3、廣播發(fā)送者通過Binder機制向AMS發(fā)送廣播倒堕;
4灾测、AMS查找符合條件的廣播,并發(fā)送到消息循環(huán)隊列中垦巴;
5媳搪、消息循環(huán)拿到此廣播并回調onReceiver()方法。
Application 和 Activity 的 Context 對象的區(qū)別
生命周期不同:
Application的Context代表的是整個應用程序的生命周期骤宣,Activity的Context代表的是當前Activity的生命周期秦爆。
Android屬性動畫工作原理
在一定時間間隔內,通過不斷對值進行改變憔披,并不斷將該值賦給對象的屬性等限,從而實現(xiàn)該對象在該屬性上的動畫效果
如何導入外部數(shù)據(jù)庫?
1、將外部數(shù)據(jù)庫放到文件目錄assets中芬膝,
2望门、通過InputStream讀取外部數(shù)據(jù)庫,通過FileOutputStream導入內部數(shù)據(jù)庫
3锰霜、需要注意外部數(shù)據(jù)庫與我們新建的數(shù)據(jù)庫屬性和數(shù)據(jù)類型要一致
LinearLayout筹误、RelativeLayout、FrameLayout的特性及對比癣缅,并介紹使用場景厨剪。
RelativeLayout 會橫向,縱向進行兩次測量友存,也就是執(zhí)行兩次measure祷膳,效率肯定相對底
LinearLayout 線性布局,從上往下的順序繪制元素爬立,如果LinearLayout 有weight屬性钾唬,也會執(zhí)行兩次measure
FrameLayout 無法控制子元素的位置,全部堆在左上角侠驯,無法改變抡秆。
談談對接口與回調的理解
接口的實現(xiàn)很簡單,?
1吟策、定義接口儒士,編寫回掉方法,給接口賦值
我們想象平時為什么需要接口
1檩坚、傳值着撩,利用接口傳值诅福,我們不關心過程只關心結果,
2拖叙、接口回調可以理解為一種設計模式氓润,類似于觀察者,程序負責項目大的時候薯鳍,有利于頁面之間的解耦
介紹下SurefaceView
1咖气、SurefaceView主要在被動的情況下更新,
2挖滤、SurefaceView主要在子線程中進行崩溪,常用于平凡刷新以及刷新是數(shù)據(jù)量大的情況下
3、SurefaceView底部采用了雙緩存機制斩松,常見的視頻播放伶唯。
RecycleView的使用
recyckeView.setLayoutManager(設置布局管理器,支持三種:橫/縱向惧盹,流式布局乳幸,瀑布流);
recyckeView.setAdapter(設置適配源)
//也可以設置分割線、動畫等
序列化的作用岭参,以及Android兩種序列化的區(qū)別
序列化是指將對象轉化為文件存儲在本地存儲中的操作反惕,主要是為了保存對象的狀態(tài)
Serializable:java自帶,使用簡單演侯,但是要重復讀寫內存姿染,效率低
Parcelable:android自帶,使用復雜秒际,重復利用內存悬赏,效率高。
插值器
android中的插值器主要是為了實現(xiàn)動畫的非線性需求而定義的娄徊,例如加減速等
估值器
協(xié)助插值器 實現(xiàn)非線性運動的動畫效果
Android中數(shù)據(jù)存儲方式
sharedpreferences:android提供的基于key闽颇、value保存在xml文件中的存儲方式,基本數(shù)據(jù)類型等寄锐。非線程安全
文件存儲:將對象采用序列化的方式保存到本地
sqlite:數(shù)據(jù)庫存儲
contentprovider:通過程序之間共享數(shù)據(jù)存儲:
網(wǎng)絡云存儲:
(二)Android源碼相關分析
invalidate和postInvalidate的區(qū)別及使用
invalidate在主線程中使用兵多,通知UI更新View
postInvalidate在子線程中調用,通知UI更新View橄仆,底層通過Handler來通知UI更新
Activity-Window-View三者的差別
1剩膘、Activity 創(chuàng)建時通過attach()初始化了
2、一個 Window 一個 Window 持有一個 DecorView 的實例盆顾,DecorView 本身是一個 FrameLayout怠褐,繼承于View, 3您宪、Activty通過setContentView將xml布局控件不斷addView()添加到View中奈懒,最終顯示到Window于我們交互奠涌;
談談對Volley的理解
google推出的異步網(wǎng)絡框架,還能加載圖片磷杏,適合請求量小
使用:
1溜畅、將網(wǎng)絡請求添加到RequestQueue中
2、RequestQueue中有兩個分發(fā)器:CacheDispatch(緩存分發(fā)器)和NetworkDispatch(網(wǎng)絡分發(fā)器)茴丰,其實就是開啟兩個線程
3达皿、網(wǎng)絡請求會有優(yōu)先從緩存中獲取,如果緩存中沒有就開啟一個networkdispatch贿肩,并且將請求添加到cachediapatch中,
4龄寞、將請求結果傳遞到主線程汰规。
如何優(yōu)化自定義View
優(yōu)化自定義view可以從兩個方面考慮:
1、減少invaildate調用次數(shù)物邑,invaildate在主線程中運行溜哮,調用它會執(zhí)行view的onDraw方法,造成UI卡頓
2色解、requestLayout操作非常耗時茂嗓,因為執(zhí)行requestLayout會使android Ui系統(tǒng)遍歷整個view層級來計算view大小
3、如果UI復雜科阎,可以考慮使用ViewGroup述吸,與view不同的是,自定義view僅僅測量一部分
低版本SDK如何實現(xiàn)高版本api锣笨?
低版本使用高版本的api最常見的是編譯報錯蝌矛,android為開發(fā)者提供了避免編譯報錯的解決方案,那就是注解:
@SuppressLint(newApi)
讓編譯器忽略所有對新api版本的調用檢查
@TargetApi(11)
讓編譯器忽略對特定版本的便宜檢查
描述一次網(wǎng)絡請求的流程
1错英、通過url找到IP
2入撒、根據(jù)IP簡歷TCP連接(三次握手)
3、向服務器發(fā)送數(shù)據(jù)
4椭岩、服務器解析并返回結果
5茅逮、對結果進行處理
Bitmap對象的理解
Bitmap核心思想有三個:高效加載,緩存策略判哥,性能優(yōu)化献雅;
高效加載:在不影響圖片顯示的情況下,使用采樣率對圖片就行高效加載姨伟;流程
? ?1惩琉、將BitmapFactory.Options的inJustDecodeBounds設為true并加載圖片;
? ?2夺荒、從BitmapFactory.Options獲取圖片的信息瞒渠,outHeight和outWidth參數(shù)
? ?3良蒸、根據(jù)采樣率的規(guī)則結果目標view的大小,計算出inSampleSize采樣率
? ?4伍玖、將BitmapFactory.inJustDecodeBounds設為false嫩痰,然后重新加載圖片
緩存策略:在實際開發(fā)中我們經(jīng)常用bitmap進行圖片緩存,使用緩存策略窍箍,我們不用每次都從網(wǎng)絡下載圖片串纺,緩存策略一般是指緩存的添加、獲取和刪除椰棘,因此實際開發(fā)中配合LRUCache能更高效的加載圖片
性能優(yōu)化:bitmap加載圖片所占用內存一部分來自jvm分配纺棺,另一部分來自native也就是底層分配,jvm的分配的內存有gc來回收邪狞,而native非配的內存可以由recyle()進行回收祷蝌,因此如果我們當前如果確定對象不是用可以調用recyle進行釋放底層分配的內存,實際上android可以不用我們調用這個方法帆卓,如果gc檢測到當前bitmap沒有引用巨朦,會自動釋放recycle,因此手動調用也沒有關系
ActivityThread剑令,AMS糊啡,WMS的工作原理
自定義View如何考慮機型適配
合理使用warp_content,match_parent.
使用RelativeLayout 減少層級布局
盡量使用點9圖片
針對不同的機型吁津,使用不同的布局文件放在對應的目錄下棚蓄,android會自動匹配
自定義View的事件
一個touch事件由,down事件腺毫、move事件癣疟、up事件組成,當一個時間產生以后潮酒,系統(tǒng)會將這個點擊事件傳遞到某個具體的view上睛挚,傳遞的順序是activity、viewgroup急黎、view扎狱,傳遞的過程中經(jīng)過三個過程。
AsyncTask 工作流程勃教?重要方法淤击?
AsyncTask內部封裝了線程池和Handler,便于執(zhí)行后臺任務和在子線程中更新UI
工作流程:
1故源、耗時操作之前準備 (Main Thread)
2污抬、處理耗時操作 & 向主線程發(fā)送更新進度的?message(Work Thread)
3、獲取進度的回調并處理 (Work Thread)
4、耗時操作結束的處理 (Main Thread)
5印机、(如果調用cancel),則要處理取消后的相應操作 (Main Thread)
主要涉及到的四個核心方法
onPreExecute():?在主線程處理一些準備工作矢腻。
doInBackground(Params…params):?在子線程中處理異步耗時任務,可以通過?publishProgress?方法來更新任務的進度射赛。
onProgressUpdate(Progress…values):?在主線程中執(zhí)行多柑,當后臺任務進度改變觸發(fā)回調。
onPostExecute(Result result):?在主線程中楣责,異步任務結束觸發(fā)回調竣灌,其中 result 就是后臺任務的返回值。
SparseArray原理
1秆麸,SpareArray用兩個數(shù)組存儲key和value初嘹,保持相同索引,int數(shù)組和Object數(shù)組蛔屹。key鍵是int基本數(shù)據(jù)類型削樊,不需要hash計算,直接返回索引兔毒。
2,HashMap的key鍵必須是引用類型甸箱,SpareArray可以避免key的自動裝箱育叁,數(shù)據(jù)量不大時可以代替HashMap,更省內存芍殖。
3豪嗽,采用二分查找算法獲取數(shù)據(jù)value作者:光晨子鏈接:http://www.reibang.com/p/3dba26007242來源:簡書簡書著作權歸作者所有,任何形式的轉載都請聯(lián)系作者獲得授權并注明出處豌骏。
請介紹下ContentProvider 是如何實現(xiàn)數(shù)據(jù)共享的龟梦?
1、自定義一個ContentProvider類窃躲,繼承ContentProvider计贰,
2、實現(xiàn)它的增刪查改方法
3蒂窒、在配置文件中進行注冊躁倒,并未這個Contentprovider制定一個URL供外部訪問/
Android Service與Activity之間通信的幾種方式
1、Activity傳遞數(shù)據(jù)到Service洒琢,通過startService或者BinderService傳遞Intent傳遞數(shù)據(jù)通信
2秧秉、Service傳遞數(shù)據(jù)到Activity,通過Binder來傳遞
3衰抑、通過廣播來傳遞數(shù)據(jù)象迎,
4、通過接口回調
IntentService原理及作用是什么呛踊?
IntentService繼承Service砾淌,它是一個異步自動停止的高級服務類啦撮,優(yōu)先級比線程高,不容易被殺死拇舀,內部封裝了可供外部使用HanderThread.
原理:內部封裝了HandlerThread和Handler逻族,
作用:因為它內部的onHandleIntent是一個異步線程,因此可以執(zhí)行耗時操作骄崩,并將結果通過Handler通知給UI
SP是進程同步的嗎?有什么方法做到同步聘鳞?
android中進程之間不支持內存共享囤热,每個進程訪問sp都有一個單獨的實例此蜈,因此多進程訪問sp容易造成數(shù)據(jù)丟失,不安全等因素礁遵。
配合ContentProvider 使用
談談多線程在Android中的使用
android中ui線程不允許執(zhí)行耗時操作脱惰,因此我們平常都來開啟多線程等操作來解決網(wǎng)絡請求搏嗡,后臺下載,耗時操作的問題拉一,同時利用Handler來解決UI線程和子線程之間的通信問題采盒,這就解決了UI更新,
asyncTask蔚润、headerThread磅氨、interService
RecycleView原理
RecyclerView擁有四級緩存:
屏幕內緩存 :指在屏幕中顯示的ViewHolder,這些ViewHolder會緩存在mAttachedScrap嫡纠、mChangedScrap中 烦租。mChangedScrap表示數(shù)據(jù)已經(jīng)改變的ViewHolder列表
mAttachedScrap未與RecyclerView分離的ViewHolder列表
屏幕外緩存:當列表滑動出了屏幕時,ViewHolder會被緩存在 mCachedViews除盏,其大小由mViewCacheMax決定叉橱,默認DEFAULT_CACHE_SIZE為2,可通過Recyclerview.setItemViewCacheSize()動態(tài)設置者蠕。
自定義緩存:可以自己實現(xiàn)ViewCacheExtension類實現(xiàn)自定義緩存窃祝,可通過Recyclerview.setViewCacheExtension()設置。通常我們也不會去設置他蠢棱,系統(tǒng)已經(jīng)預先提供了兩級緩存了锌杀,除非有特殊需求,比如要在調用系統(tǒng)的緩存池之前泻仙,返回一個特定的視圖糕再,才會用到他。
緩存池 :ViewHolder首先會緩存在mCachedViews中玉转,當超過了2個(默認為2)突想,就會添加到mRecyclerPool中。mRecyclerPool會根據(jù)ViewType把ViewHolder分別存儲在不同的集合中,每個集合最多緩存5個ViewHolder猾担。
(三)常見的一些原理性問題
Handler機制和底層實現(xiàn)
定義:負責跨線程通信袭灯,這是因為在主線程不能做耗時操作,而子線程不能更新UI绑嘹,所以handle用于接收子線程的數(shù)據(jù)稽荧,配合UI線程更新界面
Handler包括Handler在內有四大要素:handler、message工腋、messageQueue姨丈、Looper
工作機制:異步通信準備->消息入列->消息循環(huán)->消息處理
1、初始化Handler擅腰,主線程會默認創(chuàng)建Looper蟋恬,Looper會自動創(chuàng)建一個MessageQueue,并開啟自動循環(huán)趁冈,
2歼争、Handler通過sendMessage/post兩個方法發(fā)送消息到消息隊列中。
3渗勘、Looper通過無限循環(huán)從消息隊列中取出消息沐绒,并交由Handler處理,如果MessageQueue為null旺坠,當前會阻塞洒沦,不會繼續(xù)執(zhí)行。
4价淌、Handler接收Looper發(fā)來的消息并處理
Handler 引起的內存泄露原因以及最佳解決方案
?泄露原因:
Handler 允許我們發(fā)送延時消息,如果在延時期間用戶關閉了 Activity瞒津,那么該 Activity 會泄露蝉衣。 這個泄露是因為 Message 會持有 Handler,而又因為 Java 的特性巷蚪,內部類會持有外部類病毡,使得 Activity 會被 Handler 持有,這樣最終就導致 Activity 泄露屁柏。
?解決方案:
?將 Handler 定義成靜態(tài)的內部類啦膜,在內部持有Activity的弱引用,并在Acitivity的onDestroy()中調用handler.removeCallbacksAndMessages(null)及時移除所有消息淌喻。?
ThreadLocal原理僧家,實現(xiàn)及如何保證Local屬性?
ThreadLocal 不是 Thread裸删,是一個線程內部的數(shù)據(jù)存儲類八拱,通過它可以在指定的線程中存儲數(shù)據(jù),對數(shù)據(jù)存儲后,只有在線程中才可以獲取到存儲的數(shù)據(jù)肌稻,對于其他線程來說是無法獲取到數(shù)據(jù)
請描述一下View事件傳遞分發(fā)機制
1清蚀、事件分發(fā)的機制就是手指觸摸屏幕后所產生的一些列事件,這些事件包括:action_down爹谭、action_move枷邪、action_up
2、當一個點擊事件產生以后系統(tǒng)會將這個點擊事件傳遞到某個具體的view上诺凡,傳遞順序是:activity东揣、viewgroup、view
3绑洛、傳遞過程中有三個重要事件:
diapatchTouchEvent:
? ? 對事件進行分發(fā)救斑,標識是否消耗當前事件
onInterceptTouchEvent:
? ? 在上述方法內部調用,標識當前事件事件是否被攔截真屯;
onTouchEvent:
? ? 在第一個方法內部調用脸候,表示用來處理點擊事件
對于一個根ViewGroup來說,當點擊事件產生以后绑蔫,首先會傳遞給它运沦,這時它的diapatchTouchEvent就會被調用,如果這個viewgroup的onInterceptTouchEvent方法返回true配深,表示它要攔截當前事件携添,接著這個事件就會交給viewgroup處理,即它的TouchEvent方法會被調用篓叶,如果不攔截烈掠,那么事件就傳遞給它的子元素,接著子元素的diapatchTouchEvent就會被調用缸托,如此反復
View和ViewGroup分別有哪些事件分發(fā)相關的回調方法
View刷新機制
在Android的View刷新機制中左敌,父View負責刷新(invalidateChild)、布局(layoutChild)顯示子View俐镐。而當子View需要刷新時矫限,則是通知父View刷新子view來完成。
View繪制流程
View的繪制是從根節(jié)點開始佩抹,是一種自上而下的過程叼风,分別經(jīng)歷測量、布局棍苹、繪制无宿,即:measure、layout廊勃、draw
mesasure:負責確定view四個頂點的位置懈贺;
layout:確定view最終四個頂點的位置和寬高
draw:將view繪制到界面中
AsyncTask機制
?一些方法:
execute串行執(zhí)行(一次只能執(zhí)行一個任務)
executeOnExecutor并行執(zhí)行(多個任務同時執(zhí)行)
onPreExecute 運行在主線程中
doInBackground工作線程
publishProgress工作線程经窖,通過Handler通知更新UI
工作原理: AnsycTask執(zhí)行任務時,內部會創(chuàng)建一個進程作用域的線程池來管理要運行的任務梭灿,也就就是 說當你調用了AsyncTask.execute()后画侣,AsyncTask會把任務交給線程池,由線程池來管理創(chuàng)建Thread和運行Therad堡妒。最后和UI打交道就交給Handler去處理了
接著問線程池問題:線程池可以同時執(zhí)行多少個TASK
3.0以前核心線程池5個配乱,緩沖線程池10個,最大線程池128個皮迟,面試時畫圖描述
AsyncTask任務是串行還是并行搬泥?
3.0以前是并行執(zhí)行,3.0以后是串行執(zhí)行伏尼,默認定義了一個串行調度忿檩。可以根據(jù)設置來調用串行或者并行方法爆阶。
使用AsyncTask遇到過哪些問題燥透? 定義過AsyncTask為Activity的非靜態(tài)內部類導致內存泄漏,java特性辨图,內部類持有外部類的引用導致的班套。 解決辦法:定義為靜態(tài)內部類持有activity的弱引用
如何取消AsyncTask?
AsyncTask.cancle()
為什么不能在子線程更新UI故河?
android中的UI控件都是非線程安全的吱韭,子線程中并發(fā)訪問可能會導致控件處于不可預期的狀態(tài)
ANR產生的原因是什么?
ANR只會發(fā)生在主線程中鱼的,產生的原因主要是主線程進行了耗時操作超過固定時間得不到響應:
1理盆、耗時的網(wǎng)絡操作
2、界面繪制得不到相應
3凑阶、大量的數(shù)據(jù)讀寫操作
ANR定位和修正
ANR產生時, 系統(tǒng)會生成一個traces.txt的文件放在/data/anr/下. 開發(fā)人員可通過adb命令將其導出到本地 ($adb pull data/anr/traces.txt .)通過分析,我們可以根據(jù)具體的日志查看Anr原因( 如: 普通阻塞,CPU滿負荷,內存泄露 )
oom是什么熏挎?
內存溢出
當一個對象分配內存,當前系統(tǒng)沒有內存可供非配時會導致內存溢出晌砾,常見的有圖片加載
什么情況導致oom?
1烦磁、圖片加載過大养匈;
2、重復創(chuàng)建view
3都伪、一些常見的內存泄漏也引起內存溢出的原因之一呕乎,比如:單例、靜態(tài)變量陨晶、屬性動畫猬仁、Handler等
有什么解決方法可以避免OOM帝璧?
1、使用bitmap的inSampleSize采樣率加載大圖湿刽,
2的烁、重復創(chuàng)建view不僅會造成內存溢出,還會造成界面卡頓诈闺,因此重復的利用view渴庆,比如在listview中
3、規(guī)范代碼編程雅镊,盡可能少使用靜態(tài)變量襟雷,
Oom 是否可以try catch?為什么仁烹?
oom不能被try catch耸弄,會直接掛掉
我們都知道Java中異常超類時Throwable,Throwable派生兩個子類Error和Exception卓缰,Error是不會被捕獲得计呈,Exception會被捕獲,oom繼承Error因此它不會被try catch
內存泄漏是什么僚饭?
內存泄漏是指當前程序申請內存震叮,申請的內存得不到釋放,這就是內存泄漏
什么情況導致內存泄漏鳍鸵?
1苇瓣、靜態(tài)變量引起的內存泄漏
2、單例引起的內存泄漏
3偿乖、屬性動畫引起的內存泄漏
4击罪、handler引起的內存泄漏
如何防止線程的內存泄漏?
1贪薪、避免使用靜態(tài)變量引用當前activity上下文媳禁,引文靜態(tài)變量會始終常駐內存得不到釋放
2、避免過多的使用單例画切,單例的實現(xiàn)也會用到static
3竣稽、屬性動畫中有一類無限循環(huán)的動畫,如果當前頁面退出要機制停止
4霍弹、Handler在進行跨線程通信中毫别,如果在子線程中持有了外部類的引用就得不到及時釋放,將handler定義為靜態(tài)內部類并持有外部類的弱引用典格,及時執(zhí)行removeCallbackAndMessage方法
Android中緩存更新策略 岛宦?
Android的緩存策略是指緩存的添加、獲取和刪除這三類操作耍缴,但不管是內存緩存還是存儲設備緩存砾肺,它們的緩存容量是有限制的挽霉,因此針對這種限制android為我們提供了LRU算法。
LRU的原理 变汪?
為減少流量消耗侠坎,可采用緩存策略。常用的緩存算法是LRU(Least Recently Used):當緩存滿時, 會優(yōu)先淘汰那些近期最少使用的緩存對象疫衩。主要是兩種方式:
LruCache(內存緩存):LruCache類是一個線程安全的泛型類:內部采用一個LinkedHashMap以強引用的方式存儲外界的緩存對象硅蹦,并提供get和put方法來完成緩存的獲取和添加操作,當緩存滿時會移除較早使用的緩存對象闷煤,再添加新的緩存對象童芹。
DiskLruCache(磁盤緩存): 通過將緩存對象寫入文件系統(tǒng)從而實現(xiàn)緩存效果
ContentProvider的權限管理(解答:讀寫分離,權限控制-精確到表級鲤拿,URL控制)
如何通過廣播攔截和abort一條短信假褪?
1、自定義一個SmsReceiver繼承Receiver
2近顷、重寫onReciver方法生音,
3、在onReceiver中監(jiān)聽系統(tǒng)短信窒升,如果監(jiān)聽到來了短信缀遍,判斷intent.getAction()和系統(tǒng)的廣播action是否相等,如果相等就攔截饱须,調用abourboardCast()
廣播是否可以請求網(wǎng)絡域醇?
不可以,廣播默認執(zhí)行在主線程中蓉媳,不能進行耗時操作
廣播引起anr的時間限制是多少譬挚?
10s
計算一個view的嵌套層級
public void getParents(ViewParent parent) {
????if (parent == null) {
????Log.w("parent", "沒有啦!@疑搿减宣!");
????return;
}
????Log.w("parent", parent.toString());
????getParents(parent.getParent());
}
Android線程有沒有上限?
線程是cpu的最小執(zhí)行單元玩荠,同時也是一種有線的資源漆腌,相對于系統(tǒng)來說,只要系統(tǒng)有足夠的cpu資源阶冈,線程就能無限的開啟
線程池有沒有上限屉凯?
有,
核心線程:5個
緩沖線程:10個
最大線程:128個
Android為什么引入Parcelable眼溶?
我們來看一下android兩種序列化的方式,Serializable和Parcelable
Serializable 序列化利用反射的原理晓勇,過程需要大量的I/O操作堂飞,性能低
Parcelable 原理是將對象進行分解灌旧,分解的部門都是傳遞可支持的數(shù)據(jù)類型,操作不需要用反射绰筛,數(shù)據(jù)也存放在 Native 內存中枢泰,效率要快很多
有沒有嘗試簡化Parcelable的使用?
kotlin使用Parcelize注解簡化Parcelable的書寫
(四)開發(fā)中常見的一些問題
ListView 中圖片錯位的問題是如何產生的?
圖片錯位的問題 原因是使用了緩存铝噩,當ListView從底網(wǎng)上滑動的時候衡蚂,當最頂部的view移出當前屏幕的時候,底部的進入的屏幕的view就復用了頂部的view骏庸,因此如果當前view數(shù)據(jù)源沒有及時清空就會導致圖片錯位問題毛甲。
解決辦法:給convertView綁定viewHolder,利用viewHodler的tag機制解決具被,預先給圖片設置一張默認加載圖玻募,同時也減少重復創(chuàng)建view的問題
混合開發(fā)有了解嗎?
混合開發(fā)就是在app中嵌套一個輕量級的瀏覽器一姿,一部分功能采用html 5來開發(fā)七咧,好處就是在不升級app的情況下就能實現(xiàn)動態(tài)更新,同時也能在其他客戶端使用叮叹。
混合開發(fā)最主要的功能就是實現(xiàn)html5 和native的交互
mWebView.addJavascriptInterface(new JsBridge(), "bxbxbai")
知道哪些混合開發(fā)的方式艾栋?說出它們的優(yōu)缺點和各自使用場景?(解答:比如:RN蛉顽,weex蝗砾,H5,小程序蜂林,WPA等遥诉。做Android的了解一些前- 端js等還是很有好處的);
屏幕適配的處理技巧都有哪些?
動態(tài)布局的理解
動態(tài)布局相對靜態(tài)布局xml相比噪叙,它不是可視化矮锈,需要運行起來才能看見效果,但它忽略了將xml轉化為布局代碼睁蕾,提高了效率苞笨;
動態(tài)布局使用較為靈活,但是需要技巧子眶,需要掌握常見的集中布局的屬性設置瀑凝。
怎么去除重復代碼?
項目越大臭杰,activity或者fragment就會越多粤咪,因此難免會有一些重復的代碼,
1渴杆、設置Base(基)activity和fragment
2寥枝、采用提煉技巧宪塔,提煉方法,抽象基類囊拜,提煉常量
3某筐、使用include減少布局重復,原理:引用其他布局冠跷,id要相同南誊,
4、用ViewStub減少整體的布局的重復蜜托,適合整體相同抄囚,局部不同的情況
畫出 Android 的大體架構圖
Linux內核:
????????Android是基于Linux內核開發(fā)
????????Linux提供了安全、內存管理盗冷、進程管理等服務怠苔。
系統(tǒng)庫和Android運行時:
????????系統(tǒng)庫是一個C/C++庫的集合,包含OpenGL仪糖,SQlite等柑司,在開發(fā)過程中,開發(fā)者通過框架層來調用這些庫
????????Android虛擬機位于Android運行時
框架層:
????????框架成提供了日常開發(fā)所用的API包管理器锅劝、內容提供者等位于此層
應用程序層:
????????包含了一些原生應用程序攒驰,如日歷、短信等
Recycleview和ListView的區(qū)別
布局:
? ??Recycleview 支持橫向/縱向布局故爵、流式布局玻粪、瀑布流;ListView僅支持橫向布局
點擊事件:
? ? ? Recycleview不支持itemClick事件诬垂,ListView支持
動畫:
? ??????Recycleview 支持item動畫劲室,ListView不支持
ViewHolder:
? ? ? ? 我們都知道ViewHolder是保存視圖引用的類,在ListView中ViewHolder可用可不用结窘,用需要自定義很洋,而RecyclerView中則必須使用,RecyclerView.ViewHolder
緩存機制:ListView緩存機制是RecyclerBin隧枫,RecyclerView是Recycler和ViewHolder配合使用
動態(tài)權限適配方案喉磁,權限組的概念
我們每個程序機會都會用到用戶權限,權限提醒分為官脓,系統(tǒng)彈窗和自定義彈窗协怒,自定義彈窗一般用于用戶拒絕系統(tǒng)彈窗的提醒窗口后并不再提醒后,我們?yōu)榱擞脩趔w驗卑笨,自己后臺檢測比較人性化的一種彈窗體驗孕暇。
Android系統(tǒng)為什么會設計ContentProvider?
如果我們項目中有需求要使用通訊錄、短信等內容妖滔,假如說:我們讀取內容后將內容以數(shù)據(jù)庫派草、SP或者xml的形式保存到本地握联,當數(shù)據(jù)來源發(fā)生改變時榜苫,那么我們保存的內容也需要修改弱左,這就造成了很大的關聯(lián)性的問題,因此系統(tǒng)為開發(fā)者提供了用于不同程序之間共享數(shù)據(jù)(跨境成通信)的一種方式ContentPrivoder;
ContentProvider厲害的地方在于:
1簸州、封裝、對數(shù)據(jù)進行了封裝歧譬、提供統(tǒng)一接口岸浑,當數(shù)據(jù)來源改變時,程序不需要做任何修改
2瑰步、提供了一種跨進程數(shù)據(jù)共享的方式
既然是對外提供數(shù)據(jù)共享矢洲,那么如何限制對方的使用呢?
答:android:exported屬性非常重要 true可以交互缩焦,false不能交互读虏,同一app組件可以使用
ContentProvider接口方法運行在哪個線程中呢?
答:配置文件中有一個叫android:multiprocess袁滥,false為單例盖桥,true為每個進程創(chuàng)建一個實例
ContentProvider和調用者在同一個進程,ContentProvider的增刪查改方法和調用者在同一線程中题翻;
ContentProvider和調用者在不同的進程揩徊,ContentProvider的方法會運行在它自身所在進程的一個Binder線程中。?
ContentProvider是如何在不同應用程序之間傳輸數(shù)據(jù)的嵌赠?
答:
下拉狀態(tài)欄是不是影響activity的生命周期
不會
Bitmap 使用時候注意什么塑荒?
內存溢出:
使用緩存
Bitmap的recycler()
Bitmap對象占用的內存分為兩部分:JVM分配和native分配,jvm分配的由GC自動回收姜挺,native分配的執(zhí)行recycler()方法才能回收齿税,recycler()并不會立即回收掉,等待下一次GC工作之前才會被回收掉初家,當前目前的android版本即使不調用這個方法偎窘,系統(tǒng)也會自動執(zhí)行recycler回收native部分內存
Android中開啟攝像頭的主要步驟
1、配置文件中添加權限
2溜在、?要將攝像頭捕獲的圖像實時地顯示在手機上陌知,使用surfaceView
3、設置窗口的顯示方式
LRUCache原理
LRUCache是一個線程安全的泛型類掖肋,它內部維護了一個LinkHashMap以強引用的方式對外緩存對象仆葡,并提供get和put方法用來獲取和添加緩存,它內部原理是刪除掉最近最少使用的緩存,添加新的緩存沿盅。
MVC把篓、MVP、MVVM
MVC:Model(數(shù)據(jù)模型層)腰涧、View(視圖展示層)韧掩、Controller(業(yè)務邏輯層)
MVP:Model(數(shù)據(jù)模型層)、View(視圖展示層)窖铡、Presenter(業(yè)務邏輯層)
MVP可以降低代碼耦合度疗锐,提高代碼的結構清晰度、可讀性更高费彼、復用性更強滑臊。
具體些來說(參考JessYan的例子):
現(xiàn)在有這么一個需求:Activity中從網(wǎng)絡獲取數(shù)據(jù)然后展示在A控件上。
如果不用MVP的話箍铲,那就直接把獲取展示等代碼都寫在Activity中雇卷,很快便可以寫完。
但現(xiàn)在需求變動了:
1.要求加入緩存功能颠猴,如果本地有數(shù)據(jù)关划,則先從本地獲取數(shù)據(jù),然后再從網(wǎng)絡獲取最新數(shù)據(jù)進行替換
2.要求數(shù)據(jù)展示在B控件上而不是A控件芙粱。
如果代碼都是你自己寫的祭玉,那改起來還比較輕松,但假如是團隊開發(fā)春畔,代碼不是你寫的脱货,你需要花時間把邏輯重新看一遍再開始改,而且如果改錯的話律姨,會影響之前已經(jīng)寫好的功能振峻。
但使用MVP模式進行開發(fā)就不同了。由于它的分工結構清晰择份,V層僅負責數(shù)據(jù)展示扣孟,P層僅負責業(yè)務邏輯,M層僅負責數(shù)據(jù)獲取/處理荣赶。所以改動起來就輕松很多凤价。
對于變動的需求1:我們只需在P層加入邏輯判斷(先從本地獲取,再網(wǎng)絡獲劝未础)利诺,然后M層增加一個從本地獲取數(shù)據(jù)方法。
對于變動的需求2:我們只需在V層修改獲取到數(shù)據(jù)后的展示方式剩燥,從控件A改成控件B慢逾。