支付流程(面試題07)

1.屏幕適配:
為了讓我們開(kāi)發(fā)的程序能夠比較美觀的顯示在不同尺寸、分辨率、像素密度的設(shè)備上。
1.使用約束布局或者相對(duì)布局
就可以根據(jù)各組件之間的特殊關(guān)系指定布局
2.適配不同尺寸避免寫死的尺寸值;wrap_content,match_parent,weight,利用dpi換算dp和px的值。
3.圖片考慮使用可以拉伸的,xml自定義shape圖片,矢量圖,自動(dòng)拉伸.9圖
4.限定符;最小寬度限定符,屏幕方向限定符,布局別名。(要注意限定符的優(yōu)先級(jí))
2.內(nèi)存溢出和內(nèi)存泄漏的區(qū)別,產(chǎn)生原因以及解決方案
概念與區(qū)別
內(nèi)存溢出:沒(méi)有足夠的內(nèi)存空間可以使用, 那就是內(nèi)存溢出。
內(nèi)存泄露:內(nèi)存泄漏時(shí)一個(gè)對(duì)象已經(jīng)不需要再使用了,但是其他的對(duì)象還持有該對(duì)象的引用,導(dǎo)致內(nèi)存不能被垃圾回收器回收。比如在內(nèi)部類持有外部類的引用時(shí)。靜態(tài)變量,非靜態(tài)內(nèi)部類:持有外部類引用(handler)。內(nèi)存泄漏會(huì)導(dǎo)致OOM.
內(nèi)存泄露的解決方案:
1.不要在匿名內(nèi)部類中進(jìn)行異步操作
2.使用Context時(shí),盡量使用Application 的 Context
3.盡量避免使用static 成員變量。

將Handler聲明為靜態(tài)類。靜態(tài)類不持有外部類的對(duì)象,所以你的Activity可以隨意被回收。需要在Handler中增加一個(gè)對(duì)Activity的弱引用(WeakReference)。因?yàn)閔andler不在持有外部對(duì)象的引用
內(nèi)存溢出
1.內(nèi)存中加載的數(shù)據(jù)量過(guò)于龐大
2.集合類中有對(duì)對(duì)象的引用,使用完后未清空,使得JVM不能回收;
3.代碼中存在死循環(huán)或循環(huán)產(chǎn)生過(guò)多重復(fù)的對(duì)象實(shí)體;
內(nèi)存溢出的解決方案:
動(dòng)態(tài)回收內(nèi)存
優(yōu)化Dalvik虛擬機(jī)的堆內(nèi)存分配
在內(nèi)存引用上做處理,比如軟引用、弱引用等
3.事件分發(fā)
事件分發(fā),如果有多層嵌套的時(shí)候,讓那個(gè)控件消費(fèi)這個(gè)點(diǎn)擊事件
事件分發(fā)三個(gè)主要的方法分別是:dispatchTouchEvent(分發(fā)) onTouchEvent(消費(fèi))
onInterceptTouchEvent(攔截),只有容器才有onInterceptTouchEvent(攔截方法)
從Activity開(kāi)始,進(jìn)入事件分發(fā),Activity無(wú)論返回true或false都自己消費(fèi),因?yàn)樗约壕褪琼攲樱幌到y(tǒng)消費(fèi),返回super向下分發(fā),交給子viewgroup,如果viewgroup的dispatchTouchEvent(分發(fā))返回true就消費(fèi),返回false交給上一層消費(fèi),返回super交給 自身攔截事件,攔截事件返回true的話自己消費(fèi),其他則繼續(xù)想下分發(fā),子view的分發(fā)事件為true自己消費(fèi),返回false交給上一層
4.Handler機(jī)制
Handler 的主要作用是線程間通信,實(shí)現(xiàn)子線程與主線程的切換,通過(guò) Handler 來(lái)異步更新UI,避免線程操作不安全的問(wèn)題
總體流程:Handler向MessageQueue發(fā)送一條Message,MessageQueue通過(guò)next方法把消息傳給Looper,Looper收到消息后開(kāi)始處理,然后最終交給Handler自己去處理。
Message Queue(消息隊(duì)列):負(fù)責(zé)存儲(chǔ)消息對(duì)象,按照先進(jìn)先出原則執(zhí)行,是由Message組成的一個(gè)隊(duì)列;
Message:消息類,包含了消息處理對(duì)象以及處理的數(shù)據(jù)等。
Looper:負(fù)責(zé)消息隊(duì)列的創(chuàng)建,從消息隊(duì)列中獲取消息執(zhí)行,一個(gè)MessageQueue需要一個(gè)Looper;
Handler :是Message的主要處理者,負(fù)責(zé)管理消息的發(fā)送和收到消息后的邏輯處理

在子線程創(chuàng)建handler:(因?yàn)閔andler必須要調(diào)用looper. Prepare()方法,所以必須要在子線程中獲取looper對(duì)象。)
方法一:在run方法創(chuàng)建一個(gè)handler對(duì)象,獲取主線程的looper來(lái)實(shí)現(xiàn)。
方法二:在run方法通過(guò)looper.prepare()獲取looper對(duì)象,在發(fā)送消息完調(diào)用Looper.loop方法,不斷遍歷MessageQueue方法

主線程的Looper.loop為什么不可以造成死循環(huán)
android所有的UI處理都是通過(guò)handler消息機(jī)制處理的,每次處理都發(fā)送到消息隊(duì)列,從消息隊(duì)列取出來(lái)才進(jìn)行執(zhí)行,如果消息隊(duì)列沒(méi)有就不執(zhí)行,所以不會(huì)造成死循環(huán)。
5.性能優(yōu)化:
卡頓優(yōu)化
1、布局優(yōu)化
一個(gè)頁(yè)面的顯示測(cè)量和繪制過(guò)程都是通過(guò)遞歸來(lái)完成的,如果層級(jí)太深,每增加一層則會(huì)增加更多的頁(yè)面顯示時(shí)間,所以布局的合理性就顯得很重要。
1.減少層級(jí)。合理使用 RelativeLayout 和 LinerLayout,ConstraintLayout
2.Merge合并,減少層級(jí),從而減少繪制時(shí)間。
3.使用 ViewStub來(lái)提高顯示速度。是看不見(jiàn),占用資源非常小的視圖對(duì)象,僅在需要時(shí)才加載布局,
4.布局復(fù)用??梢酝ㄟ^(guò)include標(biāo)簽來(lái)提高復(fù)用。
5.盡可能少用wrap_content。在已知寬高為固定值時(shí),不用wrap_content 。wrap_content會(huì)增加布局計(jì)算成本
2、避免過(guò)度繪制
過(guò)度繪制是指在屏幕上的同一塊地方在一時(shí)間被繪制了多次。從而浪費(fèi)了多余的 CPU 以及 GPU 資源。解決:移除 XML 中非必須的背景,移除 Window 默認(rèn)的背景、按需要顯示占位背景圖片
3、合理的刷新機(jī)制
在應(yīng)用開(kāi)發(fā)過(guò)程中,因?yàn)閿?shù)據(jù)的變化,需要刷新頁(yè)面來(lái)展示新的數(shù)據(jù),但頻繁刷新會(huì)增加資源開(kāi)銷,并且可能導(dǎo)致卡頓發(fā)生,因此,需要一個(gè)合理的刷新機(jī)制來(lái)提高整體的 UI 流暢度。合理的刷新需要注意以下幾點(diǎn):
1.盡量減少刷新次數(shù)。
2.盡量避免后臺(tái)有高的 CPU 線程運(yùn)行。
3.縮小刷新區(qū)域。
內(nèi)存優(yōu)化
1、優(yōu)化內(nèi)存空間
Android 系統(tǒng)對(duì)每個(gè)應(yīng)用進(jìn)程也都分配了有限的內(nèi)存, GC 能更高效地回收不再需要使用的對(duì)象,讓應(yīng)用存保持充足的可用內(nèi)存,使應(yīng)用更穩(wěn)定高效地運(yùn)行。常見(jiàn)做法如下:
1.對(duì)象引用。強(qiáng)引用、軟引用、弱引用、虛引用四種引用類型
2.減少不必要的內(nèi)存開(kāi)銷。注意自動(dòng)裝箱,增加內(nèi)存復(fù)用,比如有效利用系統(tǒng)自帶的資源、視圖復(fù)用、對(duì)象池、Bitmap對(duì)象的復(fù)用。
3.使用最優(yōu)的數(shù)據(jù)類型。比如針對(duì)數(shù)據(jù)類容器結(jié)構(gòu),可以使用ArrayMap數(shù)據(jù)結(jié)構(gòu),避免使用枚舉類型,使用緩存Lrucache等等。
4.圖片內(nèi)存優(yōu)化。可以設(shè)置位圖規(guī)格,根據(jù)采樣因子做壓縮,用一些圖片緩存方式對(duì)圖片進(jìn)行管理等等。
2、穩(wěn)定性優(yōu)化
Android 應(yīng)用的穩(wěn)定性定義很寬泛,影響穩(wěn)定性的原因很多,比如內(nèi)存使用不合理、代碼異常場(chǎng)景考慮不周全、代碼邏輯不合理等,都會(huì)對(duì)應(yīng)用的穩(wěn)定性造成影響。其中最常見(jiàn)的兩個(gè)場(chǎng)景是:Crash 和 ANR,這兩個(gè)錯(cuò)誤將會(huì)使得程序無(wú)法使用,比較常用的解決方式如下:
1.提高代碼質(zhì)量。比如開(kāi)發(fā)期間的代碼審核,看些代碼設(shè)計(jì)邏輯,業(yè)務(wù)合理性等。
3、耗電優(yōu)化
5.0 之后專門引入了一個(gè)獲取設(shè)備上電量消耗信息的 API:Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系統(tǒng)電量分析工具,和Systrace 一樣,是一款圖形化數(shù)據(jù)分析工具,直觀地展示出手機(jī)的電量消耗過(guò)程,通過(guò)輸入電量分析文件,顯示消耗情況,最后提供一些可供參考電量?jī)?yōu)化的方法。除此之外,還有一些常用方案可提供:
1.計(jì)算優(yōu)化,避開(kāi)浮點(diǎn)運(yùn)算等。
2.避免 WaleLock 使用不當(dāng)。
3.使用 Job Scheduler。
4、安裝包大小優(yōu)化
減少安裝包大小的常用方案
1.代碼混淆。使用proGuard 代碼混淆器工具,它包括壓縮、優(yōu)化、混淆等功能。
2.資源優(yōu)化。比如使用 Android Lint 刪除剩余資源,資源文件最少化等。
3.圖片優(yōu)化。比如利用 AAPT 工具對(duì) PNG 格式的圖片做壓縮處理,降低圖片色彩位數(shù)等。
4.避免重復(fù)功能的庫(kù),使用 WebP圖片格式等。
5.插件化。比如功能模塊放在服務(wù)器上,按需下載,可以減少安裝包大小。

6.OKhttp使用、有哪些操作,原理和源碼詳解
網(wǎng)絡(luò)請(qǐng)求的框架用于代替HttpurlConnection和httpclient。可以用來(lái)文件上傳,下載,加載圖片,網(wǎng)絡(luò)請(qǐng)求,是根據(jù)build模式(將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離),鏈?zhǔn)秸{(diào)用,每一個(gè)方法的返回值類型都是當(dāng)前類的對(duì)象
優(yōu)點(diǎn)是:
1.支持同步、異步。
2.緩存響應(yīng)數(shù)據(jù)(減少了重復(fù)的網(wǎng)絡(luò)請(qǐng)求)
3.自動(dòng)重連(底層是Socket,有自動(dòng)維護(hù)的socket連接池,減少了握手次數(shù))
使用:
先用一個(gè)構(gòu)造好的OkHttpClient和Request獲取到一個(gè)Call,然后執(zhí)行call的異步或者同步方法取得Response或者處理異常。
五大攔截器:
一、RetryAndFollowUpInterceptor (重定向攔截器)
1.創(chuàng)建 StreamAllocation對(duì)socket進(jìn)行管理,比如連接復(fù)用,選擇連接自動(dòng)重連等
2.根據(jù)響應(yīng)碼做重定向和重試,重定向時(shí)如果地址不一致會(huì)釋放連接,多重定向?yàn)?0次,超出拋異常
二、BridgeInterceptor (橋接攔截器)
用來(lái)連接用戶請(qǐng)求信息 和 HTTP 請(qǐng)求
BridgeInterceptor 在請(qǐng)求階段,補(bǔ)全http header,
在響應(yīng)階段保存
Cookie
三、CacheInterceptor (緩存攔截器)
在緩存可用的情況下,讀取本地的緩存的數(shù)據(jù),如果沒(méi)有直接去服務(wù)器讀取數(shù)據(jù),如果有,首先先判斷是否有緩存策略,然后判斷是否過(guò)期,如果沒(méi)有過(guò)期,直接從緩存中讀,如果過(guò)期了,你需要添加一些之前的頭部信息
注意事項(xiàng):
只支持GET方式,并且需要服務(wù)器配合,通過(guò)header相關(guān)的頭來(lái)控制緩存
創(chuàng)建OkhttpClient時(shí)候需要配置Cache
四、ConnectInterceptor (連接攔截器)
主要作用是打開(kāi)了與服務(wù)器的鏈接,正式開(kāi)啟了網(wǎng)絡(luò)請(qǐng)求。對(duì)socket封裝,判斷連接是否可以重用,除了比較連接當(dāng)前的host,也可以比較路由信息。最多空閑連接為5,最長(zhǎng)空閑時(shí)間為五分鐘
五、CallServerInterceptor(讀寫攔截器)
給服務(wù)器寫數(shù)據(jù)和讀取數(shù)據(jù);
寫頭部信息,寫body表單信息等等;
它負(fù)責(zé)實(shí)現(xiàn)網(wǎng)絡(luò) IO,所有攔截器都要依賴它才能拿到響應(yīng)數(shù)據(jù)。

7.Retrofit使用,常用注解、動(dòng)態(tài)代理以及原理
什么是Retrofit?
Retrofit 是一個(gè)Square開(kāi)發(fā)的安卓客戶端請(qǐng)求庫(kù)。其中內(nèi)部封裝了okhttp庫(kù)。Retrofit使用注解,能夠極大的簡(jiǎn)化網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)的代碼。
Retrofit常用注解:
@Query,@QueryMap,@Field,@FieldMap, @FormUrlEncoded,@Path,@Url

@Query,@QueryMap
@Query主要用于Get請(qǐng)求數(shù)據(jù),用于拼接在Url路徑后面的查詢參數(shù),多個(gè)參數(shù)中間用,隔開(kāi)。
@QueryMap:主要的效果等同于多個(gè)@Query參數(shù)拼接,主要也用于Get請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)。
@Field,@FieldMap
@Field的用法類似于@Query,主要不同的是@Field主要用于Post請(qǐng)求數(shù)據(jù)。@FieldMap的用法類似于@QueryMap。
兩者主要區(qū)別是:如果請(qǐng)求為post實(shí)現(xiàn),那么最好傳遞參數(shù)時(shí)使用@Field、@FieldMap和@FormUrlEncoded。因?yàn)锧Query和或QueryMap都是將參數(shù)拼接在url后面的,而@Field或@FieldMap傳遞的參數(shù)時(shí)放在請(qǐng)求體的。
@FormUrlEncoded
如果是Post請(qǐng)求的話,必須加@FromUrlEncoded注解。
@Path
@Path主要用于Get請(qǐng)求,用于替換Url路徑中的變量字符
@Url
@Url是動(dòng)態(tài)的Url請(qǐng)求數(shù)據(jù)的注解。
retrofit有幾個(gè)關(guān)鍵的地方.(原理)
1.用戶自定義的接口和接口方法.由動(dòng)態(tài)代理創(chuàng)建對(duì)象.
2.converter轉(zhuǎn)換器.把response轉(zhuǎn)換為一個(gè)具體的對(duì)象
3.注解的使用.
Retrofit中的動(dòng)態(tài)代理 :
也就是一個(gè)網(wǎng)絡(luò)調(diào)用,你只需要在你創(chuàng)建的接口里面通過(guò)注解進(jìn)行設(shè)置,然后通過(guò)retrofit創(chuàng)建一個(gè)api然后調(diào)用,就可以自動(dòng)完成一個(gè)Okhttp的Call的創(chuàng)建。
8.RxJava使用,可以實(shí)現(xiàn)哪些操作以及常用操作符
RxJava將鏈?zhǔn)骄幊毯彤惒浇Y(jié)合在一起,采用觀察者模式,和響應(yīng)式編程來(lái)實(shí)現(xiàn)。RxJava 的異步可以隨著程序邏輯變得越來(lái)越復(fù)雜,它依然能夠保持簡(jiǎn)潔。
RxJava 有四個(gè)基本概念:Observable (被觀察者)、 Observer (觀察者)、 subscribe (訂閱)、事件。
Observable 和 Observer 通過(guò) subscribe() 方法實(shí)現(xiàn)訂閱關(guān)系,從而 Observable 可以在需要的時(shí)候發(fā)出事件來(lái)通知 Observer。RxJava 的事件回調(diào)方法除了普通事件 onNext() 之外,還定義了兩個(gè)特殊的事件:onCompleted() 和 onError()。
總結(jié):

  1. 只有當(dāng)Observable被訂閱了subscriber)方法才會(huì)被執(zhí)行
  2. onCompleted方法里會(huì)把Subscription取消訂閱(unsubscribe)
  3. 如果調(diào)用了void onError(Throwable e)方法,那么onNext和onCompleted都不會(huì)執(zhí)行。會(huì)在onError調(diào)用之前,把Subscription取消注冊(cè)。
  4. 整個(gè)事件流不管是正常結(jié)束(onComplete)還是出現(xiàn)了異常(onError),Subscription都會(huì)被取消注冊(cè)(unsubscribe)。
    但是,由于我們可能執(zhí)行一些耗時(shí)操作,界面又被關(guān)閉了,所以還需要把subscription取消注冊(cè)
    創(chuàng)建操作
    用于創(chuàng)建Observable(被觀察者)的操作符
    ?Create(創(chuàng)建) — 通過(guò)調(diào)用觀察者(observer)的方法從頭開(kāi)始創(chuàng)建一個(gè)Observable
    ?Just(僅僅) — 將一個(gè)對(duì)象或者一組對(duì)象轉(zhuǎn)換為一個(gè)會(huì)發(fā)出該對(duì)象或那些對(duì)象的Observable
    ?Start(開(kāi)始) — 創(chuàng)建一個(gè)發(fā)出函數(shù)的返回值的Observable
    ?Timer(定時(shí)器) — 創(chuàng)建在一個(gè)指定的延遲之后發(fā)出單個(gè)數(shù)據(jù)項(xiàng)的Observable
    變換操作
    用于對(duì)Observable發(fā)出的數(shù)據(jù)進(jìn)行變換的操作符
    ?FlatMap(扁平映射) — 將Observable發(fā)出的數(shù)據(jù)變換為Observables集合,然后將這些 Observable發(fā)出的數(shù)據(jù)平坦化的放進(jìn)一個(gè)單獨(dú)的Observable,可以認(rèn)為是一個(gè)將嵌套的數(shù)據(jù)結(jié)構(gòu)展開(kāi)的過(guò)程
    ?Map(映射) — 通過(guò)對(duì)序列的每一項(xiàng)都應(yīng)用一個(gè)函數(shù)變換Observable發(fā)出的數(shù)據(jù),實(shí)質(zhì)是對(duì)序列中的每一項(xiàng)執(zhí)行一個(gè)函數(shù),函數(shù)的參數(shù)就是這個(gè)數(shù)據(jù)項(xiàng)
    過(guò)濾操作
    用于從Observable發(fā)射的數(shù)據(jù)中選擇性的過(guò)濾一些數(shù)據(jù)的操作符
    ?Distinct(去重) — 抑制Observable發(fā)出的重復(fù)數(shù)據(jù)
    ?First(首選) — 只從Observable發(fā)出第一個(gè)數(shù)據(jù)項(xiàng)滿足條件的第一個(gè)數(shù)據(jù)項(xiàng)
    ?Last(末項(xiàng)) — 只發(fā)出Observable發(fā)出最后一條數(shù)據(jù)
    組合操作
    用于將多個(gè)Observable組合成一個(gè)單一的Observable的操作符
    ?Join - 當(dāng)在根據(jù)由另一Observable發(fā)射的項(xiàng)目定義的時(shí)間窗期間發(fā)出來(lái)自一個(gè)Observable的項(xiàng)目時(shí),就將兩個(gè)Observable發(fā)射的數(shù)據(jù)組合成一個(gè)并發(fā)射
    ?Merge(合并) - 將多個(gè)Observable發(fā)射的數(shù)據(jù)組合并成一個(gè)
    ?Zip - 通過(guò)指定的函數(shù)將多個(gè)Observable的發(fā)射組合在一起,并根據(jù)此函數(shù)的結(jié)果為每個(gè)組合發(fā)出單個(gè)數(shù)據(jù)項(xiàng)
    錯(cuò)誤處理操作
    有助于從Observable的錯(cuò)誤通知中恢復(fù)的操作符
    ?Catch(捕獲) — 繼續(xù)序列操作,將錯(cuò)誤替換為正常的數(shù)據(jù),從onError通知中恢復(fù)
    ?Retry(重試) — 如果Observable發(fā)射了一個(gè)onError通知,重新訂閱它,希望它將完成并沒(méi)有錯(cuò)誤
    輔助操作
    用于處理Observable的操作符
    ?Delay — 延遲一段時(shí)間發(fā)射結(jié)果數(shù)據(jù)
    ?ObserveOn(觀察在) — 指定Observer觀察Observable的調(diào)度器(Scheduler)(工作線程)
    ?Serialize(序列化) — 強(qiáng)制Observable按次序發(fā)射數(shù)據(jù)并且功能是有效的
    ?Subscribe(訂閱) — 收到Observable發(fā)射的數(shù)據(jù)和通知后執(zhí)行的操作
    ?SubscribeOn(訂閱在) — 指定Observable應(yīng)該在哪個(gè)調(diào)度器上執(zhí)行
    ?Timeout(超時(shí)) — 如果過(guò)了指定的一段時(shí)間沒(méi)有發(fā)射數(shù)據(jù),則發(fā)射錯(cuò)誤通知
    背壓操作
    ?backpressure operators - 為了應(yīng)對(duì)觀察者消費(fèi)事件比被觀察者生產(chǎn)事件更快,所以需要背壓
    31、自定義View
    通常自定義view分為
    1.繼承現(xiàn)有控件,對(duì)其控件的功能進(jìn)行拓展。
    2.將現(xiàn)有控件進(jìn)行組合,實(shí)現(xiàn)功能更加強(qiáng)大控件。
    3.重寫View實(shí)現(xiàn)全新的控件
    一般當(dāng)我們遇到了原生控件無(wú)法滿足我們現(xiàn)有的需求的時(shí)候,我們就可以創(chuàng)建一個(gè)全新的View來(lái)實(shí)現(xiàn)我們所需要的功能。創(chuàng)建一個(gè)全新View實(shí)現(xiàn)自定義控件,無(wú)非分成這么幾步:
    1.在OnMeasure()方法中,測(cè)量自定義控件的大小,使自定義控件能夠自適應(yīng)布局各種各樣的需求。
    將 MeasureSpec 經(jīng)過(guò)自身處理后, 分發(fā)到下層子 View
    View 測(cè)量流程是父 View 先測(cè)量子 View,等子 View 測(cè)量完了,再來(lái)測(cè)量自己。在ViewGroup 測(cè)量子 View 的入口就是 measureChildWithMargins
    子 View 確定了大小之后, 再回到父容器中
    父容器結(jié)合子 View 大小和 自身布局特性 來(lái)確定自己的大小, 一直回到頂層
    2.draw過(guò)程
    3.1,背景繪制
    4.2,對(duì)View的內(nèi)容進(jìn)行繪制
    5.3,對(duì)當(dāng)前View的所有子View進(jìn)行繪制
    6.4,對(duì)View的滾動(dòng)條進(jìn)行繪制

7.在OnDraw()方法中,利用Canvas(畫(huà)布)與Paint(畫(huà)筆)來(lái)繪制要顯示的內(nèi)容。
8.在OnLayout()方法中來(lái)確定控件顯示位置。
measure() 方法中我們已經(jīng)測(cè)量出View的大小,根據(jù)這些大小,我們接下來(lái)就需要確定 View 在父 View 的位置進(jìn)行排版布局,這就是layout 作用。
對(duì) View 進(jìn)行排版布局,還是要看父 View,也就是 ViewGroup。

10.在OnTouchEvent()方法處理控件的觸摸事件。
進(jìn)程間通信:
一、使用 Intent
1.Activity,Service,Receiver 都支持在 Intent 中傳遞 Bundle 數(shù)據(jù),而 Bundle 實(shí)現(xiàn)了 Parcelable 接口,可以在不同的進(jìn)程間進(jìn)行傳輸。
2.在一個(gè)進(jìn)程中啟動(dòng)了另一個(gè)進(jìn)程的 Activity,Service 和 Receiver ,可以在 Bundle 中附加要傳遞的數(shù)據(jù)通過(guò) Intent 發(fā)送出去。
二、使用文件共享
1.Windows 上,一個(gè)文件如果被加了排斥鎖會(huì)導(dǎo)致其他線程無(wú)法對(duì)其進(jìn)行訪問(wèn),包括讀和寫;而 Android 系統(tǒng)基于 Linux ,使得其并發(fā)讀取文件沒(méi)有限制地進(jìn)行,甚至允許兩個(gè)線程同時(shí)對(duì)一個(gè)文件進(jìn)行讀寫操作,盡管這樣可能會(huì)出問(wèn)題。
2.可以在一個(gè)進(jìn)程中序列化一個(gè)對(duì)象到文件系統(tǒng)中,在另一個(gè)進(jìn)程中反序列化恢復(fù)這個(gè)對(duì)象(注意:并不是同一個(gè)對(duì)象,只是內(nèi)容相同。)。
3.SharedPreferences 是個(gè)特例,系統(tǒng)對(duì)它的讀 / 寫有一定的緩存策略,即內(nèi)存中會(huì)有一份 ShardPreferences 文件的緩存,系統(tǒng)對(duì)他的讀 / 寫就變得不可靠,當(dāng)面對(duì)高并發(fā)的讀寫訪問(wèn),SharedPreferences 有很多大的幾率丟失數(shù)據(jù)。因此,IPC 不建議采用 SharedPreferences。
三、使用 Messenger
Messenger 是一種輕量級(jí)的 IPC 方案,它的底層實(shí)現(xiàn)是 AIDL ,可以在不同進(jìn)程中傳遞 Message 對(duì)象,它一次只處理一個(gè)請(qǐng)求,在服務(wù)端不需要考慮線程同步的問(wèn)題,服務(wù)端不存在并發(fā)執(zhí)行的情形
?服務(wù)端進(jìn)程:服務(wù)端創(chuàng)建一個(gè) Service 來(lái)處理客戶端請(qǐng)求,同時(shí)通過(guò)一個(gè) Handler 對(duì)象來(lái)實(shí)例化一個(gè) Messenger 對(duì)象,然后在 Service 的 onBind 中返回這個(gè) Messenger 對(duì)象底層的 Binder 即可。
?客戶端進(jìn)程:首先綁定服務(wù)端 Service ,綁定成功之后用服務(wù)端的 IBinder 對(duì)象創(chuàng)建一個(gè) Messenger ,通過(guò)這個(gè) Messenger 就可以向服務(wù)端發(fā)送消息了,消息類型是 Message 。如果需要服務(wù)端響應(yīng),則需要?jiǎng)?chuàng)建一個(gè) Handler 并通過(guò)它來(lái)創(chuàng)建一個(gè) Messenger(和服務(wù)端一樣),并通過(guò) Message 的 replyTo 參數(shù)傳遞給服務(wù)端。服務(wù)端通過(guò) Message 的 replyTo 參數(shù)就可以回應(yīng)客戶端了。
四、使用 AIDL
Messenger 是以串行的方式處理客戶端發(fā)來(lái)的消息,如果大量消息同時(shí)發(fā)送到服務(wù)端,服務(wù)端只能一個(gè)一個(gè)處理,所以大量并發(fā)請(qǐng)求就不適合用 Messenger ,而且 Messenger 只適合傳遞消息,不能跨進(jìn)程調(diào)用服務(wù)端的方法。AIDL 可以解決并發(fā)和跨進(jìn)程調(diào)用方法的問(wèn)題,要知道 Messenger 本質(zhì)上也是 AIDL ,只不過(guò)系統(tǒng)做了封裝方便上層的調(diào)用而已。
五、使用 ContentProvider
用于不同應(yīng)用間數(shù)據(jù)共享,和 Messenger 底層實(shí)現(xiàn)同樣是 Binder 和 AIDL,系統(tǒng)做了封裝,使用簡(jiǎn)單。 系統(tǒng)預(yù)置了許多 ContentProvider ,如通訊錄、日程表,需要跨進(jìn)程訪問(wèn)。 使用方法:繼承 ContentProvider 類實(shí)現(xiàn) 6 個(gè)抽象方法,這六個(gè)方法均運(yùn)行在 ContentProvider 進(jìn)程中,除 onCreate 運(yùn)行在主線程里,其他五個(gè)方法均由外界回調(diào)運(yùn)行在 Binder 線程池中。
ContentProvider 的底層數(shù)據(jù),可以是 SQLite 數(shù)據(jù)庫(kù),可以是文件,也可以是內(nèi)存中的數(shù)據(jù)。
六、使用 Socket
Socket起源于 Unix,而 Unix 基本哲學(xué)之一就是“一切皆文件”,都可以用“打開(kāi) open –讀寫 write/read –關(guān)閉 close ”模式來(lái)操作。Socket 就是該模式的一個(gè)實(shí)現(xiàn),網(wǎng)絡(luò)的 Socket 數(shù)據(jù)傳輸是一種特殊的 I/O,Socket 也是一種文件描述符。Socket 也具有一個(gè)類似于打開(kāi)文件的函數(shù)調(diào)用: Socket(),該函數(shù)返回一個(gè)整型的Socket 描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^(guò)該 Socket 實(shí)現(xiàn)的。
常用的 Socket 類型有兩種:流式 Socket(SOCK_STREAM)和數(shù)據(jù)報(bào)式 Socket(SOCK_DGRAM)。流式是一種面向連接的 Socket,針對(duì)于面向連接的 TCP 服務(wù)應(yīng)用;數(shù)據(jù)報(bào)式 Socket 是一種無(wú)連接的 Socket ,對(duì)應(yīng)于無(wú)連接的 UDP 服務(wù)應(yīng)用。
Srvice:
Service是四大組件之一,它可以在后臺(tái)執(zhí)行長(zhǎng)時(shí)間運(yùn)行操作而沒(méi)有用戶界面的應(yīng)用組件
兩種啟動(dòng)方式和特點(diǎn):
startService特點(diǎn):
1.使用這種start方式啟動(dòng)的Service的生命周期如下:onCreate()--->onStartCommand()---> onDestroy()
2.如果服務(wù)已經(jīng)開(kāi)啟,不會(huì)重復(fù)的執(zhí)行onCreate(), 而是會(huì)調(diào)用onStart()和onStartCommand()
3.一旦服務(wù)開(kāi)啟跟調(diào)用者(開(kāi)啟者)就沒(méi)有任何關(guān)系了。
4.開(kāi)啟者退出了,開(kāi)啟者掛了,服務(wù)還在后臺(tái)長(zhǎng)期的運(yùn)行。
5.開(kāi)啟者不能調(diào)用服務(wù)里面的方法。
bindService特點(diǎn):
1.使用這種start方式啟動(dòng)的Service的生命周期如下:onCreate() --->onBind()--->onUnbind()--->onDestroy()
2.綁定服務(wù)不會(huì)調(diào)用onStart()或者onStartCommand()方法
3.bind的方式開(kāi)啟服務(wù),綁定服務(wù)。調(diào)用者調(diào)用unbindService解除綁定,服務(wù)也會(huì)跟著銷毀。
4.綁定者可以調(diào)用服務(wù)里面的方法
IntentService是什么。。通常用來(lái)離線下載
?重點(diǎn)(本質(zhì)上也是為了節(jié)省資源)
?IntentService是繼承自Service并處理異步請(qǐng)求的一個(gè)類,其內(nèi)部采用HandlerThread和Handler實(shí)現(xiàn)的,在IntentService內(nèi)有一個(gè)工作線程來(lái)處理耗時(shí)操作,其優(yōu)先級(jí)比普通Service高
?當(dāng)任務(wù)完成后,IntentService會(huì)自動(dòng)停止,而不需要手動(dòng)調(diào)用stopSelf()
?可以多次啟動(dòng)IntentService,每個(gè)耗時(shí)操作都會(huì)以工作隊(duì)列的方式在IntentService中onHandlerIntent()回調(diào)方法中執(zhí)行,并且每次只會(huì)執(zhí)行一個(gè)工作線程

  1. IntentService使用方法
    1.創(chuàng)建Service繼承自IntentService
    2.覆寫構(gòu)造方法和onHandlerIntent()方法
    3.在onHandlerIntent()中執(zhí)行耗時(shí)操作
    3.IntentService工作原理
    1.IntentService繼承自Service,內(nèi)部有一個(gè)HandlerThread對(duì)象
    2.在onCreate的時(shí)候會(huì)創(chuàng)建一個(gè)HandlerThread對(duì)象,并啟動(dòng)線程
    3.緊接著創(chuàng)建ServiceHandler對(duì)象,ServiceHandler繼承自Handler,用來(lái)處理消息。ServiceHandler將獲取HandlerThread的Looper就可以開(kāi)始正常工作了
    Service保活
    1 onStartCommand方法,返回START_STICKY
    在運(yùn)行onStartCommand后service進(jìn)程被殺死后,那將保留在開(kāi)始狀態(tài),但不會(huì)保留那些傳入的intent。不久后service就會(huì)再次嘗試重新創(chuàng)建,因?yàn)楸A粼陂_(kāi)始狀態(tài),在創(chuàng)建 service后將保證調(diào)用onstartCommand。如果沒(méi)有傳遞任何開(kāi)始命令給service,那獲取到的Intent為null。手動(dòng)返回START_STICKY,親測(cè)當(dāng)service因內(nèi)存不足被kill,當(dāng)內(nèi)存又有的時(shí)候,service又被重新創(chuàng)建,但是不能保證任何情況下都被重建,比如進(jìn)程被干掉了….
    2 提升Service優(yōu)先級(jí)
    在AndroidManifest.xml文件中對(duì)于intent-filter可以通過(guò)android:priority = “1000”這個(gè)屬性設(shè)置最高優(yōu)先級(jí),1000是最高值,如果數(shù)字越小則優(yōu)先級(jí)越低,同時(shí)適用于廣播。
    3 提升Service進(jìn)程優(yōu)先級(jí)
    Android中將進(jìn)程分成6個(gè)等級(jí),由高到低分別是:前臺(tái)進(jìn)程、可視進(jìn)程、次要服務(wù)進(jìn)程、后臺(tái)進(jìn)程、內(nèi)容供應(yīng)節(jié)點(diǎn)以及空進(jìn)程。當(dāng)系統(tǒng)進(jìn)程空間緊張時(shí),會(huì)按照優(yōu)先級(jí)自動(dòng)進(jìn)行進(jìn)程回收??梢允褂胹tartForeground()將服務(wù)設(shè)置為前臺(tái)進(jìn)程
    4 在onDestory中重啟Service
    直接在onDestroy()里startService或service +broadcast 方式,就是當(dāng)service走ondestory的時(shí)候,發(fā)送一個(gè)自定義的廣播,當(dāng)收到廣播的時(shí)候,重新啟動(dòng)service。
    5 監(jiān)聽(tīng)系統(tǒng)廣播判斷Service狀態(tài)
    通過(guò)系統(tǒng)的一些廣播,比如:手機(jī)重啟、界面喚醒、應(yīng)用狀態(tài)改變等等監(jiān)聽(tīng)并捕獲到,然后判斷我們的Service是否還存活,但要記得加權(quán)限。
    9.Glide
    glide默認(rèn)使用httpurlcolltion加載圖片,還可以修改為okhttp3或Volley來(lái)進(jìn)行加載圖片
    1、glide怎么獲取圖片寬高,獲取屏幕寬高的幾種方案:
    1.可以直接獲取到尺寸,當(dāng)xml文件里寫固定值,可以直接獲取。還有就是布局已經(jīng)繪制完成,通過(guò)view可以獲取,如果是wrap_content就通過(guò) override() 指定其他固定尺寸,并使用屏幕尺寸為該請(qǐng)求尺寸
    2.布局沒(méi)有繪制完成,通過(guò)調(diào)用onPreDrawListener監(jiān)聽(tīng)實(shí)現(xiàn)獲取寬高
    2.綁定生命周期分為五種類型1、content2、Activity3、FragmentActivity4、Fragment5、View
    原理:通過(guò)獲取 Activity 的FragmentManager,綁定一個(gè)空RequestManagerFragment,用來(lái)綁定空的Fragment然后在RequestManagerFragment 中初始化RequestManager,并注冊(cè)至LifecycleListener
    當(dāng)Activity 觸發(fā)生命周期時(shí),回調(diào) Fragment,并傳至LifecycleListener,LifecycleListener會(huì)回調(diào)所有向其注冊(cè)過(guò)的RequestManager
    Glide和Picasso比較:
    1.Picasso和Glide的withi后面的參數(shù)不同
    Picasso.with(這里只能傳入上下文) .
    Glide.with,后面可以傳入上下文,activity實(shí)例,FragmentActivity實(shí)例,Fragement.傳入的對(duì)象要比前者多.
    2.加載后圖片質(zhì)量不同
    Picasso采用的ARGB-8888,
    Glide采用的是RGB-565 相對(duì)而言,
    Picasso加載的是全圖,圖片質(zhì)量和清晰對(duì)要比Glide的要高
    但是,因?yàn)榧虞d的采樣率過(guò)高,導(dǎo)致,出現(xiàn)OOM異常的概率要比Glide要大很多.
    3.加載Gif圖片(備注:Gif圖片消耗太對(duì)內(nèi)存,盡量謹(jǐn)慎使用):
    Picasso不能加載git圖片
    Glide可以加載緩存圖片
    4.緩存策略和加載速度.
    Picasso緩存的是全尺寸
    Glide的緩存的跟ImageView的尺寸相同.
    講ImageView調(diào)整為不同的大小,不管大小如何設(shè)置,
    Glide則不同,他會(huì)為每種大小不一致的ImageView都緩存一次.Glide的這個(gè)特點(diǎn),讓加載顯得特別的快,
    Picasso只緩存一個(gè)全尺寸的,Picasso則因?yàn)樾枰陲@示之前重新調(diào)整大小而導(dǎo)致一些延遲,(即便是添加了noFade)
    5.總結(jié):
    Glide比Picasso加載速度要快,其實(shí)他是在Picasso的基礎(chǔ)上進(jìn)行了第二次封裝,
    Glide比Picasso需要更多的空間來(lái)緩存;
    Glide加載圖像以及磁盤緩存的方式,都優(yōu)于Picasso,且Glide更有利于減少OutOfMemoryError的發(fā)生;
    Gif動(dòng)畫(huà),是Glide的殺手锏.
    3.Glide線程池
    1.磁盤緩存線程池
    2.核心處理線程池
    3.動(dòng)畫(huà)線程池
    10、MVC,MVP,MVVM 的區(qū)別
    MVC:
    moduel對(duì)數(shù)據(jù)進(jìn)行處理,將數(shù)據(jù)給view展示
    View用戶界面,給controller傳送要顯示的頁(yè)面
    Controller:控制器,對(duì)邏輯做處理,讓moduel改變狀態(tài)
    特點(diǎn):因?yàn)関iew可以訪問(wèn)moduel,所以要做一些邏輯,導(dǎo)致更改view比較困難,
    Controller代碼過(guò)多臃腫,職責(zé)不清晰,測(cè)試不方便(必須手動(dòng)點(diǎn)擊,使用自動(dòng)化的測(cè)試工具)所有的通信都是單向的
    MVP:
    View :是指顯示數(shù)據(jù)并且和用戶交互的層。
    Model :是數(shù)據(jù)源層。用來(lái)保存數(shù)據(jù),以及請(qǐng)求數(shù)據(jù)等。
    Presenter:是從Model中獲取數(shù)據(jù)并提供給View的層,Presenter還負(fù)責(zé)處理所有的邏輯
    優(yōu)點(diǎn):測(cè)試方便,m與v完全脫離,各部分通信都是雙向的,降低了耦合性,
    缺點(diǎn),接口過(guò)于頻繁,維護(hù)不方便
    MVVM:
    對(duì)MVP的改進(jìn)
    1將Presenter改名為ViewModuel
    并通過(guò)雙向的數(shù)據(jù)綁定來(lái)實(shí)現(xiàn)視圖和數(shù)據(jù)的交互。也就是說(shuō)只需要將數(shù)據(jù)和視圖綁定一次之后,那么之后當(dāng)數(shù)據(jù)發(fā)生改變時(shí)就會(huì)自動(dòng)的在UI上刷新而不需要我們自己進(jìn)行手動(dòng)刷新。在MVVM中,他盡可能的會(huì)簡(jiǎn)化數(shù)據(jù)流的走向,使其變得更加簡(jiǎn)潔明了。
    優(yōu)點(diǎn):可以使得數(shù)據(jù)流的走向更加的清晰明了,同時(shí)也簡(jiǎn)化了開(kāi)發(fā),數(shù)據(jù)和視圖只需要進(jìn)行一次綁定即可。
    11、AsyncTask
    基本概念及原理:
    異步任務(wù),它本質(zhì)上就是一個(gè)封裝了線程池和Handler的異步框架??梢詫?shí)現(xiàn)UI線程和后臺(tái)線程進(jìn)行通訊,后臺(tái)線程執(zhí)行異步任務(wù),并把結(jié)果返回給UI線程。
    利用AsyncTask,可以方便的實(shí)現(xiàn)異步任務(wù)處理,可以在子線程更新UI,封裝簡(jiǎn)化了異步操作,使用線程,線程池處理異步任務(wù),AsyncTask執(zhí)行任務(wù)時(shí),內(nèi)部會(huì)創(chuàng)建一個(gè)進(jìn)程作用域的線程池來(lái)管理要運(yùn)行的任務(wù),也就是說(shuō)當(dāng)你調(diào)用了AsyncTa sk.execute()后,AsyncTask會(huì)把任務(wù)交給線程池,由線程池來(lái)管理創(chuàng)建Thread和運(yùn)行Thread。
    為什么要做異步任務(wù):
    因?yàn)閍ndroid中只有主線程才可以對(duì)ui進(jìn)行操作,但是不可以做耗時(shí)操作,如果主線程做耗時(shí)操作,可能就會(huì)導(dǎo)致ANR,將耗時(shí)操作放到子線程去做,此時(shí)就可以用AsyncTask,既避免了Android中單線程,又避免了ANR.
    使用方法:
    構(gòu)建AsyncTask子類的泛型參數(shù):
    Params:啟動(dòng)任務(wù)時(shí)輸入的參數(shù)類型.
    Progress:后臺(tái)任務(wù)執(zhí)行中返回進(jìn)度值的類型.
    Result:后臺(tái)任務(wù)執(zhí)行完成后返回結(jié)果的類型.
    構(gòu)建AsyncTask子類的回調(diào)方法:
    doInBackground:必須重寫,異步執(zhí)行后臺(tái)線程要完成的任務(wù),耗時(shí)操作將在此方法中完成.
    onPreExecute:執(zhí)行后臺(tái)耗時(shí)操作前被調(diào)用,通常用于進(jìn)行初始化操作.
    onPostExecute:當(dāng)doInBackground方法完成后,系統(tǒng)將自動(dòng)調(diào)用此方法,并將doInBackground方法返回的值傳入此方法.通過(guò)此方法進(jìn)行UI的更新.
    onProgressUpdate:當(dāng)在doInBackground方法中調(diào)用publishProgress方法更新任務(wù)執(zhí)行進(jìn)度后,將調(diào)用此方法.通過(guò)此方法我們可以知曉任務(wù)的完成進(jìn)度.
    使用AsyncTask的注意事項(xiàng)
    ① 必須在UI線程中創(chuàng)建AsyncTask的實(shí)例.
    ② 只能在UI線程中調(diào)用AsyncTask的execute方法.
    ③ AsyncTask被重寫的四個(gè)方法是系統(tǒng)自動(dòng)調(diào)用的,不應(yīng)手動(dòng)調(diào)用.
    ④ 每個(gè)AsyncTask只能被執(zhí)行(execute方法)一次,多次執(zhí)行將會(huì)引發(fā)異常.
    ⑤ AsyncTask的四個(gè)方法,只有doInBackground方法是運(yùn)行在其他線程中,其他三個(gè)方法都運(yùn)行在UI線程中,也就說(shuō)其他三個(gè)方法都可以進(jìn)行UI的更新操作.
    12、Android 6.0、7.0、8.0、9.0各個(gè)版本的版本特性主要講解關(guān)于開(kāi)發(fā)方面
    6.0
    運(yùn)行時(shí)權(quán)限,首次使用要申請(qǐng)獲得權(quán)限
    低電耗模式和應(yīng)用待機(jī)模式,一段時(shí)間不用,會(huì)處于休眠狀態(tài)或待機(jī)模式
    取消支持http客戶端的支持,用HttpURLConnection,減少透明壓縮和響應(yīng)緩存等
    文本操作,選中之后可以對(duì)其操作
    WLAN和網(wǎng)絡(luò)連接變更
    對(duì)相機(jī)的服務(wù)有些改變
    USB連接,僅充電模式,要做其他操作,要獲取權(quán)限
    7.0
    多窗口支持,分屏功能
    增強(qiáng)通知功能,模板更新,消息傳遞樣式自定義,捆綁通知,快速通知等,
    配置文件指導(dǎo)的JIT/AOT編譯,對(duì)代碼進(jìn)行分析,讓它可以在應(yīng)用運(yùn)行時(shí)持續(xù)提升 Android 應(yīng)用的性能,提高應(yīng)用安裝和系統(tǒng)更新的速度,
    低電耗模式,即設(shè)備處于空閑狀態(tài)時(shí),通過(guò)推遲應(yīng)用的 CPU 和網(wǎng)絡(luò)活動(dòng)以實(shí)現(xiàn)省電目的的系統(tǒng)模式
    流量節(jié)省模式,
    夜間模式
    多語(yǔ)言區(qū)域支持,更多語(yǔ)言
    秘鑰認(rèn)證
    VR支持,可以讓用戶打造高質(zhì)量移動(dòng)VR體驗(yàn)
    新增FrameMetricsListener API 允許應(yīng)用檢測(cè)他的UI渲染性能
    8.0
    自動(dòng)填充框架
    Android 8.0 通過(guò)引入自動(dòng)填充框架,簡(jiǎn)化了登錄和信用卡表單之類表單的填寫工作。在用戶選擇接受自動(dòng)填充之后,新老應(yīng)用都可使用自動(dòng)填充框架。
    畫(huà)中畫(huà)模式
    Android 8.0 允許以畫(huà)中畫(huà) (PIP) 模式啟動(dòng)操作組件。PIP 是一種特殊的多窗口模式,最常用于視頻播放。而 Android 8.0 則讓該功能可進(jìn)一步用于其他 Android 設(shè)備。
    字體
    1提供從程序應(yīng)用請(qǐng)求字體,不不需要讓Apk去下載字體,減少APK大小
    2 XML 中的字體,允許您使用字體作為資源。
    自動(dòng)調(diào)整Textview的大小
    根據(jù) TextView 的大小自動(dòng)設(shè)置文本展開(kāi)或收縮的大小。更容易屏幕適配
    可以自適應(yīng)應(yīng)用圖標(biāo)
    提高WebView API增強(qiáng)應(yīng)用穩(wěn)定性和安全性
    統(tǒng)一的布局外邊距和內(nèi)邊距
    指針捕獲,例如游戲,遠(yuǎn)程桌面都收益與指針控制
    新的 StrictMode 檢測(cè)程序,幫助識(shí)別應(yīng)用可能出現(xiàn)的錯(cuò)誤
    自定義數(shù)據(jù)存儲(chǔ)
    WLAN 感知
    在具有相應(yīng) WLAN 感知硬件的設(shè)備上,應(yīng)用和附近設(shè)備可以通過(guò) WLAN 進(jìn)行搜索和通信,無(wú)需依賴互聯(lián)網(wǎng)接入點(diǎn)
    無(wú)障礙功能
    支持開(kāi)發(fā)者使用以下無(wú)障礙功能創(chuàng)建自己的無(wú)障礙服務(wù)。
    新增與電話相關(guān)的權(quán)限

9.0:
1.所有應(yīng)用都使用HTTPS,對(duì)所有應(yīng)用信息安全
2.多攝像頭支持,您可以通過(guò)兩個(gè)或更多物理攝像頭來(lái)同時(shí)訪問(wèn)多個(gè)視頻流。
3.顯示屏缺口支持
Android 9 支持最新的全面屏,其中包含為攝像頭和揚(yáng)聲器預(yù)留空間的屏幕缺口。 通過(guò) DisplayCutout 類可確定非功能區(qū)域的位置和形狀,這些區(qū)域不應(yīng)顯示內(nèi)容。 要確定這些屏幕缺口區(qū)域是否存在及其位置,請(qǐng)使用 getDisplayCutout() 函數(shù)。
4.動(dòng)畫(huà),用來(lái)繪制GIF和WebP動(dòng)畫(huà)圖像
5.HDR VP9視頻,HEIF圖像壓縮和MediaApi
6.對(duì)流量費(fèi)用敏感,如果網(wǎng)絡(luò)阻塞時(shí),會(huì)延遲較大的網(wǎng)絡(luò)請(qǐng)求
13、EventBus
EventBus簡(jiǎn)化了Android組件間的通信。有效的分離事件發(fā)送方和接收方(也就是解耦的意思),能避免復(fù)雜和容易出錯(cuò)的依賴性和生命周期問(wèn)題 。
三要素:
Event 事件。它可以是任意類型
Subscriber 事件訂閱者。3.0之后需要加上注解@subscribe(),并且指定線程模型,默認(rèn)是POSTING。3.0以前必須定義onEvent固定的那幾個(gè)方法
Publisher 事件的發(fā)布者??梢栽谌我饩€程發(fā)布事件,使用EventBus.getDefault()就可以得到一個(gè)EventBus對(duì)象,然后再調(diào)用post(Object)方法即可。

四種線程模式:
? POSTING (默認(rèn)) 事件處理的線程跟發(fā)布事件的線程在同一個(gè)線程。
? MAIN 表示事件處理函數(shù)的線程在主線程(UI)線程,因此在這里不能進(jìn)行耗時(shí)操作。
? BACKGROUND 表示事件處理函數(shù)的線程在后臺(tái)線程,因此不能進(jìn)行UI操作。
? ASYNC 表示無(wú)論事件發(fā)布的線程是哪一個(gè),事件處理函數(shù)始終會(huì)新建一個(gè)子線程運(yùn)行,同樣不能進(jìn)行UI操作。

粘性事件:黏性事件,就是指發(fā)送了該事件之后再訂閱者依然能夠接收到的事件。使用黏性事件的時(shí)候有兩個(gè)地方需要做些修改。一個(gè)是訂閱事件的地方,一個(gè)是發(fā)布事件的地方,即調(diào)用EventBus的postSticky方法來(lái)發(fā)布事件:
優(yōu)先級(jí):
priority它用來(lái)指定訂閱方法的優(yōu)先級(jí),是一個(gè)整數(shù)類型的值,默認(rèn)是0,值越大表示優(yōu)先級(jí)越大。在某個(gè)事件被發(fā)布出來(lái)的時(shí)候,優(yōu)先級(jí)較高的訂閱方法會(huì)首先接受到事件。
14、GreenDao
一對(duì)一
@ToOne
就是一個(gè)主鍵對(duì)應(yīng)一個(gè)值
一對(duì)多
@ToMany(referencedJoinProperty = "parentId")類似于約束外鍵。
比如一個(gè)老師有多個(gè)學(xué)生,要有一個(gè)主鍵,一個(gè)外鍵,根據(jù)外鍵去查看另外一張表,反過(guò)來(lái)就是多對(duì)一
多對(duì)多
@JoinEntity(entity = TeacherJoinStudentBean.class,sourceProperty = "tId",targetProperty ="sId")
比如多個(gè)老師有多個(gè)學(xué)生,這種情況需要另外一張表,用來(lái)存放老師和學(xué)生的id和自己的主鍵,直接查看這張表就可以。

實(shí)體注解:
@Entity 用于標(biāo)識(shí)這是一個(gè)需要Greendao幫我們生成代碼的bean
@Id 標(biāo)明主鍵,可以設(shè)置為是否自增,如果原來(lái)字段里就有id,那么就不需要設(shè)置 Long類型的Id,將Id改為不可自增就可以
@Transient表示這個(gè)字段不會(huì)再數(shù)據(jù)庫(kù)里面插入
@Index 通過(guò)這個(gè)字段建立索引
@Convert對(duì)不是基本類型進(jìn)行轉(zhuǎn)換

關(guān)鍵的幾個(gè)類:
DaoMaster:用于創(chuàng)建數(shù)據(jù)庫(kù)以及獲取DaoSession
DaoSession:用于獲取各個(gè)表對(duì)應(yīng)的Dao對(duì)象
各個(gè)表對(duì)應(yīng)的Dao:提供了對(duì)表進(jìn)行增刪改查的方法
對(duì)于每一個(gè)實(shí)體類,greenDao生成一個(gè)DAO,持有很多持久性的方法,例如 count, loadAll以及insertInTx。

greendao加密:
添加依賴,加密的方法是用了getEncryptedWritableDb,在得到DB并getSession時(shí)需要輸入密鑰。
在取數(shù)據(jù)時(shí)使用的session必須也是使用相同的密鑰new出來(lái)的,否則只能看到空數(shù)據(jù)。并且把加密后的本地文件拿出來(lái),也是看不到內(nèi)容的。

GreenDao升級(jí):greendao不支持?jǐn)?shù)據(jù)遷移
第一步:新建一個(gè)類,繼承DaoMaster.DevOpenHelper,重寫onUpgrade(Database db, int oldVersion, int newVersion)方法,在該方法中使用MigrationHelper進(jìn)行數(shù)據(jù)庫(kù)升級(jí)以及數(shù)據(jù)遷移。
然后使用MyOpenHelper替代DaoMaster.DevOpenHelper來(lái)進(jìn)行創(chuàng)建數(shù)據(jù)庫(kù)等操作
第二步:新增或者修改字段,新增的字段都會(huì)被賦予空值,將原來(lái)的getset方法刪除,重新build,最后修改版本號(hào)
29、熱修復(fù)
版本發(fā)布之后發(fā)現(xiàn)嚴(yán)重BUG,需要緊急動(dòng)態(tài)修復(fù)
小功能即時(shí)上線、下線,比如節(jié)日活動(dòng)

而熱修復(fù)的開(kāi)發(fā)流程顯得更加靈活,優(yōu)勢(shì)很多:
無(wú)需重新發(fā)版,實(shí)時(shí)高效熱修復(fù)
用戶無(wú)感知修復(fù)(甚至無(wú)需重啟應(yīng)用),無(wú)需下載新的應(yīng)用,代價(jià)小
修復(fù)成功率高,把損失降到最低

而熱修復(fù)的開(kāi)發(fā)流程顯得更加靈活,優(yōu)勢(shì)很多:
無(wú)需重新發(fā)版,實(shí)時(shí)高效熱修復(fù)
用戶無(wú)感知修復(fù)(甚至無(wú)需重啟應(yīng)用),無(wú)需下載新的應(yīng)用,代價(jià)小
修復(fù)成功率高,把損失降到最低

主流框架:
騰訊,生成dex文件,因?yàn)閐ex文件是以數(shù)組的形式出錯(cuò),他通過(guò)改變dex文件的順序,實(shí)現(xiàn)熱更新
2.阿里云,添加so庫(kù),利用C語(yǔ)言進(jìn)行一些算法,改變執(zhí)行順序

15、視頻上傳,下載,緩存,壓縮
視頻的壓縮上傳采用集成七牛短視頻,
16、描述Java中斷點(diǎn)續(xù)傳和多線程斷點(diǎn)續(xù)傳的詳細(xì)流程
多線程斷點(diǎn)續(xù)傳流程:
1、 HttpUrlConnection去請(qǐng)求服務(wù)器 獲得文件的長(zhǎng)度con.getContentLength()
2、 創(chuàng)建一個(gè)空的RandomAcessFile來(lái)接收,并且指定剛剛獲取的長(zhǎng)度setLength
3、開(kāi)啟N個(gè)線程 計(jì)算每個(gè)線程需要下載的長(zhǎng)度
4、獲取之前先去看看下載的進(jìn)度保存文件是否存在如果存在就從文件里獲取已經(jīng)下載的進(jìn)度
5、開(kāi)始文件下載
6、臨時(shí)文件的刪除 資源的關(guān)閉
單線程斷點(diǎn)續(xù)傳流程:
1)通過(guò)遠(yuǎn)程url和本地保存目錄開(kāi)始運(yùn)行
2)通過(guò)遠(yuǎn)程url獲取文件大小
3)通過(guò)本地臨時(shí)文件info和遠(yuǎn)程文件比較大小判斷是否有本地文件下載完畢
4)未下載完成的開(kāi)始斷點(diǎn)下載
5)完成后刪除臨時(shí)文件
30、js與Android交互
Android開(kāi)發(fā)過(guò)程中,我們或多或少都會(huì)用到webview,使用webview來(lái)展示一些經(jīng)常變動(dòng)的界面更加方便簡(jiǎn)單,
也已于維護(hù)。另一方面hybrid App開(kāi)發(fā)現(xiàn)在用的也越來(lái)越多了。其中native和h5之間的交互更是必不可少的。
常用的有web.load Url(“”);
Webview可以對(duì)html頁(yè)面通過(guò)指定的幾個(gè)方法做本地緩存,減少用戶流量,
要注意的問(wèn)題:
在WebView加載頁(yè)面的時(shí)候,會(huì)自動(dòng)開(kāi)啟線程去加載,如果不很好的關(guān)閉這些線程,就會(huì)導(dǎo)致電量消耗加大,可以采用暴力的方法,直接在onDestroy方法中System.exit(0)結(jié)束當(dāng)前正在運(yùn)行中的java虛擬機(jī)

17、單例模式、工廠模式、觀察者、適配器;
Builder模式
意圖:將一個(gè)復(fù)雜的構(gòu)建與其表示相分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。
何時(shí)使用:一些基本部件不會(huì)變,而其組合經(jīng)常變化的時(shí)候。
關(guān)鍵代碼:建造者:創(chuàng)建和提供實(shí)例,導(dǎo)演:管理建造出來(lái)的實(shí)例的依賴關(guān)系。

觀察者模式
發(fā)布訂閱模式,發(fā)布者發(fā)布信息,訂閱者獲取信息,訂閱了就能收到信息,沒(méi)訂閱就收不到信息
意圖:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。
何時(shí)使用:一個(gè)對(duì)象(目標(biāo)對(duì)象)的狀態(tài)發(fā)生改變,所有的依賴對(duì)象(觀察者對(duì)象)都將得到通知,進(jìn)行廣播通知。
如何解決:使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化。
工廠模式
意圖:定義一個(gè)創(chuàng)建對(duì)象的接口,讓其子類自己決定實(shí)例化哪一個(gè)工廠類,工廠模式使其創(chuàng)建過(guò)程延遲到子類進(jìn)行。
主要解決:主要解決接口選擇的問(wèn)題。
何時(shí)使用:我們明確地計(jì)劃不同條件下創(chuàng)建不同實(shí)例時(shí)。
關(guān)鍵代碼:創(chuàng)建過(guò)程在其子類執(zhí)行。

19.Activity一共有以下四種啟動(dòng)模式:
1.Standard(默認(rèn)的啟動(dòng)模式):每次啟動(dòng)一個(gè)Activity都會(huì)創(chuàng)建一個(gè)新的實(shí)例入棧,不管這個(gè)實(shí)例是否存在。
2.SingleTop(棧頂復(fù)用模式):當(dāng)一個(gè)singleTop模式的Activity已經(jīng)位于任務(wù)棧的棧頂,再去啟動(dòng)它時(shí),不會(huì)再創(chuàng)建新的實(shí)例,如果不位于棧頂,就會(huì)創(chuàng)建新的實(shí)例
3.SingTask(有彈棧的效果):在同一個(gè)Task中只有一個(gè)實(shí)例,如果在棧頂,系統(tǒng)不會(huì)創(chuàng)建新的Activity實(shí)例,如果不在棧頂,系統(tǒng)就把這個(gè)Activity移到棧頂,把他上面的Activity移出去

  1. SingleInstance(單例模式)SingTask是任務(wù)棧內(nèi)單例,SingleInstance則是Activity單例,會(huì)創(chuàng)建一個(gè)新的任務(wù)棧,這個(gè)任務(wù)棧只有一個(gè)Activity
    20、簡(jiǎn)述什么是泛型,泛型如何使用和項(xiàng)目中如何使用
    泛型的本質(zhì)是為了參數(shù)化類型(在不創(chuàng)建新的類型的情況下,通過(guò)泛型指定的不同類型來(lái)控制形參具體限制的類型)。也就是說(shuō)在泛型使用過(guò)程中,操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù),這種參數(shù)類型可以用在類、接口和方法中,分別被稱為泛型類、泛型接口、泛型方法。
    泛型如何使用
    泛型可以用到容器,方法,接口,內(nèi)部類,抽象類
    泛型的好處:
    增強(qiáng)程序的可讀性和穩(wěn)點(diǎn)性,在實(shí)際使用之前類型就已經(jīng)確定了,不需要強(qiáng)制類型轉(zhuǎn)換
    21.Java中線程的實(shí)現(xiàn)的幾種方式、和常用的方法、以及多線程安全問(wèn)題
    線程的三種方式:
    1)繼承Thread類創(chuàng)建線程
    2)實(shí)現(xiàn)Runnable接口創(chuàng)建線程
    3)使用Callable和Future創(chuàng)建線程
    常用方法:
    start() :?jiǎn)?dòng)線程,進(jìn)入就緒狀態(tài)
    run():都用來(lái)定義線程對(duì)象被調(diào)度之后所執(zhí)行的操作,都是系統(tǒng)自動(dòng)調(diào)用而用戶程序不得引用的方法。
    sleep(int millsecond): 優(yōu)先級(jí)高的線程可以在它的run()方法中調(diào)用sleep方法來(lái)使自己休眠一段時(shí)間。
    wait:調(diào)用該方法的線程進(jìn)入等待狀態(tài),需要注意的是調(diào)用wait()方法后,會(huì)釋放對(duì)象的鎖。
    多線程安全問(wèn)題:
    什么情況下會(huì)產(chǎn)生線程安全問(wèn)題?
    1,多個(gè)線程在操作共享的數(shù)據(jù)。 ? 2,操作共享數(shù)據(jù)的線程代碼有多條。
    解決思路:
    將多條操作共享數(shù)據(jù)的線程代碼封裝起來(lái),當(dāng)有線程在執(zhí)行這些代碼的時(shí)候,其他線程不可以參與運(yùn)算。
    當(dāng)前線程把這些代碼都執(zhí)行完畢后,其他線程才可以參與運(yùn)算。
    22.Java中線程池的實(shí)現(xiàn)的幾種方式和各自特點(diǎn)與使用場(chǎng)景
    實(shí)現(xiàn)方式
    線程池的實(shí)現(xiàn)方式是通過(guò)Executors類創(chuàng)建幾種不同類型的線程池
    四種線程池:
    newCacheThreadPool 創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程
    newFixedpool創(chuàng)建一個(gè)定長(zhǎng)線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待 newScheduledpool創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)和周期性任務(wù)執(zhí)行 ? newSingeThreadExecutor創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO,LIFO,優(yōu)先級(jí))執(zhí)行
    使用場(chǎng)景:
    單個(gè)任務(wù)處理時(shí)間短 ? 將需處理的任務(wù)數(shù)量大
    23、Java中數(shù)組、集合、鏈 表、隊(duì)列的數(shù)據(jù)結(jié)構(gòu)和優(yōu)缺點(diǎn)和他們之間的區(qū)別
    數(shù)組:
    長(zhǎng)度固定 ? 可以存儲(chǔ)基本類型,也可以存儲(chǔ)引用類型,存儲(chǔ)元素類型一致 ? 數(shù)組可以在內(nèi)存中連續(xù)存儲(chǔ)多個(gè)元素的構(gòu)造,在內(nèi)存中的分配也是連續(xù)的
    優(yōu)點(diǎn):有下標(biāo),查詢方便,增刪快
    缺點(diǎn): 數(shù)組的大小固定后就不能擴(kuò)容了 ? 數(shù)組只能存儲(chǔ)一種類型的數(shù)據(jù) ? 添加,刪除的操作慢,因?yàn)橐苿?dòng)其他的元素
    集合:
    長(zhǎng)度可變 ? 只可以存儲(chǔ)引用類型 ? 可以存儲(chǔ)多種類型
    List有序可重復(fù) ?
    ArrayList: 底層:數(shù)組(存儲(chǔ)空間連續(xù)) 增刪慢,查詢快 線程不安全,(不同步) 效率高 ?
    Vector: 底層:數(shù)組(存儲(chǔ)空間連續(xù)) 增刪慢,查詢快 線程安全,(同步) 效率低 ?
    LinkedList: 底層:鏈表(兩部分:值域,地址域) 增刪快,查詢慢 線程不安全,效率高
    Set無(wú)序不可重復(fù) ?
    HashSet 底層:哈希表(hashcode,equals) 線程不安全,效率高 ? LinkedHashSet 底層: 鏈表(保證有序) 哈希表(hashcode,equals) ? TreeSet 底層:紅黑樹(shù) (有序:1.自然排序 2.比較器排序)
    ? Hashtable:現(xiàn)在被HashSet取代,特點(diǎn),不能存null 線程安全,效率低
    Map 雙列集合 只針對(duì)鍵有效 Key,Value ?
    HashMap 底層:哈希表(hashcode,equals) 線程不安全,效率高(針對(duì)key) ?
    LinkedHashMap 底層: 鏈表(保證有序) 哈希表(hashcode,equals) ? TreeMap 底層:紅黑樹(shù) (有序:1.自然排序 2.比較器排序)
    鏈表:
    通過(guò)一個(gè)鏈子把多個(gè)結(jié)點(diǎn)(元素)連接起來(lái),由數(shù)據(jù)和地址組成的一個(gè)元素, ? 節(jié)點(diǎn)本身必須有一個(gè)地址值(就是下一個(gè)元素的地址值)
    優(yōu)點(diǎn):
    查找不方便,增刪快
    隊(duì)列:
    是一種先進(jìn)先出的數(shù)據(jù)構(gòu)造,也是運(yùn)算受限制的線性表,只可以在對(duì)頭刪除元素,在隊(duì)尾插入元素 ? 線性表是同一類型數(shù)據(jù)的一個(gè)有限序列 ? 元素之間的先后排列次序蘊(yùn)涵著其線性關(guān)系。
    24.簡(jiǎn)述Java中注解,并自定義注解。說(shuō)一下注解處理機(jī)制和使用場(chǎng)景
    什么是注解?
    Java注解也叫元數(shù)據(jù),是附加在代碼中的一些元信息,用于一些工具在編譯、運(yùn)行時(shí)進(jìn)行解析和使用,起到說(shuō)明、配置的功能。注解不會(huì)影響代碼的實(shí)際邏輯,僅僅起到輔助性的作用。
    它主要的作用有以下四方面:
    1,生成文檔,通過(guò)代碼里標(biāo)識(shí)的元數(shù)據(jù)生成javadoc文檔。
    2,編譯檢查,讓編譯器在編譯期間進(jìn)行檢查驗(yàn)證。
    3,編譯時(shí)動(dòng)態(tài)處理,例如動(dòng)態(tài)生成代碼。
    4,運(yùn)行時(shí)動(dòng)態(tài)處理,例如使用反射注入實(shí)例。
    自定義注解:
    自定義注解類編寫的一些規(guī)則:
  2. 參數(shù)成員只能用public或default這兩個(gè)訪問(wèn)權(quán)修飾
  3. 參數(shù)成員只能用八種基本數(shù)據(jù)類型和String、Enum、Class、annotations等數(shù)據(jù)類型,以及這一些類型的數(shù)組.
  4. 要獲取類方法和字段的注解信息,必須通過(guò)Java的反射技術(shù)來(lái)獲取
    25、描述Socket、Tcp和Udp,http、https區(qū)別,和使用方式和原理
    socket是對(duì)TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個(gè)調(diào)用接口(API),
    通過(guò)Socket,我們才能使用TCP/IP協(xié)議。
    TCP與UDP區(qū)別總結(jié):
    1、TCP面向連接
    UDP是無(wú)連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接
    2、TCP提供可靠的服務(wù)。也就是說(shuō),通過(guò)TCP連接傳送的數(shù)據(jù),無(wú)差錯(cuò),不丟失,不 重復(fù),且按序到達(dá);
    3、TCP面向字節(jié)流,實(shí)際上是TCP把數(shù)據(jù)看成一連串無(wú)結(jié)構(gòu)的字節(jié)流;
    UDP是面向報(bào)文的
    UDP沒(méi)有擁塞控制,因此網(wǎng)絡(luò)出現(xiàn)擁塞不會(huì)使源主機(jī)的發(fā)送速率降低
    4、每一條TCP連接只能是點(diǎn)到點(diǎn)的;UDP支持一對(duì)一,一對(duì)多,多對(duì)一和多對(duì)多的交互通信
    5、TCP首部開(kāi)銷20字節(jié);UDP的首部開(kāi)銷小,只有8個(gè)字節(jié)
    6、TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道
    HTTP與HTTPS的區(qū)別
    1、HTTPS協(xié)議需要到CA申請(qǐng)證書(shū),一般免費(fèi)證書(shū)很少,需要交費(fèi)。
    2、HTTP是超文本傳輸協(xié)議信息是明文傳輸,HTTPS則是具有安全性的ssl加密傳輸協(xié)議。
    3、HTTP和HTTPS使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
    4、HTTP的連接很簡(jiǎn)單,是無(wú)狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比HTTP協(xié)議安全。
    26、描述java中的垃圾回收機(jī)制以及內(nèi)部算法
    垃圾回收機(jī)制是Java提供的自動(dòng)釋放內(nèi)存空間的機(jī)制。 垃圾回收器(Garbage Collection,GC)是JVM自帶的一個(gè)線程,用于回收沒(méi)有被引用的對(duì)象,垃圾回收重點(diǎn)關(guān)注的是堆和方法區(qū)部分的內(nèi)存。
    java中常用的垃圾收集算法
    (1).標(biāo)記-清除算法:
    最基礎(chǔ)的垃圾收集算法,算法分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成之后統(tǒng)一回收掉所有被標(biāo)記的對(duì)象。
    (2).復(fù)制算法:
    將可用內(nèi)存按容量分成大小相等的兩塊,每次只使用其中一塊,當(dāng)這塊內(nèi)存使用完了,就將還存活的對(duì)象復(fù)制到另一塊內(nèi)存上去,然后把使用過(guò)的內(nèi)存空間一次清理掉。
    復(fù)制算法的缺點(diǎn)顯而易見(jiàn),可使用的內(nèi)存降為原來(lái)一半。
    (3).標(biāo)記-整理算法:
    標(biāo)記-整理算法在標(biāo)記-清除算法基礎(chǔ)上做了改進(jìn),標(biāo)記階段是相同的標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成之后不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),在移動(dòng)過(guò)程中清理掉可回收的對(duì)象,這個(gè)過(guò)程叫做整理。
    (4).分代收集算法:
    根據(jù)內(nèi)存中對(duì)象的存活周期不同,將內(nèi)存劃分為幾塊,java的虛擬機(jī)中一般把內(nèi)存劃分為新生代和年老代,當(dāng)新創(chuàng)建對(duì)象時(shí)一般在新生代中分配內(nèi)存空間,當(dāng)新生代垃圾收集器回收幾次之后仍然存活的對(duì)象會(huì)被移動(dòng)到年老代內(nèi)存中,當(dāng)大對(duì)象在新生代中無(wú)法找到足夠的連續(xù)內(nèi)存時(shí)也直接在年老代中創(chuàng)建。
    現(xiàn)在的Java虛擬機(jī)就聯(lián)合使用了分代復(fù)制、標(biāo)記-清除和標(biāo)記-整理算法,

27、簡(jiǎn)述什么是ANR、如何產(chǎn)生和解決
ANR定義:應(yīng)用程序無(wú)響應(yīng),會(huì)顯示一個(gè)對(duì)話框,這個(gè)對(duì)話框稱作應(yīng)用程序無(wú)響應(yīng)(ANR:Application Not Responding)對(duì)話框。用戶可以選擇“等待”而讓程序繼續(xù)運(yùn)行,也可以選擇“強(qiáng)制關(guān)閉”。
ANR產(chǎn)生原因
在多線程中做了非常耗時(shí)的操作,比如說(shuō)是下載,io異常等
潛在的耗時(shí)操作,例如網(wǎng)絡(luò)或數(shù)據(jù)庫(kù)操作,或者高耗時(shí)的計(jì)算如改變位圖尺寸,應(yīng)該在子線程里或者通過(guò)異步請(qǐng)求的方式來(lái)完成。
如何解決ANR
不在主線程做耗時(shí)操作,放在子線程中來(lái)實(shí)現(xiàn),采用Handler+mesage的方式,或者是有時(shí)候需要做一些和網(wǎng)絡(luò)相互交互的耗時(shí)操作就采用asyntask異步任務(wù)的方式等,在主線程中更新UI。
28、Android頁(yè)面恢復(fù)
32、圖片的三級(jí)緩存
當(dāng)App需要加載某一張圖片時(shí),先去手機(jī)內(nèi)存中去找該圖片,如果有,那么直接顯示,如果無(wú),則去手機(jī)sd卡或者手機(jī)外部存儲(chǔ)中找該圖片,如果有,那么直接顯示,如果無(wú),那么此時(shí)才去網(wǎng)絡(luò)下載該圖片。這種機(jī)制常稱為三級(jí)緩存策略。

內(nèi)存緩存以花費(fèi)寶貴的程序內(nèi)存為前提來(lái)快速訪問(wèn)位圖。
LruCache類(在API Level 4的Support Library中也可以找到)特別適合用來(lái)緩存Bitmaps,
它使用一個(gè)強(qiáng)引用(strong referenced)的LinkedHashMap保存最近引用的對(duì)象,并且在緩存超出設(shè)置大小的時(shí)候剔除(evict)最近最少使用到的對(duì)象。

  1. 即時(shí)通訊
    主流的框架就是環(huán)信。
    環(huán)信:流程:
    ?在線狀態(tài):客戶端A發(fā)送消息到環(huán)信服務(wù)器,環(huán)信服務(wù)器推送消息到客戶端B。
    ?離線狀態(tài):客戶端A發(fā)送消息到環(huán)信服務(wù)器,環(huán)信服務(wù)器檢測(cè)到客戶端B不在線,會(huì)添加到離線緩存中,當(dāng)客戶端B登錄后服務(wù)器會(huì)把離線消息推送給客戶端B。
    聊天記錄保存
    客戶端A發(fā)送消息到環(huán)信服務(wù)器的同時(shí),SDK 會(huì)保存這條消息到本地?cái)?shù)據(jù)庫(kù)(SDK 內(nèi)部創(chuàng)建數(shù)據(jù)庫(kù),不允許直接操作),環(huán)信服務(wù)器在推送消息到客戶端B的同時(shí)也會(huì)在服務(wù)器記錄下來(lái)(消息歷史記錄免費(fèi)存儲(chǔ)3天),客戶端B收到消息后,SDK 會(huì)將這條消息存儲(chǔ)到本地?cái)?shù)據(jù)庫(kù)。
    自動(dòng)連接:
    如果網(wǎng)絡(luò)不通過(guò),用戶應(yīng)該自動(dòng)連接到服務(wù)器,以及時(shí)接收消息
    此功能無(wú)需程序員自己做,環(huán)信框架已實(shí)現(xiàn),環(huán)信SDK會(huì)調(diào)用自動(dòng)連接的代理方法來(lái)通知應(yīng)用程序
    MChatManagerBuddyDelegate:
    上面的協(xié)議的實(shí)現(xiàn)了對(duì)用戶的基本操作,如
    (1)添加好友
    (2)從本地獲取好友列表
    (3)從服務(wù)器獲取最新好友列表
    (4)接收好友添加請(qǐng)求
    (5)刪除好友
    (6)被好友從名單上刪除
    是否使用過(guò)環(huán)信,簡(jiǎn)單的說(shuō)下環(huán)信的實(shí)現(xiàn)原理:
    環(huán)信是一個(gè)即時(shí)通信的服務(wù)提供商
    環(huán)信使用的是XMPP協(xié)議,它是再XMPP的基礎(chǔ)上進(jìn)行二次開(kāi)發(fā),對(duì)服務(wù)器Openfire和客戶端進(jìn)行功能模型的添加和客戶端SDK的封裝,環(huán)信的本質(zhì)還是使用XMPP,基本于Socket的網(wǎng)絡(luò)通信
    環(huán)信內(nèi)部實(shí)現(xiàn)了數(shù)據(jù)緩存,會(huì)把聊天記錄添加到數(shù)據(jù)庫(kù),把附件(如音頻文件,圖片文件)下載到本地,使程序員更多時(shí)間是花到用戶即時(shí)體驗(yàn)上
    環(huán)信內(nèi)部已經(jīng)實(shí)現(xiàn)了視頻,音頻,圖片,其它附件發(fā)送功能
    環(huán)信使用公司可以節(jié)約時(shí)間成本
    不需要公司內(nèi)部搭建服務(wù)器
    客戶端的開(kāi)發(fā),使用環(huán)信SDK比使用XMPPFramework更簡(jiǎn)潔方便
    35.支付流程
    支付寶支付流程:
    1.app攜帶支付信息調(diào)用支付接口請(qǐng)求支付寶客戶端調(diào)起支付界面;
    2.用戶操作,輸入密碼支付,支付成功;直接返回取消支付;出現(xiàn)錯(cuò)誤,支付失??;進(jìn)入支付界面,但輸入密碼支付,支付待確認(rèn);
    3.支付寶客戶端將支付結(jié)果告訴app客戶端,商戶服務(wù)器通知app服務(wù)器支付結(jié)果;
    4.app客戶端處理支付結(jié)果;
    5.app服務(wù)器處理支付結(jié)果。
    微信支付:
    流程解釋:
  2. 客戶端請(qǐng)求訂單
    2.認(rèn)證商戶,獲取access_token
    3、組裝生成預(yù)定單所需參數(shù)并簽名
    4、調(diào)用微信統(tǒng)一下單接口并傳遞參數(shù),得到預(yù)訂單號(hào)
    5、對(duì)得到的預(yù)定單參數(shù)再次簽名
    6、調(diào)起微信支付并驗(yàn)證參數(shù)有效性
    7、驗(yàn)證通過(guò),提示用戶輸入支付密碼
    8、提交支付,異步返回支付結(jié)果和訂單詳情
    9、客戶端同步跳轉(zhuǎn)頁(yè)面。
最后編輯于
?著作權(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)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,621評(píng)論 1 32
  • 所有知識(shí)點(diǎn)已整理成app app下載地址 J2EE 部分: 1.Switch能否用string做參數(shù)? 在 Jav...
    侯蛋蛋_閱讀 2,700評(píng)論 1 4
  • 1.設(shè)計(jì)模式是什么? 你知道哪些設(shè)計(jì)模式,并簡(jiǎn)要敘述?設(shè)計(jì)模式是一種編碼經(jīng)驗(yàn),就是用比較成熟的邏輯去處理某一種類型...
    龍飝閱讀 2,294評(píng)論 0 12
  • To 毒舌姐: 都說(shuō)“女人心,海底針”,但我怎么覺(jué)得男人心思也那么難猜呢? 家里準(zhǔn)備換個(gè)新鞋柜,我們就為買什么風(fēng)格...
    毒舌姐姐閱讀 537評(píng)論 0 3
  • 當(dāng)你說(shuō)錢時(shí),一些朋友就走遠(yuǎn)了。當(dāng)你缺錢時(shí),真正的朋友都來(lái)了。 2018下半年,再次來(lái)故事群。講我自己的故事給你們聽(tīng)...
    虛度老太婆閱讀 591評(píng)論 0 0

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