android開(kāi)發(fā)1

、主要分為以下幾部分:

(1)java面試題

(2)Android面試題

(3)高級(jí)開(kāi)發(fā)技術(shù)面試題

(4)跨平臺(tái)Hybrid 開(kāi)發(fā)


一、java面試題

熟練掌握java是很關(guān)鍵的,大公司不僅僅要求你會(huì)使用幾個(gè)api,更多的是要你熟悉源碼實(shí)現(xiàn)原理,甚至要你知道有哪些不足,怎么改進(jìn),還有一些java有關(guān)的一些算法,設(shè)計(jì)模式等等。

(一) java基礎(chǔ)面試知識(shí)點(diǎn)

java中==和equals和hashCode的區(qū)別

equals是Object的方法可以重寫(xiě) ,僅僅用來(lái)判斷兩個(gè)對(duì)象的值

==是操作符,主要用來(lái)判斷兩個(gè)對(duì)象的地址

hashCode用來(lái)獲取對(duì)象的哈希碼,用于確定對(duì)象在哈希表中的位置。

int、char、long各占多少字節(jié)數(shù)

一個(gè)字節(jié)占8位:

char:1個(gè)字節(jié),8位

short:2字節(jié),16位

int:4個(gè)字節(jié),32位

long:8個(gè)字節(jié), 64位

int與integer的區(qū)別

int是值類(lèi)型,Integer是引用類(lèi)型

Integer必須實(shí)例化后才能使用,而int不需要

int默認(rèn)是0,Integer默認(rèn)是null

探探對(duì)java多態(tài)的理解

多態(tài)的定義:同一消息可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式

多態(tài)的好處:消除類(lèi)型之間的耦合關(guān)系

多態(tài)的條件:要有繼承,要有重寫(xiě),父類(lèi)引用指向子類(lèi)對(duì)象

String、StringBuffer、StringBuilder區(qū)別

1:是否從可變的角度

String是final類(lèi)既不允許繼承也不允許改變對(duì)象

StringBuffer、StringBuilder 都繼承AbstractStringBuilder,沒(méi)有final修飾,對(duì)象可變

2、從線程安全角度來(lái)看

String因?yàn)楸籪inal修飾因此不可變,自然也就是線程安全的

StringBuffer 內(nèi)部append方法添加了同步鎖synchronized ,因此它也是線程安全的

StringBuilder內(nèi)部append方法沒(méi)有同步鎖,因此它不是線程安全的

什么是內(nèi)部類(lèi)??jī)?nèi)部類(lèi)的作用

定義:可以把一個(gè)類(lèi)定義到另一個(gè)類(lèi)的內(nèi)部,當(dāng)作外部類(lèi)的成員,這個(gè)類(lèi)就叫做內(nèi)部類(lèi)

作用:根據(jù)內(nèi)部類(lèi)的分類(lèi)說(shuō)一下各個(gè)內(nèi)部類(lèi)的作用

? ? ? ? 成員內(nèi)部類(lèi):可以訪問(wèn)外部類(lèi)的所有方法、屬性、甚至包括私有方法屬性。

? ? ? ? 局部?jī)?nèi)部類(lèi):定義在某個(gè)方法或者一個(gè)作用域里面的類(lèi),只能訪問(wèn)該方法或者作用域里面的對(duì)象

? ? ? ? 靜態(tài)內(nèi)部類(lèi):不依賴于外部類(lèi)而存在,只能訪問(wèn)外部類(lèi)的靜態(tài)成員

? ? ? ? 匿名內(nèi)部類(lèi):無(wú)名內(nèi)部類(lèi),常見(jiàn)于定義控件事件中

抽象類(lèi)和接口區(qū)別

默認(rèn)方法實(shí)現(xiàn):抽象類(lèi)可以有默認(rèn)方法實(shí)現(xiàn),接口沒(méi)有

訪問(wèn)修飾符:抽象類(lèi)public、protected;接口只能public

構(gòu)造器:抽象類(lèi)可以有構(gòu)造器,接口沒(méi)有

抽象類(lèi)的意義

1、為子類(lèi)提供一個(gè)公共的類(lèi)型

2、封裝子類(lèi)中重復(fù)的方法和屬性

3、定義有抽象方法,子類(lèi)雖然有不同的實(shí)現(xiàn),但該方法的定義是一致的

抽象類(lèi)與接口的應(yīng)用場(chǎng)景

如果你擁有一些方法并且想讓它們中的一些有默認(rèn)實(shí)現(xiàn),那么使用抽象類(lèi)吧。

如果你想實(shí)現(xiàn)多重繼承,那么你必須使用接口。由于Java不支持多繼承,子類(lèi)不能夠繼承多個(gè)類(lèi),但可以實(shí)現(xiàn)多個(gè)接口。因此你就可以使用接口來(lái)解決它。

如果基本功能在不斷改變,那么就需要使用抽象類(lèi)。如果不斷改變基本功能并且使用接口,那么就需要改變所有實(shí)現(xiàn)了該接口的類(lèi)

抽象類(lèi)是否可以沒(méi)有方法和屬性?

可以

接口的意義

使用接口可以達(dá)到一定的解耦和作用,比如:我們?cè)诮涌谥卸x一個(gè)變量,所有繼承它的子類(lèi),都用到這個(gè)變量,那么當(dāng)需求改變時(shí)只需要修改著一個(gè)變量即可;

解決java中不能多繼承的缺點(diǎn)

泛型中extends和super的區(qū)別

<? extends T>限定參數(shù)類(lèi)型的上界:參數(shù)類(lèi)型必須是T或T的子類(lèi)型

<? super T> 限定參數(shù)類(lèi)型的下界:參數(shù)類(lèi)型必須是T或T的超類(lèi)型

父類(lèi)的靜態(tài)方法能否被子類(lèi)重寫(xiě)

父類(lèi)的靜態(tài)方法可以被子類(lèi)繼承,但是不能被重寫(xiě)

進(jìn)程和線程的區(qū)別

進(jìn)程是指一個(gè)執(zhí)行單元,一般指一個(gè)程序或者應(yīng)用

線程是cpu調(diào)度的最小單元,主要用于執(zhí)行耗時(shí)操作,一個(gè)進(jìn)程可以有多個(gè)線程

final,finally,finalize的區(qū)別

final:修飾符,使用final修飾的類(lèi)、方法、屬性不能被繼承、重寫(xiě)和改變變量的值

finally:作為異常處理的一部分,通常配合try catch一起使用,標(biāo)識(shí)最終被執(zhí)行的意思

finalize:Object的一個(gè)方法,意為假定該對(duì)象被回收,什么意思呢?我們先了解一下java中垃圾回收器(GC)的工作原理,我們都知道java中的GC只回收J(rèn)VM分配的內(nèi)存,如果對(duì)象使用jni底層c、c++來(lái)進(jìn)行分配的內(nèi)存那么finalize就是負(fù)責(zé)回收這部分內(nèi)存的,在GC工作時(shí)先調(diào)用finalize()方法,并在下一次垃圾回收發(fā)生,才真正回收該對(duì)象占用的內(nèi)存。

Serializable 和Parcelable 的區(qū)別

????????????????????????????????????Serializable? ? ? ? ?????????????????????????Parcelable? ? ? ? ? ? ? ? ? ?

? ? ? ? ? 平臺(tái):? ? ? ? ? ? ? ?java自帶? ? ? ? ? ? ? ? ????????????????????????Android自帶

序列化原理:? ? ? ? ? ? ? ?將對(duì)象轉(zhuǎn)化為可存儲(chǔ)的狀態(tài) ????????將對(duì)象進(jìn)行分解,分解的部門(mén)都是傳遞可支持的數(shù)據(jù)類(lèi)型

? ? ? ?優(yōu)缺點(diǎn):? ? ? ? ? ? ? ?簡(jiǎn)單但是效率低? ? ? ? ? ? ? ? ? ? ? ? ? ?高效但是使用復(fù)雜

靜態(tài)屬性和靜態(tài)方法是否可以被繼承?是否可以被重寫(xiě)?以及原因?

可以被繼承,但是不能被重寫(xiě),靜態(tài)屬性和方法只屬于當(dāng)前類(lèi)。通過(guò)類(lèi)名.屬性,類(lèi)名.方法()調(diào)用

靜態(tài)內(nèi)部類(lèi)的設(shè)計(jì)意圖

非靜態(tài)內(nèi)部類(lèi)在創(chuàng)建的時(shí)候會(huì)持有外部的引用,而靜態(tài)內(nèi)部類(lèi)沒(méi)有

因此非靜態(tài)內(nèi)部類(lèi)有兩個(gè)重要的作用:

1、它的創(chuàng)建不需要外圍,不支持外部類(lèi)的引用

2、靜態(tài)內(nèi)部類(lèi)不能訪問(wèn)外部任何非靜態(tài)屬性和方法

談?wù)剬?duì)kotlin的理解

1、kotlin是一門(mén)靜態(tài)語(yǔ)言,支持多種平臺(tái) 移動(dòng)端、服務(wù)端、以及瀏覽器端

2、空安全的語(yǔ)言,支持泛型,空指針的判斷,支持與java進(jìn)行完全的交互

3、代碼末尾沒(méi)有分號(hào)、被調(diào)用的方法放在上邊等特點(diǎn)

閉包和局部?jī)?nèi)部類(lèi)的區(qū)別

閉包是一個(gè)可調(diào)用的對(duì)象,它包含了一些信息,這些信息來(lái)自創(chuàng)建它的作用域,就是我們常見(jiàn)的lambda 表達(dá)式()=>{ 作用域 };

局部?jī)?nèi)部類(lèi)是定義在某個(gè)方法或者某個(gè)局部中的類(lèi),它只能訪問(wèn)該方法中的變量

string 轉(zhuǎn)換成 integer的方式及原理

1、循環(huán)調(diào)用string的每個(gè)字符的十進(jìn)制數(shù)值

2、通過(guò)*=或/=進(jìn)行計(jì)算拼接

3、最后判斷是否為正負(fù)值,返回結(jié)果


(二) java深入源碼級(jí)的面試題(有難度)

哪些情況下的對(duì)象會(huì)被垃圾回收機(jī)制處理掉?

GC確定哪些對(duì)象回收有兩種算法:

1、引用計(jì)數(shù)法

對(duì)象頭處維護(hù)了一個(gè)引用計(jì)數(shù)去counter一個(gè)對(duì)象被引用一次計(jì)數(shù)器就會(huì)+1,不會(huì)引用就會(huì)-1,為0的時(shí)候GC工作的時(shí)候就會(huì)被回收,但是它不能解決循環(huán)引用帶來(lái)的問(wèn)題

2、可達(dá)性算法

java默認(rèn)的垃圾回收算法,虛擬機(jī)會(huì)先將一些對(duì)象定義為 GC Roots,沿著GC Roots向下尋找,如果對(duì)象不能通過(guò)GC Roots尋找到,那么虛擬機(jī)就認(rèn)為該對(duì)象是被回收的


講一下常見(jiàn)編碼方式?

ASCII:我理解為中文中的GB2312,使用8為二進(jìn)制來(lái)表示字母和字符

UTF-8:英文一個(gè)字符一個(gè)字節(jié),中文占用3/4字節(jié)

UTF-16:定長(zhǎng)編碼,所有字符占兩個(gè)字節(jié)

utf-8編碼中的中文占幾個(gè)字節(jié);int型幾個(gè)字節(jié)?

中文少數(shù)占3個(gè)字節(jié),多數(shù)占4個(gè)字節(jié),int型數(shù)字占1個(gè)字節(jié)

靜態(tài)代理和動(dòng)態(tài)代理的區(qū)別,什么場(chǎng)景使用?

靜態(tài)代理:在程序運(yùn)行前已經(jīng)存在的,提前寫(xiě)好的。代理類(lèi)和委托類(lèi)的關(guān)系提前確定好的。

優(yōu)點(diǎn):業(yè)務(wù)只關(guān)注業(yè)務(wù)本身,專(zhuān)一性

缺點(diǎn):代理對(duì)象只能服務(wù)一種類(lèi)型的對(duì)象,代理需要新的方法,每個(gè)委托都要實(shí)現(xiàn)

動(dòng)態(tài)代理:源碼在運(yùn)行期間JVM根據(jù)反射等機(jī)制動(dòng)態(tài)的生成

Java的異常體系

最近在看java編程思想,根據(jù)自己編碼經(jīng)歷,談?wù)剬?duì)異常的理解:

首先我們都知道java每個(gè)對(duì)象都有一個(gè)異常的超類(lèi)Throwable,它由兩個(gè)子類(lèi)Error(錯(cuò)誤)和Exception(異常)

Error:嚴(yán)重的不可處理的異常,會(huì)導(dǎo)致程序直接掛掉,比如內(nèi)存溢出、類(lèi)定義錯(cuò)誤等

Exception:可處理異常,可以捕獲并處理,比如對(duì)象空指針,文件找不到路徑等

????????????運(yùn)行時(shí)異常:時(shí)在程序運(yùn)行前編譯前檢查語(yǔ)法錯(cuò)誤來(lái)提醒

? ? ? ? ? ??編譯時(shí)異常:主要是程序在運(yùn)行后出現(xiàn)的邏輯錯(cuò)誤或者內(nèi)存溢出而導(dǎo)致的異常,?

1、除非你能解決處理異常,否則不要捕獲它,如果是記錄錯(cuò)誤消息,別忘了把它在拋出去

2、異常即代表一種錯(cuò)誤 也代表一種消息

Java中實(shí)現(xiàn)多態(tài)的機(jī)制是什么?

多態(tài)的實(shí)現(xiàn)有三個(gè)必要條件:

繼承:再多態(tài)中必須有繼承關(guān)系的子類(lèi)、父類(lèi)

重寫(xiě):子類(lèi)重寫(xiě)父類(lèi)中的方法,調(diào)用這些方法就會(huì)調(diào)用子類(lèi)的方法

向上轉(zhuǎn)型:將子類(lèi)的引用賦給父類(lèi),這樣可以調(diào)用父類(lèi)中的方法,和父類(lèi)中沒(méi)有,子類(lèi)中有的方法

如何將一個(gè)Java對(duì)象序列化到文件里?

FileOutputStream fileOutputStream = new FileOutputStream("d://test.out");

ObjectOutputStream objectOutputStream= new ObjectOutputStream(fileOutputStream);

objectOutputStream.writeObject("object");

objectOutputStream.close();?

說(shuō)說(shuō)你對(duì)Java反射的理解

定義:反射就是程序運(yùn)行時(shí)動(dòng)態(tài)的獲取類(lèi)和對(duì)象的方法或者屬性

作用:通過(guò)反射,我們可以獲取相應(yīng)的屬性和方法或者資源,比如我們?cè)诔绦蛑邢氆@取第三方的資源文件,就不能通過(guò)R.id的方式獲取,必須通過(guò)反射才能拿到資源文件

使用:可以通過(guò)對(duì)象.getClass()、類(lèi).class、Class.forName("")

說(shuō)說(shuō)你對(duì)Java注解的理解

定義:注解也稱(chēng)為元數(shù)據(jù),是一種代碼的級(jí)別說(shuō)明,聲明在包、類(lèi)、字段、方法、局部變量、方法參數(shù)等前面,來(lái)對(duì)這些元素進(jìn)行說(shuō)明,注釋等

作用:

?1)編寫(xiě)文檔:通過(guò)代碼里的標(biāo)識(shí)的元數(shù)據(jù)生成文檔【生成文檔doc文檔】

2)代碼分析:通過(guò)代碼里的標(biāo)識(shí)的元數(shù)據(jù)對(duì)代碼進(jìn)行分析【使用反射】

3)編譯檢查:通過(guò)代碼里的標(biāo)識(shí)的元數(shù)據(jù)讓編譯器能過(guò)實(shí)現(xiàn)基本的編譯檢查

java提供了四種元注解:

1.@Target,:規(guī)定注解所修飾的對(duì)象范圍

2.@Retention:表示注解的生命周期

3.@Documented:用于描述

4.@Inherited:主要說(shuō)明了一種繼承性,子類(lèi)可以繼承父類(lèi)注解

說(shuō)說(shuō)你對(duì)依賴注入的理解

我理解的依賴注入是你不需要關(guān)心對(duì)象的生命周期,什么時(shí)候調(diào)用、銷(xiāo)毀等過(guò)程,只需要關(guān)注,調(diào)用它的外部類(lèi)即可:

代碼舉例說(shuō)明:對(duì)象注入、屬性注入

說(shuō)一下泛型原理,并舉例說(shuō)明

泛型的本質(zhì)是參數(shù)化類(lèi)型,它可以用在接口,方法和類(lèi)中,泛型接口、泛型方法、泛型類(lèi)

比如List<String>:

1、它的好處就是在編譯時(shí)期就幫我們檢查類(lèi)型是否安全,不需要運(yùn)行,并且所有的強(qiáng)轉(zhuǎn)都是自動(dòng)和隱士的,效率高

Java中String的了解

String為什么要設(shè)計(jì)成不可變的?

final修飾,不可被繼承,不可被重寫(xiě),類(lèi)型安全,

Object類(lèi)的equal和hashCode方法重寫(xiě),為什么?

1、如果兩個(gè)對(duì)象的equal相同,那么hashCode一定相同,

2、如果hashCode相同。equal并不一定相同

如果equal重寫(xiě),hashCode沒(méi)有被重寫(xiě),可能會(huì)導(dǎo)致兩個(gè)沒(méi)有關(guān)系的對(duì)象equal相同。

(四) 線程、多線程和線程池

開(kāi)啟線程的三種方式?

繼承Thread類(lèi),調(diào)用run()或start()方法

實(shí)現(xiàn)Runnable接口,調(diào)用run()方法? ? ?沒(méi)有返回值,不能進(jìn)行容錯(cuò)處理

Callable接口實(shí)現(xiàn)類(lèi),調(diào)用call()實(shí)現(xiàn)? ? ? 有返回值,并且能容錯(cuò)處理,拋出錯(cuò)誤信息

線程和進(jìn)程的區(qū)別?

進(jìn)程是程序的執(zhí)行單元,一般指一個(gè)應(yīng)用或程序

線程是cpu調(diào)度的最小單元,是一種有限的系統(tǒng)資源,分為UI線程和子線程

一個(gè)進(jìn)程可以有多個(gè)線程。

為什么要有線程,而不是僅僅用進(jìn)程?

進(jìn)程的缺點(diǎn):

????進(jìn)程在同一時(shí)間只能干一件事,如果同時(shí)干多件事就無(wú)能為力

????進(jìn)程在處理任務(wù)一旦遇到阻塞,當(dāng)前程序就會(huì)掛起,下一步操作就無(wú)法繼續(xù)進(jìn)行

線程的優(yōu)點(diǎn):

? ? 減少程序的響應(yīng)時(shí)間,同時(shí)執(zhí)行多個(gè)耗時(shí)操作,充分利用系統(tǒng)資源,避免閑置浪費(fèi)。

run()和start()方法區(qū)別

我們首先來(lái)了解一下線程的五個(gè)狀態(tài):

創(chuàng)建:new Thread(new Runnable);這是線程的創(chuàng)建階段,等待被執(zhí)行

就緒:調(diào)用線程的start()方法,當(dāng)前線程就會(huì)告知虛擬機(jī)我已準(zhǔn)備就緒,由JVM進(jìn)行調(diào)度

運(yùn)行:線程會(huì)調(diào)用實(shí)現(xiàn)runnable的run()方法,此時(shí)線程才真正執(zhí)行

阻塞:執(zhí)行過(guò)程中的暫停等操作。sleep

死亡:run方法執(zhí)行完畢,線程死亡

總結(jié):start()方法只是讓線程處于就緒狀態(tài),告訴cpu我已準(zhǔn)備好了,請(qǐng)開(kāi)始執(zhí)行,然后調(diào)用run方法按順序執(zhí)行。

如何控制某個(gè)方法允許并發(fā)訪問(wèn)線程的個(gè)數(shù)?

java中有一個(gè)叫做信號(hào)量的類(lèi)Semaphore,負(fù)責(zé)控制線程的載入、釋放以及最大并發(fā)訪問(wèn)的個(gè)數(shù),只需要在構(gòu)造函數(shù)中傳入一個(gè)最大的并發(fā)數(shù)就可以。

在Java中wait和sleep方法的不同;

sleep:睡眠,一直持有鎖,事件過(guò)后任務(wù)繼續(xù)執(zhí)行,Thread方法

wait:等待,會(huì)釋放鎖,需要notify()喚醒才能繼續(xù)持有,Object方法

什么導(dǎo)致線程阻塞?

Thread.sleep() 線程睡眠

Object.wait() 線程等待

Thread.yeild() 線程禮讓

Thread.join() 線程自閉

線程如何關(guān)閉?

通常情況下線程運(yùn)行完畢會(huì)自動(dòng)結(jié)束,但是有時(shí)候需要提前讓用戶取消操作等。

1、通過(guò)退出標(biāo)識(shí),自定義一個(gè)isFlag標(biāo)識(shí),在Run方法中進(jìn)行判斷

2、?線程提供interrupted()方法判斷線程是否已經(jīng)中斷來(lái)停止

講一下java中的同步的方法

java允許多線程并發(fā)操作,在多線程并發(fā)中同時(shí)操作一個(gè)可共享的變量是容易造成數(shù)據(jù)不準(zhǔn)確,比如數(shù)據(jù)庫(kù)增刪查改,java引入同步來(lái)保持?jǐn)?shù)據(jù)的一致性final:變量的唯一性,不可變synchronized:作用域代碼塊,方法,通過(guò)線程互斥,同一時(shí)間只允許一個(gè)線程操作。Volatile:修飾變量變化保證立即對(duì)線程可見(jiàn)

數(shù)據(jù)一致性如何保證?

java允許多線程并發(fā)操作,在多線程并發(fā)中同時(shí)操作一個(gè)可共享的變量是容易造成數(shù)據(jù)不準(zhǔn)確,比如數(shù)據(jù)庫(kù)增刪查改,java引入同步來(lái)保持?jǐn)?shù)據(jù)的一致性

final:變量的唯一性,不可變

synchronized:作用域代碼塊,方法,通過(guò)線程互斥,同一時(shí)間只允許一個(gè)線程操作。

Volatile:修飾變量變化保證立即對(duì)線程可見(jiàn)

如何保證線程安全?

java中死鎖和臟數(shù)據(jù)就是典型的線程安全問(wèn)題,只有存在共享數(shù)據(jù)時(shí)才需要考慮線程安全問(wèn)題

synchronized:作用域代碼塊,方法,通過(guò)線程互斥,同一時(shí)間只允許一個(gè)線程操作。Volatile:修飾變量變化保證立即對(duì)線程可見(jiàn)

如何實(shí)現(xiàn)線程同步?

三種方式:

synchronized 同步代碼塊,同一時(shí)間只允許一個(gè)線程操作

Lock,手動(dòng)獲取鎖,釋放鎖

synchronized? 通過(guò)方法。

兩個(gè)進(jìn)程同時(shí)要求寫(xiě)或者讀,能不能實(shí)現(xiàn)?如何防止進(jìn)程的同步?

線程間操作List

多線程操作list容易引起并發(fā)操作導(dǎo)致數(shù)據(jù)的不一致性,

Java中對(duì)象的生命周期

1.??????創(chuàng)建階段(Created) New一個(gè)對(duì)象,有jvm分配內(nèi)存

2.??????應(yīng)用階段(In Use)? 至少被一個(gè)強(qiáng)引用持有

3.??????不可見(jiàn)階段(Invisible)? ?是指該對(duì)象不在當(dāng)前作用域中被訪問(wèn),編譯直接報(bào)錯(cuò)

4.??????不可達(dá)階段(Unreachable)? 不再持有,但是會(huì)被靜態(tài)變量或者jni底層引用

5.??????收集階段(Collected)?

6.??????終結(jié)階段(Finalized)??對(duì)象運(yùn)行完finalize()等待被回收

7.??????對(duì)象空間重分配階段(De-allocated)?對(duì)象徹底消失了

Synchronized用法

Synchronized(this){代碼塊}:其他想要訪問(wèn)此處代碼時(shí),會(huì)被阻塞

public syncchronized void method(){...} 修飾一個(gè)方法,表示其他任務(wù)訪問(wèn)該方法會(huì)被阻塞

synchronize的原理

Java對(duì)象頭和monitor是實(shí)現(xiàn)synchronized的基礎(chǔ)

對(duì)象頭:通過(guò)對(duì)象頭來(lái)確定對(duì)象是哪個(gè)類(lèi)的實(shí)例

monitor:對(duì)象監(jiān)視器,用來(lái)監(jiān)視對(duì)象狀態(tài),它是一種同步機(jī)制

談?wù)剬?duì)Synchronized關(guān)鍵字,類(lèi)鎖,方法鎖,重入鎖的理解

Synchronized是同步的一種機(jī)制,主要用來(lái)解決并發(fā)訪問(wèn)同一對(duì)象所造成的安全問(wèn)題。

Synchronized 修飾靜態(tài)方法獲取到的就是類(lèi)鎖,修飾整個(gè)類(lèi)

Synchronized 修飾代碼塊修飾一個(gè)方法獲取到的就是方法鎖,修飾當(dāng)前方法

沖入所:子類(lèi)繼承父類(lèi)的方法,子類(lèi)父類(lèi)都有方法鎖,

static synchronized 方法的多線程訪問(wèn)和作用

static? synchronized標(biāo)識(shí)當(dāng)前鎖的整個(gè)類(lèi)的靜態(tài)方法,修飾的是整個(gè)類(lèi),也成為類(lèi)鎖。

作用:它可以對(duì)類(lèi)的所有對(duì)象實(shí)例起作用,

同一個(gè)類(lèi)里面兩個(gè)synchronized方法,兩個(gè)線程同時(shí)訪問(wèn)的問(wèn)題

不能同步執(zhí)行,多線程同時(shí)訪問(wèn)同一個(gè)類(lèi)的兩個(gè)synchronized方法時(shí),jvm會(huì)檢測(cè)到當(dāng)前類(lèi)對(duì)象前面的synchronized關(guān)鍵字,會(huì)對(duì)對(duì)象ID加鎖,因此,兩個(gè)線程同時(shí)訪問(wèn),會(huì)等待一個(gè)執(zhí)行完成才能執(zhí)行另一個(gè)。

談?wù)剉olatile關(guān)鍵字的作用

禁止指令重排,修飾變量變化立即對(duì)線程可見(jiàn),線程每次使用的時(shí)候都會(huì)使用修改后的值

synchronized 和volatile 關(guān)鍵字的區(qū)別

synchronized 作用于方法,代碼塊,volatile只能修飾變量

synchronized 會(huì)造成線程阻塞,volatile不會(huì)

synchronized只要用于并發(fā)操作是保證數(shù)據(jù)的唯一性,volatile主要是變量變化時(shí)立馬對(duì)其他線程可見(jiàn)。

synchronized與Lock的區(qū)別

synchronized 時(shí)java內(nèi)置鎖,Lock不是java內(nèi)置

synchronized不需要用戶去手動(dòng)的釋放鎖,使用完后會(huì)自動(dòng)釋放,Lock需要用戶手動(dòng)釋放,不手動(dòng)釋放會(huì)造成死鎖現(xiàn)象

ReentrantLock 、synchronized和volatile比較

ReentrantLock的內(nèi)部實(shí)現(xiàn)

lock原理

死鎖的四個(gè)必要條件?

互斥:某個(gè)資源一次只能有一個(gè)進(jìn)程訪問(wèn),其他進(jìn)程需要先等待

占有且等待,當(dāng)前進(jìn)程本身占有著一種資源,同時(shí)也需要其他進(jìn)程正在訪問(wèn)的其他資源,需要等待

不可搶占:別人已經(jīng)占有,不可使用

循環(huán)等待:

怎么避免死鎖?

1、避免一個(gè)線程同時(shí)獲取多個(gè)鎖;

2、避免一個(gè)線程在鎖內(nèi)同時(shí)占用多個(gè)資源,盡量保證每個(gè)鎖只占用一個(gè)資源

對(duì)象鎖和類(lèi)鎖是否會(huì)互相影響?

類(lèi)鎖和對(duì)象鎖不是同1個(gè)東西,一個(gè)是類(lèi)的Class對(duì)象的鎖,一個(gè)是類(lèi)的實(shí)例的鎖。也就是說(shuō):1個(gè)線程訪問(wèn)靜態(tài)synchronized的時(shí)候,允許另一個(gè)線程訪問(wèn)對(duì)象的實(shí)例synchronized方法。反過(guò)來(lái)也是成立的,因?yàn)樗麄冃枰逆i是不同的

什么是線程池,如何使用?

線程池就是將任務(wù)添加到隊(duì)列中順序或并發(fā)執(zhí)行的一個(gè)集合,android線程池一般有這幾個(gè)參數(shù):核心線程數(shù),緩沖線程數(shù),最大線程數(shù)

Java的并發(fā)、多線程、線程模型

談?wù)剬?duì)多線程的理解

優(yōu)點(diǎn):多線程可以處理耗時(shí)操作,方便多任務(wù)同時(shí)執(zhí)行,比如網(wǎng)絡(luò)操作,后臺(tái)下載等。

缺點(diǎn):線程是一種有限的系統(tǒng)資源,因此,需要避免大量線程的開(kāi)銷(xiāo)以及內(nèi)存泄漏

多線程有什么要注意的問(wèn)題?

多線程是一種有限的系統(tǒng)資源,大量的創(chuàng)建會(huì)導(dǎo)致資源消耗,盡量使用線程池

Android中容易引起內(nèi)存泄漏:持有外部類(lèi)的引用。

談?wù)勀銓?duì)并發(fā)編程的理解并舉例說(shuō)明

cpu在同一時(shí)間只能處理一件事,因此并發(fā)看似是同時(shí)執(zhí)行,實(shí)際上實(shí)在不停的切換進(jìn)程

談?wù)勀銓?duì)多線程同步機(jī)制的理解?

線程同步是一種安全機(jī)制,它主要是解決多線程同時(shí)訪問(wèn)統(tǒng)一資源導(dǎo)致的數(shù)據(jù)安全問(wèn)題。

synchronized;volatile

如何保證多線程讀寫(xiě)文件的安全?

多線程 同時(shí)訪問(wèn)同一個(gè)文件回導(dǎo)致數(shù)據(jù)安全問(wèn)題,因此可以使用同步鎖來(lái)解決這種問(wèn)題。

可以使用synchronzied來(lái)保證在同一時(shí)間只能由一個(gè)線程來(lái)操作

斷點(diǎn)續(xù)傳原理及實(shí)現(xiàn)

斷點(diǎn)續(xù)傳分為單線程斷點(diǎn)續(xù)傳和多線程斷點(diǎn)續(xù)傳,

單線程斷點(diǎn)續(xù)傳:比較簡(jiǎn)單,至開(kāi)啟一個(gè)線程下載某一個(gè)文件起始位置是0-文件總大小,網(wǎng)絡(luò)斷開(kāi)記住當(dāng)前所下載的位置,下次下載重新定義http的Range

多線程斷點(diǎn)續(xù)傳:開(kāi)啟多個(gè)線程同時(shí)下載某個(gè)文件中的某一個(gè)部分,舉例說(shuō)明

實(shí)現(xiàn):

不管是單線程還是多線程都要用到:

1、斷點(diǎn)續(xù)傳需要指定http的Range和Content-Rang

2、如果檢測(cè)到網(wǎng)絡(luò)斷開(kāi)則要記錄當(dāng)前下載的位置也就是Range,等待下次重新連接的時(shí)候,指定當(dāng)前Range?


二、Android面試題

Android面試題包括Android基礎(chǔ),還有一些源碼級(jí)別的、原理這些等。所以想去大公司面試,一定要多看看源碼和實(shí)現(xiàn)方式,常用框架可以試試自己能不能手寫(xiě)實(shí)現(xiàn)一下,鍛煉一下自己。

(一)Android基礎(chǔ)知識(shí)點(diǎn)

四大組件是什么

Activity:Service:BoradcastReceiver:ContentProvider:

四大組件的生命周期和簡(jiǎn)單用法

Activity之間的通信方式

1、通過(guò)Intent傳遞,大小限制1Mb

2、通過(guò)類(lèi)靜態(tài)變量

3、通過(guò)全局變量

4、通過(guò)SharedPreferences、文件等用的較少

Activity各種情況下的生命周期

橫豎屏切換的時(shí)候,Activity 各種情況下的生命周期

橫屏:onSaveInstanceState->onPause()->onStop->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()

豎屏:橫屏*2

對(duì)android:configChanges屬性,一般認(rèn)為有以下幾點(diǎn):

1、不設(shè)置Activity的android:configChanges時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次,切豎屏?xí)r會(huì)執(zhí)行兩次

2、設(shè)置Activity的android:configChanges="orientation"時(shí),切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫、豎屏?xí)r只會(huì)執(zhí)行一次

3、設(shè)置Activity的android:configChanges="orientation|keyboardHidden"時(shí),切屏不會(huì)重新調(diào)用各個(gè)生命周期,只會(huì)執(zhí)行onConfigurationChanged方法?

Activity與Fragment之間生命周期比較

Activity:onCreate、onStart、onResume、onPause、onStop、onDestroy、onRestart

Fragment:

onAttach(與Activyty關(guān)聯(lián)時(shí)調(diào)用)、 onCreate、onCreateView(創(chuàng)建Fragment視圖時(shí)調(diào)用)、onActivityCreated(Activity 的Create方法調(diào)用時(shí)調(diào)用)

onStart、

onResume、

onPause、

onStop、

onDestroyView(Fragment視圖被移除時(shí)調(diào)用)、onDestroy、onDetach(與Activity取消關(guān)聯(lián)時(shí)調(diào)用)

Activity上有Dialog的時(shí)候按Home鍵時(shí)的生命周期

onPause()、onStop()

兩個(gè)Activity 之間跳轉(zhuǎn)時(shí)必然會(huì)執(zhí)行的是哪幾個(gè)方法?

A:onPause、B:onCreate、onStart、onResume、A:onStop

前臺(tái)切換到后臺(tái),然后再回到前臺(tái),Activity生命周期回調(diào)方法。

A->B:

A:onPause、B:onCreate、onStart、onResume、A:onStop

B返回A:

B:onPause、A:onRestart、onStart、onResume、B:onStop、onDestroy

彈出Dialog,生命值周期回調(diào)方法。

A:onPause、B:onCreate、onStart、onResume

Activity的四種啟動(dòng)模式對(duì)比

standard:默認(rèn)模式,每次都會(huì)創(chuàng)建一個(gè)新的頁(yè)面

singleTop:棧頂模式,創(chuàng)建時(shí)優(yōu)先檢查棧頂是否存在相同的活動(dòng),有展示,沒(méi)有創(chuàng)建

singleTask:棧內(nèi)模式,創(chuàng)建時(shí)優(yōu)先檢查棧內(nèi)是否存在相同的活動(dòng),有展示并清除當(dāng)前活動(dòng)以上所有頁(yè)面,沒(méi)有創(chuàng)建

singleInstance:?jiǎn)卫J?,存在于單?dú)的棧中,且只有一個(gè)實(shí)例

Activity狀態(tài)保存于恢復(fù)

一般我們指的狀態(tài)保存和恢復(fù)是指的非正常狀態(tài)下的activity生命周期

onSaveInstanceState

onRetoreInstanceState

如何實(shí)現(xiàn)Fragment的滑動(dòng)?

Fragment和Viewpager配合使用

給Viewpager設(shè)置setAdapter和setOnPageChangeListener即可

fragment之間傳遞數(shù)據(jù)的方式?

調(diào)用getFragmentManager()的findFragmentById()獲取fragment對(duì)象,根據(jù)對(duì)象調(diào)用方法來(lái)實(shí)現(xiàn)

Activity 怎么和Service 綁定?

Activity-Intent-Service

bindService(new Intent(Activity,Service.class),)

怎么在Activity 中啟動(dòng)自己對(duì)應(yīng)的Service?

startService(new Intent(...))

service和activity怎么進(jìn)行數(shù)據(jù)交互?

通過(guò)Intent進(jìn)行傳值

Service的開(kāi)啟方式 以及Service 的生命周期

startService:

startService、onCreate、onStart、service running、onStop、onDestroy

bindService、onCreate、onBind、service running,onUnBind,onDestroy

談?wù)勀銓?duì)ContentProvider的理解

定義:

ContentProvider它是一種數(shù)據(jù)共享性組件,用戶向其他組件乃至其他應(yīng)用共享數(shù)據(jù),和廣播一樣無(wú)法被用戶感知,他內(nèi)部需要實(shí)現(xiàn)增刪查改方法,內(nèi)部維護(hù)了一個(gè)數(shù)據(jù)集合,通過(guò)數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)

日常開(kāi)發(fā):自定義類(lèi)繼承ContentProvider,實(shí)現(xiàn)增刪查改方法,處理好線程同步,對(duì)外實(shí)現(xiàn)URL來(lái)實(shí)現(xiàn)。

說(shuō)說(shuō)ContentProvider、ContentResolver、ContentObserver 之間的關(guān)系

ContentProvider 內(nèi)容提供者,向外提供共享數(shù)據(jù)

ContentResolver:內(nèi)容解析者,對(duì)內(nèi)容提供者提供的數(shù)據(jù)進(jìn)行分析

ContentObserver:內(nèi)容觀察者,觀察內(nèi)容在各個(gè)階段的狀態(tài)

請(qǐng)描述一下廣播BroadcastReceiver的理解

1、BroadcastReceiver 時(shí)一種消息型組件,在不同組件乃至不同應(yīng)用之間傳遞消息,無(wú)法被用戶感知,因?yàn)樗ぷ髟谙到y(tǒng)內(nèi)部,

2、廣播有兩種注冊(cè)方式:靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)。生命周期也根據(jù)注冊(cè)不同

3、廣播默認(rèn)運(yùn)行在主線程中,不支持耗時(shí)操作。

廣播的分類(lèi)

有序廣播:消息的照發(fā)送的順序接收

無(wú)序廣播:所有設(shè)備幾乎在同一時(shí)刻接收到廣播

本地廣播:只能在當(dāng)前應(yīng)用中接收到廣播

粘性廣播:先發(fā)送,后注冊(cè)

在manifest 和代碼中如何注冊(cè)和使用BroadcastReceiver?

靜態(tài)注冊(cè):mainfest中<receiver android:name=".MyReceiver">action</receiver>

動(dòng)態(tài)注冊(cè):regeisterReceiver(new MyReceiver(),filter);

廣播發(fā)送的原理:

1、首先自定義一個(gè)廣播接收者BroadcastRecevier,并重寫(xiě)onReceiver();

2、通過(guò)Binder機(jī)制像AMS進(jìn)行注冊(cè);

3、廣播發(fā)送者通過(guò)Binder機(jī)制向AMS發(fā)送廣播;

4、AMS查找符合條件的廣播,并發(fā)送到消息循環(huán)隊(duì)列中;

5、消息循環(huán)拿到此廣播并回調(diào)onReceiver()方法。

Application 和 Activity 的 Context 對(duì)象的區(qū)別

生命周期不同:

Application的Context代表的是整個(gè)應(yīng)用程序的生命周期,Activity的Context代表的是當(dāng)前Activity的生命周期。

Android屬性動(dòng)畫(huà)工作原理

在一定時(shí)間間隔內(nèi),通過(guò)不斷對(duì)值進(jìn)行改變,并不斷將該值賦給對(duì)象的屬性,從而實(shí)現(xiàn)該對(duì)象在該屬性上的動(dòng)畫(huà)效果

如何導(dǎo)入外部數(shù)據(jù)庫(kù)?

1、將外部數(shù)據(jù)庫(kù)放到文件目錄assets中,

2、通過(guò)InputStream讀取外部數(shù)據(jù)庫(kù),通過(guò)FileOutputStream導(dǎo)入內(nèi)部數(shù)據(jù)庫(kù)

3、需要注意外部數(shù)據(jù)庫(kù)與我們新建的數(shù)據(jù)庫(kù)屬性和數(shù)據(jù)類(lèi)型要一致

LinearLayout、RelativeLayout、FrameLayout的特性及對(duì)比,并介紹使用場(chǎng)景。

RelativeLayout 會(huì)橫向,縱向進(jìn)行兩次測(cè)量,也就是執(zhí)行兩次measure,效率肯定相對(duì)底

LinearLayout 線性布局,從上往下的順序繪制元素,如果LinearLayout 有weight屬性,也會(huì)執(zhí)行兩次measure

FrameLayout 無(wú)法控制子元素的位置,全部堆在左上角,無(wú)法改變。

談?wù)剬?duì)接口與回調(diào)的理解

接口的實(shí)現(xiàn)很簡(jiǎn)單,?

1、定義接口,編寫(xiě)回掉方法,給接口賦值

我們想象平時(shí)為什么需要接口

1、傳值,利用接口傳值,我們不關(guān)心過(guò)程只關(guān)心結(jié)果,

2、接口回調(diào)可以理解為一種設(shè)計(jì)模式,類(lèi)似于觀察者,程序負(fù)責(zé)項(xiàng)目大的時(shí)候,有利于頁(yè)面之間的解耦

介紹下SurefaceView

1、SurefaceView主要在被動(dòng)的情況下更新,

2、SurefaceView主要在子線程中進(jìn)行,常用于平凡刷新以及刷新是數(shù)據(jù)量大的情況下

3、SurefaceView底部采用了雙緩存機(jī)制,常見(jiàn)的視頻播放。

RecycleView的使用

recyckeView.setLayoutManager(設(shè)置布局管理器,支持三種:橫/縱向,流式布局,瀑布流);

recyckeView.setAdapter(設(shè)置適配源)

//也可以設(shè)置分割線、動(dòng)畫(huà)等

序列化的作用,以及Android兩種序列化的區(qū)別

序列化是指將對(duì)象轉(zhuǎn)化為文件存儲(chǔ)在本地存儲(chǔ)中的操作,主要是為了保存對(duì)象的狀態(tài)

Serializable:java自帶,使用簡(jiǎn)單,但是要重復(fù)讀寫(xiě)內(nèi)存,效率低

Parcelable:android自帶,使用復(fù)雜,重復(fù)利用內(nèi)存,效率高。

插值器

android中的插值器主要是為了實(shí)現(xiàn)動(dòng)畫(huà)的非線性需求而定義的,例如加減速等

估值器

協(xié)助插值器 實(shí)現(xiàn)非線性運(yùn)動(dòng)的動(dòng)畫(huà)效果

Android中數(shù)據(jù)存儲(chǔ)方式

sharedpreferences:android提供的基于key、value保存在xml文件中的存儲(chǔ)方式,基本數(shù)據(jù)類(lèi)型等。非線程安全

文件存儲(chǔ):將對(duì)象采用序列化的方式保存到本地

sqlite:數(shù)據(jù)庫(kù)存儲(chǔ)

contentprovider:通過(guò)程序之間共享數(shù)據(jù)存儲(chǔ):

網(wǎng)絡(luò)云存儲(chǔ):

(二)Android源碼相關(guān)分析

invalidate和postInvalidate的區(qū)別及使用

invalidate在主線程中使用,通知UI更新View

postInvalidate在子線程中調(diào)用,通知UI更新View,底層通過(guò)Handler來(lái)通知UI更新

Activity-Window-View三者的差別

1、Activity 創(chuàng)建時(shí)通過(guò)attach()初始化了

2、一個(gè) Window 一個(gè) Window 持有一個(gè) DecorView 的實(shí)例,DecorView 本身是一個(gè) FrameLayout,繼承于View, 3、Activty通過(guò)setContentView將xml布局控件不斷addView()添加到View中,最終顯示到Window于我們交互;

談?wù)剬?duì)Volley的理解

google推出的異步網(wǎng)絡(luò)框架,還能加載圖片,適合請(qǐng)求量小

使用:

1、將網(wǎng)絡(luò)請(qǐng)求添加到RequestQueue中

2、RequestQueue中有兩個(gè)分發(fā)器:CacheDispatch(緩存分發(fā)器)和NetworkDispatch(網(wǎng)絡(luò)分發(fā)器),其實(shí)就是開(kāi)啟兩個(gè)線程

3、網(wǎng)絡(luò)請(qǐng)求會(huì)有優(yōu)先從緩存中獲取,如果緩存中沒(méi)有就開(kāi)啟一個(gè)networkdispatch,并且將請(qǐng)求添加到cachediapatch中,

4、將請(qǐng)求結(jié)果傳遞到主線程。

如何優(yōu)化自定義View

優(yōu)化自定義view可以從兩個(gè)方面考慮:

1、減少invaildate調(diào)用次數(shù),invaildate在主線程中運(yùn)行,調(diào)用它會(huì)執(zhí)行view的onDraw方法,造成UI卡頓

2、requestLayout操作非常耗時(shí),因?yàn)閳?zhí)行requestLayout會(huì)使android Ui系統(tǒng)遍歷整個(gè)view層級(jí)來(lái)計(jì)算view大小

3、如果UI復(fù)雜,可以考慮使用ViewGroup,與view不同的是,自定義view僅僅測(cè)量一部分

低版本SDK如何實(shí)現(xiàn)高版本api?

低版本使用高版本的api最常見(jiàn)的是編譯報(bào)錯(cuò),android為開(kāi)發(fā)者提供了避免編譯報(bào)錯(cuò)的解決方案,那就是注解:

@SuppressLint(newApi)

讓編譯器忽略所有對(duì)新api版本的調(diào)用檢查

@TargetApi(11)

讓編譯器忽略對(duì)特定版本的便宜檢查

描述一次網(wǎng)絡(luò)請(qǐng)求的流程

1、通過(guò)url找到IP

2、根據(jù)IP簡(jiǎn)歷TCP連接(三次握手)

3、向服務(wù)器發(fā)送數(shù)據(jù)

4、服務(wù)器解析并返回結(jié)果

5、對(duì)結(jié)果進(jìn)行處理

Bitmap對(duì)象的理解

Bitmap核心思想有三個(gè):高效加載,緩存策略,性能優(yōu)化;

高效加載:在不影響圖片顯示的情況下,使用采樣率對(duì)圖片就行高效加載;流程

? ?1、將BitmapFactory.Options的inJustDecodeBounds設(shè)為true并加載圖片;

? ?2、從BitmapFactory.Options獲取圖片的信息,outHeight和outWidth參數(shù)

? ?3、根據(jù)采樣率的規(guī)則結(jié)果目標(biāo)view的大小,計(jì)算出inSampleSize采樣率

? ?4、將BitmapFactory.inJustDecodeBounds設(shè)為false,然后重新加載圖片

緩存策略:在實(shí)際開(kāi)發(fā)中我們經(jīng)常用bitmap進(jìn)行圖片緩存,使用緩存策略,我們不用每次都從網(wǎng)絡(luò)下載圖片,緩存策略一般是指緩存的添加、獲取和刪除,因此實(shí)際開(kāi)發(fā)中配合LRUCache能更高效的加載圖片

性能優(yōu)化:bitmap加載圖片所占用內(nèi)存一部分來(lái)自jvm分配,另一部分來(lái)自native也就是底層分配,jvm的分配的內(nèi)存有g(shù)c來(lái)回收,而native非配的內(nèi)存可以由recyle()進(jìn)行回收,因此如果我們當(dāng)前如果確定對(duì)象不是用可以調(diào)用recyle進(jìn)行釋放底層分配的內(nèi)存,實(shí)際上android可以不用我們調(diào)用這個(gè)方法,如果gc檢測(cè)到當(dāng)前bitmap沒(méi)有引用,會(huì)自動(dòng)釋放recycle,因此手動(dòng)調(diào)用也沒(méi)有關(guān)系

ActivityThread,AMS,WMS的工作原理

自定義View如何考慮機(jī)型適配

合理使用warp_content,match_parent.

使用RelativeLayout 減少層級(jí)布局

盡量使用點(diǎn)9圖片

針對(duì)不同的機(jī)型,使用不同的布局文件放在對(duì)應(yīng)的目錄下,android會(huì)自動(dòng)匹配

自定義View的事件

一個(gè)touch事件由,down事件、move事件、up事件組成,當(dāng)一個(gè)時(shí)間產(chǎn)生以后,系統(tǒng)會(huì)將這個(gè)點(diǎn)擊事件傳遞到某個(gè)具體的view上,傳遞的順序是activity、viewgroup、view,傳遞的過(guò)程中經(jīng)過(guò)三個(gè)過(guò)程。

AsyncTask 工作流程?重要方法?

AsyncTask內(nèi)部封裝了線程池和Handler,便于執(zhí)行后臺(tái)任務(wù)和在子線程中更新UI

工作流程:

1、耗時(shí)操作之前準(zhǔn)備 (Main Thread)

2、處理耗時(shí)操作 & 向主線程發(fā)送更新進(jìn)度的?message(Work Thread)

3、獲取進(jìn)度的回調(diào)并處理 (Work Thread)

4、耗時(shí)操作結(jié)束的處理 (Main Thread)

5、(如果調(diào)用cancel),則要處理取消后的相應(yīng)操作 (Main Thread)

主要涉及到的四個(gè)核心方法

onPreExecute():?在主線程處理一些準(zhǔn)備工作。

doInBackground(Params…params):?在子線程中處理異步耗時(shí)任務(wù),可以通過(guò)?publishProgress?方法來(lái)更新任務(wù)的進(jìn)度。

onProgressUpdate(Progress…values):?在主線程中執(zhí)行,當(dāng)后臺(tái)任務(wù)進(jìn)度改變觸發(fā)回調(diào)。

onPostExecute(Result result):?在主線程中,異步任務(wù)結(jié)束觸發(fā)回調(diào),其中 result 就是后臺(tái)任務(wù)的返回值。


SparseArray原理

1,SpareArray用兩個(gè)數(shù)組存儲(chǔ)key和value,保持相同索引,int數(shù)組和Object數(shù)組。key鍵是int基本數(shù)據(jù)類(lèi)型,不需要hash計(jì)算,直接返回索引。

2,HashMap的key鍵必須是引用類(lèi)型,SpareArray可以避免key的自動(dòng)裝箱,數(shù)據(jù)量不大時(shí)可以代替HashMap,更省內(nèi)存。

3,采用二分查找算法獲取數(shù)據(jù)value作者:光晨子鏈接:http://www.itdecent.cn/p/3dba26007242來(lái)源:簡(jiǎn)書(shū)簡(jiǎn)書(shū)著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。

請(qǐng)介紹下ContentProvider 是如何實(shí)現(xiàn)數(shù)據(jù)共享的?

1、自定義一個(gè)ContentProvider類(lèi),繼承ContentProvider,

2、實(shí)現(xiàn)它的增刪查改方法

3、在配置文件中進(jìn)行注冊(cè),并未這個(gè)Contentprovider制定一個(gè)URL供外部訪問(wèn)/

Android Service與Activity之間通信的幾種方式

1、Activity傳遞數(shù)據(jù)到Service,通過(guò)startService或者BinderService傳遞Intent傳遞數(shù)據(jù)通信

2、Service傳遞數(shù)據(jù)到Activity,通過(guò)Binder來(lái)傳遞

3、通過(guò)廣播來(lái)傳遞數(shù)據(jù),

4、通過(guò)接口回調(diào)

IntentService原理及作用是什么?

IntentService繼承Service,它是一個(gè)異步自動(dòng)停止的高級(jí)服務(wù)類(lèi),優(yōu)先級(jí)比線程高,不容易被殺死,內(nèi)部封裝了可供外部使用HanderThread.

原理:內(nèi)部封裝了HandlerThread和Handler,

作用:因?yàn)樗鼉?nèi)部的onHandleIntent是一個(gè)異步線程,因此可以執(zhí)行耗時(shí)操作,并將結(jié)果通過(guò)Handler通知給UI

SP是進(jìn)程同步的嗎?有什么方法做到同步?

android中進(jìn)程之間不支持內(nèi)存共享,每個(gè)進(jìn)程訪問(wèn)sp都有一個(gè)單獨(dú)的實(shí)例,因此多進(jìn)程訪問(wèn)sp容易造成數(shù)據(jù)丟失,不安全等因素。

配合ContentProvider 使用

談?wù)劧嗑€程在Android中的使用

android中ui線程不允許執(zhí)行耗時(shí)操作,因此我們平常都來(lái)開(kāi)啟多線程等操作來(lái)解決網(wǎng)絡(luò)請(qǐng)求,后臺(tái)下載,耗時(shí)操作的問(wèn)題,同時(shí)利用Handler來(lái)解決UI線程和子線程之間的通信問(wèn)題,這就解決了UI更新,

asyncTask、headerThread、interService

RecycleView原理

RecyclerView擁有四級(jí)緩存:

屏幕內(nèi)緩存 :指在屏幕中顯示的ViewHolder,這些ViewHolder會(huì)緩存在mAttachedScrap、mChangedScrap中 。mChangedScrap表示數(shù)據(jù)已經(jīng)改變的ViewHolder列表

mAttachedScrap未與RecyclerView分離的ViewHolder列表

屏幕外緩存:當(dāng)列表滑動(dòng)出了屏幕時(shí),ViewHolder會(huì)被緩存在 mCachedViews,其大小由mViewCacheMax決定,默認(rèn)DEFAULT_CACHE_SIZE為2,可通過(guò)Recyclerview.setItemViewCacheSize()動(dòng)態(tài)設(shè)置。

自定義緩存:可以自己實(shí)現(xiàn)ViewCacheExtension類(lèi)實(shí)現(xiàn)自定義緩存,可通過(guò)Recyclerview.setViewCacheExtension()設(shè)置。通常我們也不會(huì)去設(shè)置他,系統(tǒng)已經(jīng)預(yù)先提供了兩級(jí)緩存了,除非有特殊需求,比如要在調(diào)用系統(tǒng)的緩存池之前,返回一個(gè)特定的視圖,才會(huì)用到他。

緩存池 :ViewHolder首先會(huì)緩存在mCachedViews中,當(dāng)超過(guò)了2個(gè)(默認(rèn)為2),就會(huì)添加到mRecyclerPool中。mRecyclerPool會(huì)根據(jù)ViewType把ViewHolder分別存儲(chǔ)在不同的集合中,每個(gè)集合最多緩存5個(gè)ViewHolder。

(三)常見(jiàn)的一些原理性問(wèn)題

Handler機(jī)制和底層實(shí)現(xiàn)

定義:負(fù)責(zé)跨線程通信,這是因?yàn)樵谥骶€程不能做耗時(shí)操作,而子線程不能更新UI,所以handle用于接收子線程的數(shù)據(jù),配合UI線程更新界面

Handler包括Handler在內(nèi)有四大要素:handler、message、messageQueue、Looper

工作機(jī)制:異步通信準(zhǔn)備->消息入列->消息循環(huán)->消息處理

1、初始化Handler,主線程會(huì)默認(rèn)創(chuàng)建Looper,Looper會(huì)自動(dòng)創(chuàng)建一個(gè)MessageQueue,并開(kāi)啟自動(dòng)循環(huán),

2、Handler通過(guò)sendMessage/post兩個(gè)方法發(fā)送消息到消息隊(duì)列中。

3、Looper通過(guò)無(wú)限循環(huán)從消息隊(duì)列中取出消息,并交由Handler處理,如果MessageQueue為null,當(dāng)前會(huì)阻塞,不會(huì)繼續(xù)執(zhí)行。

4、Handler接收Looper發(fā)來(lái)的消息并處理

Handler 引起的內(nèi)存泄露原因以及最佳解決方案

?泄露原因:

Handler 允許我們發(fā)送延時(shí)消息,如果在延時(shí)期間用戶關(guān)閉了 Activity,那么該 Activity 會(huì)泄露。 這個(gè)泄露是因?yàn)?Message 會(huì)持有 Handler,而又因?yàn)?Java 的特性,內(nèi)部類(lèi)會(huì)持有外部類(lèi),使得 Activity 會(huì)被 Handler 持有,這樣最終就導(dǎo)致 Activity 泄露。

?解決方案:

?將 Handler 定義成靜態(tài)的內(nèi)部類(lèi),在內(nèi)部持有Activity的弱引用,并在Acitivity的onDestroy()中調(diào)用handler.removeCallbacksAndMessages(null)及時(shí)移除所有消息。?

ThreadLocal原理,實(shí)現(xiàn)及如何保證Local屬性?

ThreadLocal 不是 Thread,是一個(gè)線程內(nèi)部的數(shù)據(jù)存儲(chǔ)類(lèi),通過(guò)它可以在指定的線程中存儲(chǔ)數(shù)據(jù),對(duì)數(shù)據(jù)存儲(chǔ)后,只有在線程中才可以獲取到存儲(chǔ)的數(shù)據(jù),對(duì)于其他線程來(lái)說(shuō)是無(wú)法獲取到數(shù)據(jù)

請(qǐng)描述一下View事件傳遞分發(fā)機(jī)制

1、事件分發(fā)的機(jī)制就是手指觸摸屏幕后所產(chǎn)生的一些列事件,這些事件包括:action_down、action_move、action_up

2、當(dāng)一個(gè)點(diǎn)擊事件產(chǎn)生以后系統(tǒng)會(huì)將這個(gè)點(diǎn)擊事件傳遞到某個(gè)具體的view上,傳遞順序是:activity、viewgroup、view

3、傳遞過(guò)程中有三個(gè)重要事件:

diapatchTouchEvent:

? ? 對(duì)事件進(jìn)行分發(fā),標(biāo)識(shí)是否消耗當(dāng)前事件

onInterceptTouchEvent:

? ? 在上述方法內(nèi)部調(diào)用,標(biāo)識(shí)當(dāng)前事件事件是否被攔截;

onTouchEvent:

? ? 在第一個(gè)方法內(nèi)部調(diào)用,表示用來(lái)處理點(diǎn)擊事件

對(duì)于一個(gè)根ViewGroup來(lái)說(shuō),當(dāng)點(diǎn)擊事件產(chǎn)生以后,首先會(huì)傳遞給它,這時(shí)它的diapatchTouchEvent就會(huì)被調(diào)用,如果這個(gè)viewgroup的onInterceptTouchEvent方法返回true,表示它要攔截當(dāng)前事件,接著這個(gè)事件就會(huì)交給viewgroup處理,即它的TouchEvent方法會(huì)被調(diào)用,如果不攔截,那么事件就傳遞給它的子元素,接著子元素的diapatchTouchEvent就會(huì)被調(diào)用,如此反復(fù)

View和ViewGroup分別有哪些事件分發(fā)相關(guān)的回調(diào)方法

View刷新機(jī)制

在Android的View刷新機(jī)制中,父View負(fù)責(zé)刷新(invalidateChild)、布局(layoutChild)顯示子View。而當(dāng)子View需要刷新時(shí),則是通知父View刷新子view來(lái)完成。

View繪制流程

View的繪制是從根節(jié)點(diǎn)開(kāi)始,是一種自上而下的過(guò)程,分別經(jīng)歷測(cè)量、布局、繪制,即:measure、layout、draw

mesasure:負(fù)責(zé)確定view四個(gè)頂點(diǎn)的位置;

layout:確定view最終四個(gè)頂點(diǎn)的位置和寬高

draw:將view繪制到界面中

AsyncTask機(jī)制

?一些方法:

execute串行執(zhí)行(一次只能執(zhí)行一個(gè)任務(wù))

executeOnExecutor并行執(zhí)行(多個(gè)任務(wù)同時(shí)執(zhí)行)

onPreExecute 運(yùn)行在主線程中

doInBackground工作線程

publishProgress工作線程,通過(guò)Handler通知更新UI

工作原理: AnsycTask執(zhí)行任務(wù)時(shí),內(nèi)部會(huì)創(chuàng)建一個(gè)進(jìn)程作用域的線程池來(lái)管理要運(yùn)行的任務(wù),也就就是 說(shuō)當(dāng)你調(diào)用了AsyncTask.execute()后,AsyncTask會(huì)把任務(wù)交給線程池,由線程池來(lái)管理創(chuàng)建Thread和運(yùn)行Therad。最后和UI打交道就交給Handler去處理了

接著問(wèn)線程池問(wèn)題:線程池可以同時(shí)執(zhí)行多少個(gè)TASK

3.0以前核心線程池5個(gè),緩沖線程池10個(gè),最大線程池128個(gè),面試時(shí)畫(huà)圖描述

AsyncTask任務(wù)是串行還是并行?

3.0以前是并行執(zhí)行,3.0以后是串行執(zhí)行,默認(rèn)定義了一個(gè)串行調(diào)度??梢愿鶕?jù)設(shè)置來(lái)調(diào)用串行或者并行方法。

使用AsyncTask遇到過(guò)哪些問(wèn)題? 定義過(guò)AsyncTask為Activity的非靜態(tài)內(nèi)部類(lèi)導(dǎo)致內(nèi)存泄漏,java特性,內(nèi)部類(lèi)持有外部類(lèi)的引用導(dǎo)致的。 解決辦法:定義為靜態(tài)內(nèi)部類(lèi)持有activity的弱引用

如何取消AsyncTask?

AsyncTask.cancle()

為什么不能在子線程更新UI?

android中的UI控件都是非線程安全的,子線程中并發(fā)訪問(wèn)可能會(huì)導(dǎo)致控件處于不可預(yù)期的狀態(tài)

ANR產(chǎn)生的原因是什么?

ANR只會(huì)發(fā)生在主線程中,產(chǎn)生的原因主要是主線程進(jìn)行了耗時(shí)操作超過(guò)固定時(shí)間得不到響應(yīng):

1、耗時(shí)的網(wǎng)絡(luò)操作

2、界面繪制得不到相應(yīng)

3、大量的數(shù)據(jù)讀寫(xiě)操作

ANR定位和修正

ANR產(chǎn)生時(shí), 系統(tǒng)會(huì)生成一個(gè)traces.txt的文件放在/data/anr/下. 開(kāi)發(fā)人員可通過(guò)adb命令將其導(dǎo)出到本地 ($adb pull data/anr/traces.txt .)通過(guò)分析,我們可以根據(jù)具體的日志查看Anr原因( 如: 普通阻塞,CPU滿負(fù)荷,內(nèi)存泄露 )

oom是什么?

內(nèi)存溢出

當(dāng)一個(gè)對(duì)象分配內(nèi)存,當(dāng)前系統(tǒng)沒(méi)有內(nèi)存可供非配時(shí)會(huì)導(dǎo)致內(nèi)存溢出,常見(jiàn)的有圖片加載

什么情況導(dǎo)致oom?

1、圖片加載過(guò)大;

2、重復(fù)創(chuàng)建view

3、一些常見(jiàn)的內(nèi)存泄漏也引起內(nèi)存溢出的原因之一,比如:?jiǎn)卫?、靜態(tài)變量、屬性動(dòng)畫(huà)、Handler等

有什么解決方法可以避免OOM?

1、使用bitmap的inSampleSize采樣率加載大圖,

2、重復(fù)創(chuàng)建view不僅會(huì)造成內(nèi)存溢出,還會(huì)造成界面卡頓,因此重復(fù)的利用view,比如在listview中

3、規(guī)范代碼編程,盡可能少使用靜態(tài)變量,

Oom 是否可以try catch?為什么?

oom不能被try catch,會(huì)直接掛掉

我們都知道Java中異常超類(lèi)時(shí)Throwable,Throwable派生兩個(gè)子類(lèi)Error和Exception,Error是不會(huì)被捕獲得,Exception會(huì)被捕獲,oom繼承Error因此它不會(huì)被try catch

內(nèi)存泄漏是什么?

內(nèi)存泄漏是指當(dāng)前程序申請(qǐng)內(nèi)存,申請(qǐng)的內(nèi)存得不到釋放,這就是內(nèi)存泄漏

什么情況導(dǎo)致內(nèi)存泄漏?

1、靜態(tài)變量引起的內(nèi)存泄漏

2、單例引起的內(nèi)存泄漏

3、屬性動(dòng)畫(huà)引起的內(nèi)存泄漏

4、handler引起的內(nèi)存泄漏

如何防止線程的內(nèi)存泄漏?

1、避免使用靜態(tài)變量引用當(dāng)前activity上下文,引文靜態(tài)變量會(huì)始終常駐內(nèi)存得不到釋放

2、避免過(guò)多的使用單例,單例的實(shí)現(xiàn)也會(huì)用到static

3、屬性動(dòng)畫(huà)中有一類(lèi)無(wú)限循環(huán)的動(dòng)畫(huà),如果當(dāng)前頁(yè)面退出要機(jī)制停止

4、Handler在進(jìn)行跨線程通信中,如果在子線程中持有了外部類(lèi)的引用就得不到及時(shí)釋放,將handler定義為靜態(tài)內(nèi)部類(lèi)并持有外部類(lèi)的弱引用,及時(shí)執(zhí)行removeCallbackAndMessage方法

Android中緩存更新策略 ?

Android的緩存策略是指緩存的添加、獲取和刪除這三類(lèi)操作,但不管是內(nèi)存緩存還是存儲(chǔ)設(shè)備緩存,它們的緩存容量是有限制的,因此針對(duì)這種限制android為我們提供了LRU算法。

LRU的原理 ?

為減少流量消耗,可采用緩存策略。常用的緩存算法是LRU(Least Recently Used):當(dāng)緩存滿時(shí), 會(huì)優(yōu)先淘汰那些近期最少使用的緩存對(duì)象。主要是兩種方式:

LruCache(內(nèi)存緩存):LruCache類(lèi)是一個(gè)線程安全的泛型類(lèi):內(nèi)部采用一個(gè)LinkedHashMap以強(qiáng)引用的方式存儲(chǔ)外界的緩存對(duì)象,并提供get和put方法來(lái)完成緩存的獲取和添加操作,當(dāng)緩存滿時(shí)會(huì)移除較早使用的緩存對(duì)象,再添加新的緩存對(duì)象。

DiskLruCache(磁盤(pán)緩存): 通過(guò)將緩存對(duì)象寫(xiě)入文件系統(tǒng)從而實(shí)現(xiàn)緩存效果

ContentProvider的權(quán)限管理(解答:讀寫(xiě)分離,權(quán)限控制-精確到表級(jí),URL控制)

如何通過(guò)廣播攔截和abort一條短信?

1、自定義一個(gè)SmsReceiver繼承Receiver

2、重寫(xiě)onReciver方法,

3、在onReceiver中監(jiān)聽(tīng)系統(tǒng)短信,如果監(jiān)聽(tīng)到來(lái)了短信,判斷intent.getAction()和系統(tǒng)的廣播action是否相等,如果相等就攔截,調(diào)用abourboardCast()

廣播是否可以請(qǐng)求網(wǎng)絡(luò)?

不可以,廣播默認(rèn)執(zhí)行在主線程中,不能進(jìn)行耗時(shí)操作

廣播引起anr的時(shí)間限制是多少?

10s

計(jì)算一個(gè)view的嵌套層級(jí)

public void getParents(ViewParent parent) {

????if (parent == null) {

????Log.w("parent", "沒(méi)有啦?。?!");

????return;

}

????Log.w("parent", parent.toString());

????getParents(parent.getParent());

}

Android線程有沒(méi)有上限?

線程是cpu的最小執(zhí)行單元,同時(shí)也是一種有線的資源,相對(duì)于系統(tǒng)來(lái)說(shuō),只要系統(tǒng)有足夠的cpu資源,線程就能無(wú)限的開(kāi)啟

線程池有沒(méi)有上限?

有,

核心線程:5個(gè)

緩沖線程:10個(gè)

最大線程:128個(gè)

Android為什么引入Parcelable?

我們來(lái)看一下android兩種序列化的方式,Serializable和Parcelable

Serializable 序列化利用反射的原理,過(guò)程需要大量的I/O操作,性能低

Parcelable 原理是將對(duì)象進(jìn)行分解,分解的部門(mén)都是傳遞可支持的數(shù)據(jù)類(lèi)型,操作不需要用反射,數(shù)據(jù)也存放在 Native 內(nèi)存中,效率要快很多

有沒(méi)有嘗試簡(jiǎn)化Parcelable的使用?

kotlin使用Parcelize注解簡(jiǎn)化Parcelable的書(shū)寫(xiě)

(四)開(kāi)發(fā)中常見(jiàn)的一些問(wèn)題

ListView 中圖片錯(cuò)位的問(wèn)題是如何產(chǎn)生的?

圖片錯(cuò)位的問(wèn)題 原因是使用了緩存,當(dāng)ListView從底網(wǎng)上滑動(dòng)的時(shí)候,當(dāng)最頂部的view移出當(dāng)前屏幕的時(shí)候,底部的進(jìn)入的屏幕的view就復(fù)用了頂部的view,因此如果當(dāng)前view數(shù)據(jù)源沒(méi)有及時(shí)清空就會(huì)導(dǎo)致圖片錯(cuò)位問(wèn)題。

解決辦法:給convertView綁定viewHolder,利用viewHodler的tag機(jī)制解決,預(yù)先給圖片設(shè)置一張默認(rèn)加載圖,同時(shí)也減少重復(fù)創(chuàng)建view的問(wèn)題

混合開(kāi)發(fā)有了解嗎?

混合開(kāi)發(fā)就是在app中嵌套一個(gè)輕量級(jí)的瀏覽器,一部分功能采用html 5來(lái)開(kāi)發(fā),好處就是在不升級(jí)app的情況下就能實(shí)現(xiàn)動(dòng)態(tài)更新,同時(shí)也能在其他客戶端使用。

混合開(kāi)發(fā)最主要的功能就是實(shí)現(xiàn)html5 和native的交互

mWebView.addJavascriptInterface(new JsBridge(), "bxbxbai")

知道哪些混合開(kāi)發(fā)的方式?說(shuō)出它們的優(yōu)缺點(diǎn)和各自使用場(chǎng)景?(解答:比如:RN,weex,H5,小程序,WPA等。做Android的了解一些前- 端js等還是很有好處的);

屏幕適配的處理技巧都有哪些?

動(dòng)態(tài)布局的理解

動(dòng)態(tài)布局相對(duì)靜態(tài)布局xml相比,它不是可視化,需要運(yùn)行起來(lái)才能看見(jiàn)效果,但它忽略了將xml轉(zhuǎn)化為布局代碼,提高了效率;

動(dòng)態(tài)布局使用較為靈活,但是需要技巧,需要掌握常見(jiàn)的集中布局的屬性設(shè)置。

怎么去除重復(fù)代碼?

項(xiàng)目越大,activity或者fragment就會(huì)越多,因此難免會(huì)有一些重復(fù)的代碼,

1、設(shè)置Base(基)activity和fragment

2、采用提煉技巧,提煉方法,抽象基類(lèi),提煉常量

3、使用include減少布局重復(fù),原理:引用其他布局,id要相同,

4、用ViewStub減少整體的布局的重復(fù),適合整體相同,局部不同的情況

畫(huà)出 Android 的大體架構(gòu)圖

Linux內(nèi)核:

????????Android是基于Linux內(nèi)核開(kāi)發(fā)

????????Linux提供了安全、內(nèi)存管理、進(jìn)程管理等服務(wù)。

系統(tǒng)庫(kù)和Android運(yùn)行時(shí):

????????系統(tǒng)庫(kù)是一個(gè)C/C++庫(kù)的集合,包含OpenGL,SQlite等,在開(kāi)發(fā)過(guò)程中,開(kāi)發(fā)者通過(guò)框架層來(lái)調(diào)用這些庫(kù)

????????Android虛擬機(jī)位于Android運(yùn)行時(shí)

框架層:

????????框架成提供了日常開(kāi)發(fā)所用的API包管理器、內(nèi)容提供者等位于此層

應(yīng)用程序?qū)樱?/p>

????????包含了一些原生應(yīng)用程序,如日歷、短信等

Recycleview和ListView的區(qū)別

布局:

? ??Recycleview 支持橫向/縱向布局、流式布局、瀑布流;ListView僅支持橫向布局

點(diǎn)擊事件:

? ? ? Recycleview不支持itemClick事件,ListView支持

動(dòng)畫(huà):

? ??????Recycleview 支持item動(dòng)畫(huà),ListView不支持

ViewHolder:

? ? ? ? 我們都知道ViewHolder是保存視圖引用的類(lèi),在ListView中ViewHolder可用可不用,用需要自定義,而RecyclerView中則必須使用,RecyclerView.ViewHolder

緩存機(jī)制:ListView緩存機(jī)制是RecyclerBin,RecyclerView是Recycler和ViewHolder配合使用

動(dòng)態(tài)權(quán)限適配方案,權(quán)限組的概念

我們每個(gè)程序機(jī)會(huì)都會(huì)用到用戶權(quán)限,權(quán)限提醒分為,系統(tǒng)彈窗和自定義彈窗,自定義彈窗一般用于用戶拒絕系統(tǒng)彈窗的提醒窗口后并不再提醒后,我們?yōu)榱擞脩趔w驗(yàn),自己后臺(tái)檢測(cè)比較人性化的一種彈窗體驗(yàn)。

Android系統(tǒng)為什么會(huì)設(shè)計(jì)ContentProvider?

如果我們項(xiàng)目中有需求要使用通訊錄、短信等內(nèi)容,假如說(shuō):我們讀取內(nèi)容后將內(nèi)容以數(shù)據(jù)庫(kù)、SP或者xml的形式保存到本地,當(dāng)數(shù)據(jù)來(lái)源發(fā)生改變時(shí),那么我們保存的內(nèi)容也需要修改,這就造成了很大的關(guān)聯(lián)性的問(wèn)題,因此系統(tǒng)為開(kāi)發(fā)者提供了用于不同程序之間共享數(shù)據(jù)(跨境成通信)的一種方式ContentPrivoder;

ContentProvider厲害的地方在于:

1、封裝、對(duì)數(shù)據(jù)進(jìn)行了封裝、提供統(tǒng)一接口,當(dāng)數(shù)據(jù)來(lái)源改變時(shí),程序不需要做任何修改

2、提供了一種跨進(jìn)程數(shù)據(jù)共享的方式

既然是對(duì)外提供數(shù)據(jù)共享,那么如何限制對(duì)方的使用呢?

答:android:exported屬性非常重要 true可以交互,false不能交互,同一app組件可以使用

ContentProvider接口方法運(yùn)行在哪個(gè)線程中呢?

答:配置文件中有一個(gè)叫android:multiprocess,false為單例,true為每個(gè)進(jìn)程創(chuàng)建一個(gè)實(shí)例

ContentProvider和調(diào)用者在同一個(gè)進(jìn)程,ContentProvider的增刪查改方法和調(diào)用者在同一線程中;

ContentProvider和調(diào)用者在不同的進(jìn)程,ContentProvider的方法會(huì)運(yùn)行在它自身所在進(jìn)程的一個(gè)Binder線程中。?

ContentProvider是如何在不同應(yīng)用程序之間傳輸數(shù)據(jù)的?

答:

下拉狀態(tài)欄是不是影響activity的生命周期

不會(huì)

Bitmap 使用時(shí)候注意什么?

內(nèi)存溢出:

使用緩存

Bitmap的recycler()

Bitmap對(duì)象占用的內(nèi)存分為兩部分:JVM分配和native分配,jvm分配的由GC自動(dòng)回收,native分配的執(zhí)行recycler()方法才能回收,recycler()并不會(huì)立即回收掉,等待下一次GC工作之前才會(huì)被回收掉,當(dāng)前目前的android版本即使不調(diào)用這個(gè)方法,系統(tǒng)也會(huì)自動(dòng)執(zhí)行recycler回收native部分內(nèi)存

Android中開(kāi)啟攝像頭的主要步驟

1、配置文件中添加權(quán)限

2、?要將攝像頭捕獲的圖像實(shí)時(shí)地顯示在手機(jī)上,使用surfaceView

3、設(shè)置窗口的顯示方式

LRUCache原理

LRUCache是一個(gè)線程安全的泛型類(lèi),它內(nèi)部維護(hù)了一個(gè)LinkHashMap以強(qiáng)引用的方式對(duì)外緩存對(duì)象,并提供get和put方法用來(lái)獲取和添加緩存,它內(nèi)部原理是刪除掉最近最少使用的緩存,添加新的緩存。

MVC、MVP、MVVM

MVC:Model(數(shù)據(jù)模型層)、View(視圖展示層)、Controller(業(yè)務(wù)邏輯層)

MVP:Model(數(shù)據(jù)模型層)、View(視圖展示層)、Presenter(業(yè)務(wù)邏輯層)

MVP可以降低代碼耦合度,提高代碼的結(jié)構(gòu)清晰度、可讀性更高、復(fù)用性更強(qiáng)。

具體些來(lái)說(shuō)(參考JessYan的例子):

現(xiàn)在有這么一個(gè)需求:Activity中從網(wǎng)絡(luò)獲取數(shù)據(jù)然后展示在A控件上。

如果不用MVP的話,那就直接把獲取展示等代碼都寫(xiě)在Activity中,很快便可以寫(xiě)完。

但現(xiàn)在需求變動(dòng)了:

1.要求加入緩存功能,如果本地有數(shù)據(jù),則先從本地獲取數(shù)據(jù),然后再?gòu)木W(wǎng)絡(luò)獲取最新數(shù)據(jù)進(jìn)行替換

2.要求數(shù)據(jù)展示在B控件上而不是A控件。

如果代碼都是你自己寫(xiě)的,那改起來(lái)還比較輕松,但假如是團(tuán)隊(duì)開(kāi)發(fā),代碼不是你寫(xiě)的,你需要花時(shí)間把邏輯重新看一遍再開(kāi)始改,而且如果改錯(cuò)的話,會(huì)影響之前已經(jīng)寫(xiě)好的功能。

但使用MVP模式進(jìn)行開(kāi)發(fā)就不同了。由于它的分工結(jié)構(gòu)清晰,V層僅負(fù)責(zé)數(shù)據(jù)展示,P層僅負(fù)責(zé)業(yè)務(wù)邏輯,M層僅負(fù)責(zé)數(shù)據(jù)獲取/處理。所以改動(dòng)起來(lái)就輕松很多。

對(duì)于變動(dòng)的需求1:我們只需在P層加入邏輯判斷(先從本地獲取,再網(wǎng)絡(luò)獲?。缓驧層增加一個(gè)從本地獲取數(shù)據(jù)方法。

對(duì)于變動(dòng)的需求2:我們只需在V層修改獲取到數(shù)據(jù)后的展示方式,從控件A改成控件B。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容